Приложение крашится из-за background service

350
21 декабря 2016, 00:21

Доброго времени суток, суть проблемы:

Приложение имеет Service, который проверяет наличие новых заказов на сервере.

Если приложение свернуть, Service исправно выдаёт уведомления в шторку, но при завершении приложения, вместо уведомлений каждую минуту, выскакивает отчёт о краше этого приложения.

Не могу понять в чём проблема.

Листинг кода прилагаю:

MyDataReceiver:

public class MyDataReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        context.startService(new Intent(context, UpdateService.class));
    }
}

UpdateService:

public class UpdateService extends Service {
    private Context context;
    private Timer timer;
    private UpdateTask timerTask;
    //public UpdateService(Context _context) {context = _context;}
    @Override
    public void onCreate() {
        if (timer == null) {
            timer = new Timer();
            timerTask = new UpdateTask(getApplicationContext());
            timer.schedule(timerTask, 30000, 60000);
        }
    }
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

UpdateTask:

public class UpdateTask extends TimerTask {
    private Context context;
    public UpdateTask(Context _context) {context = _context;}
    @Override
    public void run() {
        if (WorkSQLite.ReadOrders(context).size() == 0)
            new OrdersFromDB.CheckNewOrders(context).execute(context.getFilesDir().getPath().toString());
    }
}

NotificationService:

public class NotificationService extends IntentService {
    NotificationManager nm;
    @Override
    public void onCreate() {
        super.onCreate();
        nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        sendNotif();
    }
    public NotificationService() {
        super(NotificationService.class.getSimpleName());
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        sendNotif();
        return super.onStartCommand(intent, flags, startId);
    }
    void sendNotif() {
        Notification myNotification;
        Intent intent = new Intent(getApplicationContext(), ItemsListActivity.class);
        PendingIntent pIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0);
        Notification.Builder builder = new Notification.Builder(this);
        builder.setAutoCancel(false);
        builder.setTicker("Hey. New Orders!");
        builder.setContentTitle("Flower Deliver Car");
        builder.setContentText("You have a new orders");
        builder.setSmallIcon(R.mipmap.ic_launcher);
        builder.setAutoCancel(true);
        //builder.setPriority(Notification.PRIORITY_MAX);
        builder.setDefaults(Notification.DEFAULT_SOUND);
        builder.setDefaults(Notification.DEFAULT_VIBRATE);
        builder.setDefaults(Notification.DEFAULT_LIGHTS);
        //builder.flags |= Notification.FLAG_AUTO_CANCEL;
        builder.setContentIntent(pIntent);
        builder.setOngoing(true);
        myNotification = builder.getNotification();
        //myNotification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
        //startForeground(1, myNotification);
        nm.notify(1, myNotification);
    }
    public IBinder onBind(Intent arg0) {
        return null;
    }
}

UPDATE:

CheckNewOrders:

public static class CheckNewOrders extends AsyncTask<String, Void, Boolean> {
        private Context context;
        public CheckNewOrders(Context _context) {
            this.context = _context;
        }
        @Override
        protected Boolean doInBackground(String... urls) {
            String track = "";
            try {track += "track=" + FileSys.readFile(urls[0]);}
            catch (Exception ex) {SysEx.ExMessage(ex);}
            String url_all_products = "http://93.170.141.12:8080/api/app/checkneworders?" + track + "&" + "key=" + KEY + "&" + "cash=" + CashFunc.getCash(KEY);
            HttpHandler sh = new HttpHandler();
            String jsonStr = sh.makeServiceCall(url_all_products);
            if (jsonStr != null) {
                try {
                    JSONObject jsonObj = new JSONObject(jsonStr);
                    int success = jsonObj.getInt(TAG_SUCCESS);
                    if (success == 1) return true;
                } catch (final JSONException e) {
                    Log.e(TAG, "Json parsing error: " + e.getMessage());
                }
            }
            return false;
        }
        @Override
        protected void onPostExecute(Boolean flag) {
            //if (flag) super.onPostExecute(flag);
            //else super.onPostExecute(flag);
            if (flag) context.startService(new Intent(context, NotificationService.class));
        }
    }

StackTrace:

E/AndroidRuntime: FATAL EXCEPTION: Timer-0
                                                                                  java.lang.ExceptionInInitializerError
                                                                                      at com.example.zaki.deliverflowerscar.Service.UpdateTask.run(UpdateTask.java:22)
                                                                                      at java.util.Timer$TimerImpl.run(Timer.java:284)
                                                                                   Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
                                                                                      at android.os.Handler.<init>(Handler.java:121)
                                                                                      at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:607)
                                                                                      at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:607)
                                                                                      at android.os.AsyncTask.<clinit>(AsyncTask.java:190)
                                                                                      at com.example.zaki.deliverflowerscar.Service.UpdateTask.run(UpdateTask.java:22) 
                                                                                      at java.util.Timer$TimerImpl.run(Timer.java:284) 
READ ALSO
Interface с реализацией

Interface с реализацией

Я во всех учебниках видел, читал, тестировал interface с методами без реализацииНо вот копаюсь в дереве и тут есть методы с реализацией default

298
DrawerLayout cannot be cast to LinearLayout при вызове диалогового окна

DrawerLayout cannot be cast to LinearLayout при вызове диалогового окна

Этот вопрос является продолжением темы Создание всплывающего окна с произвольным содержимымВ том вопросе было предложено такое решение:

320
Андроид демонстрация обновления

Андроид демонстрация обновления

Необходимо, чтобы после обновления на устройстве при первом входе открывался некий фрагмент, демонстрирующий "Что нового в приложении", так...

313