java - 我的应用程序有时会崩溃(AsyncTask 应该是静态的)

标签 java android rss

我有一个 android 应用程序可以显示我网站的 rss 并在有新内容时显示通知。

问题: 我的应用程序有时会崩溃,这是我在 Google Play 控制台中看到的:

java.lang.RuntimeException: 
  at android.os.AsyncTask$3.done (AsyncTask.java:318)
  at java.util.concurrent.FutureTask.finishCompletion (FutureTask.java:354)
  at java.util.concurrent.FutureTask.setException (FutureTask.java:223)
  at java.util.concurrent.FutureTask.run (FutureTask.java:242)
  at android.os.AsyncTask$SerialExecutor$1.run (AsyncTask.java:243)
  at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1133)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:607)
  at java.lang.Thread.run (Thread.java:761)

Caused by: java.lang.NullPointerException: 
  at com.mydomain.rss.notification.RssNotificationService$SearchForUpdates.doInBackground (RssNotificationService.java:100)
  at com.mydomain.rss.notification.RssNotificationService$SearchForUpdates.doInBackground (RssNotificationService.java:92)
  at android.os.AsyncTask$2.call (AsyncTask.java:304)
  at java.util.concurrent.FutureTask.run (FutureTask.java:237)

在 android studio 中,我看到以下消息:

This AsyncTask class should be static or leaks might occur (com.mydomain.rss.notification.RssNotificationService.SearchForUpdates)

下面是我需要修改的java文件来修复这个问题,但是我不确定我要修改什么来修复这个问题:

package com.mydomain.rss.notification;

import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import com.mydomain.rss.FeedReaderActivity;
import com.mydomain.rss.R;
import com.mydomain.rss.SettingsActivity;
import com.mydomain.rss.cache.MainActivityContext;
import com.mydomain.rss.cache.RefreshFeed;
import com.mydomain.rss.parser.RSSItem;
import com.mydomain.rss.utility.RSSutility;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.text.Html;

/**
 * RSS Service Executer
 */

public class RssNotificationService extends Service {

    public static final int NOTIFICATION_ID = 1;
    //public static final String TITLE_ERROR = "Notify Error";

    Handler searchHandler = new Handler();
    Timer searchLoader = new Timer();

     @Override
     public void onCreate() {
         super.onCreate();
         boolean is_notification_on = getPrefrenceBoolean(SettingsActivity.NOTIFICATION, false);
         if (is_notification_on){
             new SearchForUpdates().execute();
         }
     }

     @Override
     public IBinder onBind(Intent intent) {
         return null;
     }

     @Override
     public void onRebind(Intent intent) {
     super.onRebind(intent);
     }

     @Override
     public boolean onUnbind(Intent intent) {
     return true;
     }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
       return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    public boolean getPrefrenceBoolean(String preference, boolean default_value){
        SharedPreferences sp = getSharedPreferences(this.getPackageName(), Context.MODE_PRIVATE);
        return sp.getBoolean (preference, default_value);
    }

    public void savePrefrenceString(String preference, String value){
        SharedPreferences.Editor editor = getSharedPreferences(this.getPackageName(), Context.MODE_PRIVATE).edit();
        editor.putString(preference, value);
        editor.apply();
    }
    public String getPrefrenceString(String preference, String default_value){
        SharedPreferences sp = getSharedPreferences(this.getPackageName(), Context.MODE_PRIVATE);
        return sp.getString(preference, default_value);
    }

    private class SearchForUpdates extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... params) {

                String lastest_title = getPrefrenceString ("lastTitle", "No feed");

                List<RSSItem> feeds = RSSutility.getRSSFeed(getString(R.string.rss_url));
                RSSItem feed = feeds.get(0);
                String title = feed.getTitle(); 

                if (lastest_title.equalsIgnoreCase(title)){
                    //no update
                }else{
                    showNotification(feed);
                    //store last title so next time will not notify for same rss
                    savePrefrenceString("lastTitle", title);
                }

            return "Executed";
        }

        @Override
        protected void onPostExecute(String result) { 

             boolean is_notification_on = getPrefrenceBoolean(SettingsActivity.NOTIFICATION, false);
             if (is_notification_on){
                //Reload Menu
                long SEARCH_FREQUENCY = Integer.valueOf(getString(R.string.frequency)) * 60 * 1000; 

                searchLoader = new Timer();
                searchLoader.schedule(new TimerTask(){
                    public void run() {
                            searchHandler.post(new Runnable(){
                                public void run(){
                                    new SearchForUpdates().execute();
                                    searchLoader.cancel();
                                }
                            });
                }}, SEARCH_FREQUENCY, SEARCH_FREQUENCY);
             }
        }

        @Override
        protected void onPreExecute() {}

        @Override
        protected void onProgressUpdate(Void... values) {}
    }

    private void showNotification(RSSItem feed) {

        Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_notification);  

        Uri alarmSound = null;
        boolean is_notification_sound_on = getPrefrenceBoolean(SettingsActivity.NOTIFICATION_SOUND, false);
        if (is_notification_sound_on){
            alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        }

        String html = feed.getDescription();
        html = html.replaceAll("<(.*?)\\>", ""); //Removes all items in brackets
        html = html.replaceAll("<(.*?)\\\n", ""); //Must be undeneath
        html = html.replaceFirst("(.*?)\\>", ""); //Removes any connected item to the last bracket
        html = html.replaceAll("&nbsp;", "");
        html = html.replaceAll("&amp;", "");
        html = html.replaceAll("%20", " ");
        html = html.replaceAll("%2C", ", ");
        html = html.replaceAll("%0A", "");

        String title = feed.getTitle();
        title = title.replaceAll("<(.*?)\\>", ""); //Removes all items in brackets
        title = title.replaceAll("<(.*?)\\\n", ""); //Must be undeneath
        title = title.replaceFirst("(.*?)\\>", ""); //Removes any connected item to the last bracket
        title = title.replaceAll("&nbsp;", "");
        title = title.replaceAll("&amp;", "");
        title = title.replaceAll("%20", " ");
        title = title.replaceAll("%2C", ", ");
        title = title.replaceAll("%0A", "");

        //String description = feed.getDescription();

        NotificationCompat.Builder builder = new NotificationCompat.Builder(
                this).setSmallIcon(R.drawable.ic_launcher).setLargeIcon(icon)
                .setContentTitle(feed.getTitle()).setContentText(html)
                .setAutoCancel(true)
                .setSound(alarmSound);

        NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle();  
        bigText.bigText(Html.fromHtml(html));  
        bigText.setBigContentTitle(title);  
        bigText.setSummaryText(Html.fromHtml(html));  
        builder.setStyle(bigText);

        Intent intent = new Intent(this, FeedReaderActivity.class);
        intent.putExtra("NOTIFICATION", true);
        intent.putExtra("title", feed.getTitle());
        intent.putExtra("description", feed.getDescription());
        intent.putExtra("link", feed.getLink());
        intent.putExtra("pubDate", feed.getPubdate());
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        builder.setContentIntent(contentIntent);

        // Send the notification to the system.
        NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(NOTIFICATION_ID, builder.build());

        if (MainActivityContext.instance().activity!=null){
            MainActivityContext.instance().activity.runOnUiThread(new Runnable(){
                @Override
                public void run() {
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            Intent broadcast = new Intent();
                            broadcast.setAction("com.rss.RELOAD_URL");
                            sendBroadcast(broadcast);
                            RefreshFeed.instance().refresh = true;
                        }
                    }, 1000);
                }
            });
        }

    }

}

所以,如果您知道如何解决我的问题,请回复并修改。

最佳答案

在您的 asyncTask 后台执行 List<RSSItem> feeds它的 valeo 是空的,所以当你访问它时 feeds.get(0)导致空指针异常。您的 AsyncTask 类应该是静态的,这样您将只能获得它的一个对象。

关于java - 我的应用程序有时会崩溃(AsyncTask 应该是静态的),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47442323/

相关文章:

android - 升级Gradle版本和lib升级-失败

ANDROID-如何将 gridView 中的选定项目保存在字符串中?

xml - ATOM feed + Google Analytics Javascript = 验证?

java - 启动 Selendroid 中的异常

java - 我应该添加一个ID吗?

python - 使用 python 正则表达式从 Craigslist rss 提要中提取地址

c# - 如何开始制作 C# RSS 阅读器?

java - 如何遍历文件夹中的所有文件(如果文件名未知)?

java - 从html源代码中过滤pdf链接

java - 如何从两个库类继承?如果不可能,有什么替代方案?