Android粘性服务正在被丢失,丢失所有信息

时间:2014-09-03 07:53:28

标签: java android service timer

我的服务基本上是计时器。它接收具有位置数据,开始时间,用户ID等的对象,并且每秒增加停止值。我想让这项服务不间断运行,直到在应用程序中停止。我已经读过我需要以粘性方式启动此服务,所以我这样做了。但我注意到,在我的主要应用程序被系统或用户杀死后,服务重新启动并丢失所有信息(关于当前计时器运行等等 - 我有数据包含对象列表)。

该服务的理念是: 用户点击应用中的按钮 - >服务正在启动并计算通知栏中的时间变化信息并向主应用程序发送广播 - >即使app被用户或系统杀死,我也希望继续更新通知栏。

我的课程如下:

public class TimerService extends Service{
    private NotificationCompat.Builder builder;
    private static JsonHistoryList activities;
    private Intent intent;
    private Handler handler;

    private Runnable sendUpdateToUi = new Runnable() {
        @Override
        public void run() {
            sendBroadcast();
            handler.postDelayed(this, 1000);
        }
    };

    private NotificationManager mNotificationManager;

    private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if(action.equals(ACTION_ADD)){
                JsonHistory item = (JsonHistory) intent.getSerializableExtra(HISTORY_ARG);
                new NetworkAsyncTask().execute(ACTION_ADD_ID, item);
            }else if(action.equals(ACTION_DELETE)){
                int id = intent.getIntExtra(CATEGORY_ID_ARG, -1);
                if(id > 0){
                    new NetworkAsyncTask().execute(ACTION_DELETE_ID, id);
                }
            }else if(action.equals(ACTION_CLEAR)){
                activities.clear();
            }
        }
    };

    public TimerService() {
        handler = new Handler();
    }

    private void sendBroadcast() {
        Long time = new Date().getTime();

        for(JsonHistory item: activities){
            ContentValues values = new ContentValues();
            values.put(History.C_STOP, time);
            String[] selectionArgs = {String.valueOf(item.id)};
            getContentResolver().update(History.URI, values, History.C_ID + "=?", selectionArgs);
            item.stop = time;
        }

        intent.putExtra(ACTIVITY_LIST_ARG, activities);

        Intent bIntent = new Intent(this, MainActivity.class);
        bIntent.putExtra(CATEGORY_ARG, activities);
        builder.setContentText(String.format(getString(R.string.notification_bar_message), activities.size()));
        Notification barNotif = builder.build();
        mNotificationManager.notify(SERVICE_ID, barNotif);

        sendBroadcast(intent);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        IntentFilter filter = new IntentFilter();
        filter.addAction(ACTION_ADD);
        filter.addAction(ACTION_DELETE);
        filter.addAction(ACTION_CLEAR);
        registerReceiver(receiver, filter);
        intent = new Intent(ACTION);
        handler.removeCallbacks(sendUpdateToUi);
        handler.postDelayed(sendUpdateToUi, 1000);
        activities = new JsonHistoryList();

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        if(intent != null && intent.hasExtra(TimerService.ACTIVITY_LIST_ARG)){
            ArrayList<JsonHistory> temp = (ArrayList<JsonHistory>) intent.getSerializableExtra(TimerService.ACTIVITY_LIST_ARG);
            if(temp != nu;; && temp.size() > 0)activities.addAll(temp);
        }

        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        Intent bIntent = new Intent(this, MainActivity.class);
        PendingIntent pbIntent = PendingIntent.getActivity(this, 0, bIntent, 0);
        builder =
                new NotificationCompat.Builder(this)
                        .setSmallIcon(R.drawable.notification_icon)
                        .setContentTitle(getString(R.string.app_name))
                        .setContentText(String.format(getString(R.string.notification_bar_message), activities.size()))
                        .setAutoCancel(true)
                        .setOngoing(true)
                        .setContentIntent(pbIntent);
        Notification barNotif = builder.build();
        this.startForeground(SERVICE_ID, barNotif);
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver);
        handler.removeCallbacks(sendUpdateToUi);
        stopForeground(true);
    }

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

    private class NetworkAsyncTask extends AsyncTask<Object, Void, String>{
        Gson gson;

        public NetworkAsyncTask() {
            super();
            gson = new Gson();
        }

        @Override
        protected String doInBackground(Object... params) {
            Integer actionId = (Integer) params[0];
            String result = null;
            switch (actionId){
                case ACTION_ADD_ID:
                    break;
                case  ACTION_DELETE_ID:
                    break;
                default:
                    result = null;
                    break;
            }
            return result;
        }
    }
}

感谢您的回复

1 个答案:

答案 0 :(得分:0)

当您停止服务时,如果应用程序被销毁,它将丢失其信息。这是因为该服务实例与应用程序的特定实例相关联。

在我看来,一个简单的解决方法是将您仍需要的信息存储在某种类型的持久存储中(SQLite,内部/外部存储器,共享首选项)

然后,每次使用新的应用程序启动启动服务时,请确保从您选择的任何持久存储方法重新加载所需的信息。

此外,假设您不希望在用户杀死该应用程序时继续此服务,请确保向服务发送意图以阻止它:

    intent = new Intent(this, BackgroundLocationService.class);  
    stopService(intent);