从 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 上测试它。当我按下通知栏并使其展开时,就会立即出现问题。手机死机,触摸即走,无论我是否真的会到达通知栏,还是通知栏会崩溃。如果我确实到达通知栏,性能问题仍然存在,并且再次关闭通知栏与打开它一样棘手。 我的想法是,发送的通知更新的绝对数量可能会导致问题,但我不确定。
感谢任何想法和建议。
I am uploading a video file using an Async Task. To track the progress I have a notification running in the statusbar. The notification works and updates correctly, but it causes severe performance issues to the extent where the statusbar crashes and the phone needs to be restarted. My code as follows:
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);
}
}
I am testing this on a HTC Sensation. The problems occur the instant I press the notification bar, causing it to expand. The phone freezes and its touch and go whether I will actually get to the notification bar or the notification bar will crash. If i do get to the notification bar the performance issues persist, and closing the notification bar again is just as tricky as opening it.
What I'm thinking is maybe the sheer amount of notification updates sent could be causing the problem, but I am not sure.
Appreciate any ideas and suggestions.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你的怀疑是对的。
以下指令
将以很短的时间间隔被非常频繁地调用。
在这种情况下,我要做的就是存储我想要显示的全部进展,并仅在自上次调用以来发生变化时才发送它。
在
doInBackground
方法中,可以声明一个变量如:那么,在
transferred
方法中:将会显着减少Notification的refresh方法的调用次数。
Your suspicions are right.
The following instruction
will be called very frequently, at short intervals.
What I would do in such situation is to store the pourcent avancement I want to display and send it only if it changed since the latest call.
In the
doInBackground
method, you can declare a variable such as:Then, in the
transferred
method:It will significantly reduce the number of call to the refresh method of the Notification.
问题在于,每次执行
publishProgress()
时,您的代码都会因更新而溢出Notification
服务。我所做的,以及您应该做的,是实现一个不会溢出服务的解决方案,而是让您的代码大约每百分之五或百分之十更新一次通知
。The problem is that your code is overflowing the
Notification
service with updates every time you executepublishProgress()
. What I've done, and what you should do, is to implement a solution that doesn't overflow the service, but instead make your code update theNotification
about every five or ten percent.