从 AsynTask 更新通知栏导致通知栏崩溃

发布于 2025-01-08 06:36:08 字数 6313 浏览 1 评论 0原文

我正在使用异步任务上传视频文件。为了跟踪进度,我在状态栏中运行了一条通知。该通知可以正常工作并更新,但会导致严重的性能问题,导致状态栏崩溃并且需要重新启动手机。我的代码如下:

    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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

魂ガ小子 2025-01-15 06:36:08

你的怀疑是对的。
以下指令

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

将会显着减少Notification的refresh方法的调用次数。

Your suspicions are right.
The following instruction

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

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:

int lastPourcent = 0;

Then, in the transferred method:

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

It will significantly reduce the number of call to the refresh method of the Notification.

爱冒险 2025-01-15 06:36:08

问题在于,每次执行 publishProgress() 时,您的代码都会因更新而溢出 Notification 服务。我所做的,以及您应该做的,是实现一个不会溢出服务的解决方案,而是让您的代码大约每百分之五或百分之十更新一次通知

The problem is that your code is overflowing the Notification service with updates every time you execute publishProgress(). 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 the Notification about every five or ten percent.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文