1

Я загружаю видеофайл с помощью задачи Async. Чтобы отслеживать прогресс, у меня есть уведомление, запущенное в строке состояния. Уведомление работает и обновляется правильно, но это приводит к серьезным проблемам с производительностью в том случае, когда аварийная ситуация находится в статусе, и телефон необходимо перезапустить. Мой код выглядит следующим образом:Обновление панели уведомлений от AsynTask приводит к сбою сообщения об ошибке

private class UploadMedia extends AsyncTask<Void, Integer, String> { 

    private int NOTIFICATION_ID = 1; 
    private CharSequence _contentTitle; 
    private final NotificationManager _notificationManager = (NotificationManager) getActivity() 
      .getApplicationContext() 
      .getSystemService(
        getActivity().getApplicationContext().NOTIFICATION_SERVICE); 
    Notification _notification; 
    PendingIntent _pendingIntent; 

    private long totalSize; 
    private int _progress = 0; 
    private InputStreamBody isb; 
    private File uploadFile; 

    protected void onPreExecute() { 

     Intent intent = new Intent(); 
     _pendingIntent = PendingIntent.getActivity(getActivity(), 0, 
       intent, 0); 

     _contentTitle = "Uploader " + mediaTitle + " til Skoletube"; 
     CharSequence contentText = _progress + "% complete"; 

     _notification = new Notification(R.drawable.icon, _contentTitle, 
       System.currentTimeMillis()); 
     _notification.flags = _notification.flags 
       | Notification.FLAG_ONGOING_EVENT; 
     _notification.contentIntent = _pendingIntent; 
     _notification.setLatestEventInfo(getActivity(), _contentTitle, 
       contentText, _pendingIntent); 

     _notificationManager.notify(NOTIFICATION_ID, _notification); 

     Toast.makeText(getActivity(), "Starter upload", Toast.LENGTH_SHORT) 
       .show(); 

     try { 
      uploadFile = new File(_mediaFile.getPath()); 

      // FileInputStream is = new FileInputStream(uploadFile); 
      // 
      // ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
      // byte[] b = new byte[1024]; 
      // int bytesRead; 
      // while ((bytesRead = is.read(b)) != -1) { 
      // bos.write(b, 0, bytesRead); 
      // } 
      // byte[] data = bos.toByteArray(); 
      // 
      // isb = new InputStreamBody(new ByteArrayInputStream(data), 
      // uploadFile.getName()); 

     } catch (Exception ex) { 
      Log.i(TAG, 
        "Pre execute - oh noes... D: " 
          + ex.getLocalizedMessage()); 
     } 

    } 

    @Override 
    protected String doInBackground(Void... params) { 
     String result = ""; 
     try { 
      // Inititate connectionparts 
      HttpClient client = new DefaultHttpClient(); 
      HttpPost postRequest = new HttpPost(
        "http://www.skoletube.dk/beta/api_userupload.php"); 

      CustomMultipartEntity multipartE = new CustomMultipartEntity(
        HttpMultipartMode.BROWSER_COMPATIBLE, 
        new ProgressListener() { 

         @Override 
         public void transferred(long num) { 
          publishProgress((int) ((num/(float) totalSize) * 100)); 

         } 
        }); 

      // Add the post elements 
      String timestamp = String 
        .valueOf(System.currentTimeMillis()/1000); 
      String mode = "xml"; 
      String hashSum = Utils.md5(ActiveUser.getPartner() + timestamp 
        + ActiveUser.getInstance().getToken() 
        + ActiveUser.getInstance().getSecret() 
        + ActiveUser.getInstance().getUserID() 
        + spnChannel.getSelectedItem().toString() 
        + mediaDescribtion + "KEYWORDLOL" 
        + spnPublic.getSelectedItem().toString() + mediaTitle 
        + ActiveUser.getSharedkey()); 

      multipartE.addPart("uid", new StringBody(ActiveUser 
        .getInstance().getUserID())); 
      multipartE.addPart("token", new StringBody(ActiveUser 
        .getInstance().getToken())); 
      multipartE.addPart("token_secret", new StringBody(ActiveUser 
        .getInstance().getSecret())); 
      multipartE.addPart("partner", 
        new StringBody(ActiveUser.getPartner())); 
      multipartE.addPart("timestamp", 
        new StringBody(timestamp.toString())); 
      multipartE.addPart("key", new StringBody(hashSum)); 
      multipartE.addPart("video_title", new StringBody(mediaTitle)); 
      multipartE.addPart("video_desc", new StringBody(
        mediaDescribtion)); 
      multipartE.addPart("video_keyword", 
        new StringBody("KEYWORDLOL")); 
      multipartE.addPart("video_privacy", new StringBody(spnPublic 
        .getSelectedItem().toString())); 
      multipartE.addPart("video_channel", new StringBody(spnChannel 
        .getSelectedItem().toString())); 
      multipartE.addPart("videoupload", new FileBody(uploadFile)); 

      postRequest.setEntity(multipartE); 

      totalSize = multipartE.getContentLength(); 


      HttpResponse loginResponse = client.execute(postRequest); 
      HttpEntity theEnt = loginResponse.getEntity(); 
      result = EntityUtils.toString(theEnt); 

      Log.i(TAG, "Result: " + result); 

     } catch (Exception ex) { 
      Log.i(TAG, 
        "Do in background - oh noes... D: " 
          + ex.getLocalizedMessage()); 

     } 
     return result; 
    } 

    @Override 
    protected void onProgressUpdate(Integer... progress) { 
     if (_notification == null) 
      return; 
     _progress = progress[0]; 
     _contentTitle = "Uploader " + mediaTitle + " til Skoletube"; 
     CharSequence contentText = _progress + "% complete"; 
     _notification.setLatestEventInfo(getActivity(), _contentTitle, 
       contentText, _pendingIntent); 
     _notificationManager.notify(NOTIFICATION_ID, _notification); 
    } 

    @Override 
    protected void onPostExecute(String result) { 
     _notificationManager.cancel(NOTIFICATION_ID); 
    } 

} 

Я тестирую это на HTC Sensation. Проблемы возникают в тот момент, когда я нажимаю панель уведомлений, вызывая ее расширение. Телефон замерзает, и его прикосновение и выход, действительно ли я доберусь до панели уведомлений, или на панели уведомлений произойдет сбой. Если я доберусь до панели уведомлений, проблемы с производительностью сохраняются, и закрытие панели уведомлений снова столь же сложно, как и открытие. То, что я думаю, может быть, это может быть связано с огромным количеством уведомлений об обновлениях, но я не уверен.

Оцените любые идеи и предложения.

ответ

3

Ваши подозрения верны. Следующая инструкция

publishProgress((int) ((num/(float) totalSize) * 100)); 

будет называться очень часто, через короткие промежутки времени.

Что бы я делал в такой ситуации, я должен хранить светящийся проспект, который я хочу отобразить, и отправить его, только если он изменился с момента последнего вызова.

В методе doInBackground, вы можете объявить переменную, такие как:

int lastPourcent = 0; 

Затем в методе transferred:

int currentPoucent = (int) ((num/(float) totalSize) * 100); 
if (currentPourcent > lastPourcent) { 
    publishProgress(currentPourcent); 
    lastPourcent = currentPourcent; 
} 

Это позволит значительно сократить количество вызова метода обновления извещения.

2

Проблема в том, что ваш код переполняет службу Notification обновлениями при каждом выполнении publishProgress(). То, что я сделал, и что вам нужно сделать, - это реализовать решение, которое не переполняет службу, а вместо этого обновит код Notification примерно каждые пять или десять процентов.