2013-02-22 4 views
-1

я создал Service для загрузки фильмов и уведомления о прогрессе, и я обнаружил проблему, когда я начал загрузку, а затем вышла из приложения, моя Служба создала новое, не разрушив предыдущий.Начало службы Android

Вход:

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; 
} 

}

ответ

1

Из проверки возврата флага, указанный в вашем onStartCommand я могу видеть вас определили START_REDELIVER_INTENT. Javadoc для этого типа состояний флага возврата;

если процесс этого сервиса будет убит в то время как он был запущен (после возвращения из onStartCommand (Intent, Int, Int)), то он будет запланирован на рестарт и последний доставлен Намерение вновь доставлен он снова через onStartCommand (Intent, int, int)

Из этого объяснения очевидно, что ваш сервис убит. Причина этого неясна, но обеспечение сервисов (и их дочерних потоков) остается «живым» - это то, с чем я столкнулся раньше. В нашем приложении мы обнаружили, что сон для телефона был особенно разрушительным. Мы «взломали» (?) Вокруг этих нюансов, предоставив услугу Wake-Lock и WiFi-Lock, чтобы (a) Служба не была законсервирована во сне и (b) система сохранила блокировку Wi-Fi (т. Е. Не отключите активное соединение Wi-Fi), пока мы работали над дочерними потоками. Пожалуйста, ознакомьтесь с поведением вашего сервиса в среде сна после того, как мы его отсортируем. Тем не менее, этот флаг, похоже, объясняет кажущийся перезапуск службы и повторную попытку загрузки.

Из краткого обзора вашего кода я вижу, что вы общаетесь со своим сервисом из своей темы. IntentService может быть применим в этом сценарии, как указывает Ранджит. Тем не менее, дочерний поток не может связываться с Сервисом, который выделил рабочий поток. Причиной этого является то, что служба хостинга почти сразу же убивается после того, как откручивается рабочий поток, поскольку работа службы выполняется, когда все оставшиеся работы выполняются асинхронно. Это может объяснить, почему это не сработало для вас.

Чтобы двигаться вперед, я бы попытался выполнить одно из следующих действий;

  1. Используйте IntentService и переместите все коды уведомлений в нить и разорвите все коммуникации AsyncTask-Service. Также обратите внимание на комментарии, которые я сделал относительно WakeLocks и WiFiLocks для сетевых коммитов. Эти инструменты выглядят весьма опасными для батареи, если они используются без особого внимания.
  2. Если вы хотите, чтобы ваша служба существовала до тех пор, пока ваша дочерняя нить, я бы предложил вернуть флага START_STICKY из вашей службы и разрешить вашему приложению связываться с ней (ref: Bound Service, чтобы узнать, как это происходит.
2

Я могу sugget вас с помощью IntentService. Там, где андроид заботится о вашей логике рабочего потока. Вы можете найти код ниже

http://mobile.tutsplus.com/tutorials/android/android-fundamentals-intentservice-basics

+0

Это не поможет. –

+1

Могу ли я узнать проблему при использовании IntentService – Ranjith

+0

Загрузка не началась. –

Смежные вопросы