Android 安卓服务启动
我创建了Android 安卓服务启动,android,service,Android,Service,我创建了服务来下载电影并通知进度,当我开始下载并退出应用程序时,我发现了一个问题。我的服务创建新服务,而不破坏以前的服务 日志: CREATE // I press Download button Service Created START RUN CREATE // I exit from app and it creates new, without DESTROY START RUN START // I press to stop downloading
服务
来下载电影并通知进度,当我开始下载并退出应用程序时,我发现了一个问题。我的服务创建新服务,而不破坏以前的服务
日志:
CREATE // I press Download button Service Created
START
RUN
CREATE // I exit from app and it creates new, without DESTROY
START
RUN
START // I press to stop downloading
DESTROY
DownloadManager.java
public class DownloadManager extends Service{
private ExecutorService exec;
private int mb = 1024*1024;
private int Notifid;
private int progressPercent;
private String title;
private String url;
private boolean serviceWork = true;
private NotificationManager manager;
private NotificationCompat.Builder builder;
@Override
public void onCreate() {
super.onCreate();
exec = Executors.newFixedThreadPool(1);
builder = new NotificationCompat.Builder(getApplicationContext());
manager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
url = intent.getStringExtra(C.SERVICE_URL);
title = intent.getStringExtra(C.SERVICE_TITLE);
if(url.equals("cancel")){
stopSelf();
}
else {
Run run = new Run(url, title);
serviceWork = true;
exec.execute(run);
}
Notifid = 0x45;
return START_REDELIVER_INTENT;
}
@Override
public void onDestroy() {
if(url.equals("cancel")){
cancel();
}
serviceWork = false;
super.onDestroy();
}
void generateNotify(String msg1, String msg2){
builder.setAutoCancel(false);
builder.setOngoing(true);
builder.setContentTitle(msg1);
builder.setContentText(msg2);
builder.setSmallIcon(R.drawable.ic_launcher, 0);
builder.setTicker(msg1);
builder.setProgress(0, 0, true);
Intent intent = new Intent(this, DownloadManager.class);
intent.putExtra(C.SERVICE_URL, "cancel");
PendingIntent pending = PendingIntent.getService(this, 0, intent, 0);
builder.setContentIntent(pending);
manager.notify(Notifid, builder.build());
}
void progress(final int progress, final String msg){
new Thread(
new Runnable() {
@Override
public void run() {
builder.setProgress(100, progress, false);
builder.setContentText(msg);
manager.notify(Notifid, builder.build());
}
}
).start();
}
void ticker(String msg1){
builder.setTicker(msg1);
builder.setContentText(msg1);
manager.notify(Notifid, builder.build());
}
void cancel(){
manager.cancel(Notifid);
}
void cancable(){
builder.setOngoing(false);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("sdcard/Mover/"+title+".mp4"), "video/*");
PendingIntent pending = PendingIntent.getActivity(this, 0, intent, 0);
builder.setContentIntent(pending);
builder.setAutoCancel(true);
manager.notify(Notifid, builder.build());
}
class Run implements Runnable{
private String url;
private String title;
private int count;
private int fileLength;
public Run(String url, String title) {
this.url = url;
this.title = title;
}
@Override
public void run() {
try{
// Создаем подключение к ссылке.
URL openUrl = new URL(url);
URLConnection connection = openUrl.openConnection();
connection.connect();
// Проверяем наличие папки если отсуствует создаем.
File file = new File("sdcard/Mover/");
file.mkdirs();
// Размер файла
fileLength = connection.getContentLength();
// Загружаем конетнт
InputStream ips = new BufferedInputStream(openUrl.openStream());
OutputStream ops = new FileOutputStream("sdcard/Mover/"+title+".mp4");
// Показываем уведомление
DownloadManager.this.generateNotify(title, "Всего: " +format(fileLength));
byte[] data = new byte[1024];
int total = 0;
int last = 0;
int progress = 1;
int lasttotal = 0;
int speed = 0;
long current = System.currentTimeMillis();
// Читаем
while ((count = ips.read(data)) != -1) {
if(serviceWork){
ops.write(data, 0, count);
total += count;
long now = System.currentTimeMillis();
// Определяем скорость загрзки.
// Для этого делаем проверку на каждую секунду
if(now > current + 1000){
current = now;
speed = (total - lasttotal)/1024;
lasttotal = total;
}
progressPercent = (total*100)/fileLength;
if(last != progressPercent){
last = progressPercent;
progress++;
DownloadManager.this.progress(progress, "Всего: " +format(fileLength) + " / " + format(total) + " / " + speed + "KB/s");
}
}
}
ops.flush();
// Закрываем
ops.close();
ips.close();
}
catch(Exception e){
e.printStackTrace();
}
finish();
}
void finish(){
DownloadManager.this.ticker("Загрузка успешно завершена.");
DownloadManager.this.stopSelf();
DownloadManager.this.cancable();
}
void stop(){
DownloadManager.this.stopSelf();
DownloadManager.this.cancel();
}
}
public String format(int m){
String size = m%mb+"";
size = size.substring(0, Math.min(size.length(), 2));
return m/mb + "." + size + "мб";
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}我可以建议您使用IntentService。android负责你的工作线程逻辑。只需要一点点移植工作。您可以在下面找到代码
通过检查您的
onstart命令中指定的返回标志
我可以看出您已经指定了START\u REDELIVER\u INTENT
。此类返回标志的Javadoc状态
如果此服务的进程在启动时被终止(在
从onStartCommand(Intent,int,int))返回,则
计划重新启动,并将上次传递的意图重新传递给
通过onStartCommand(Intent、int、int)再次启动
从这个解释可以明显看出,您的服务正在被终止。原因尚不清楚,但确保服务(及其子线程)保持“活动”状态是我以前一直努力解决的问题。在我们的应用程序中,我们发现手机睡眠特别具有破坏性。我们通过给服务一个唤醒锁和WiFi锁来“破解”(?)这些细微差别,以确保(a)服务不会在睡眠时被封存,(b)系统保持WiFi锁(即不会断开活动WiFi连接),同时我们在子线程中有工作要做。在我们整理好这些之后,请查看您的服务在睡眠环境下的行为。
尽管如此,这个标志似乎解释了明显的重新启动服务和下载重新尝试
通过简要回顾代码,我发现您正在通过线程与服务进行通信。正如Ranjith指出的那样,IntentService
可能适用于这种情况。但是,子线程无法与脱离工作线程的服务通信。原因是托管服务在脱离工作线程后几乎立即被终止,因为服务的工作是在异步完成所有剩余工作的情况下完成的。这可以解释为什么这对你不起作用
为了推进这一点,我将尝试以下方法之一:
IntentService
,将所有通知代码下移到线程中,并切断所有异步任务服务通信。还请注意我对网络通信的WakeLocks和WiFiLocks的评论。如果不小心使用,这些工具对电池来说是非常危险的START\u STICKY
标志,并允许您的应用程序绑定到它(参考:查看它的运行情况)我能知道使用IntentService时的问题吗?你是通过上下文调用服务吗?startService(服务);我只是将你的代码放到eclipse中。请等待你的代码有错误。你能上传一个非错误代码吗..常量错误fine你能把finish放在finally块中吗