Служба, которая продолжает отправлять данные на сервер по протоколу UDP по таймеру и перезапускается после уничтожения. - PullRequest
0 голосов
/ 02 мая 2019

Я пытаюсь создать приложение на Android, которое отправляет некоторые данные (в моем текущем случае дату и время) на сервер каждые 30 секунд, пока основное действие закрыто. Приложение должно быть совместимо с текущими ограничениями Android для служб, но также должно работать и со старыми.

Я пытался сделать службу с помощью класса JobIntentService, чтобы либо onHandleWork содержал некоторое время (true), либо onHandleWork вызывал новый enqueueWork (я не помню, работал ли он вообще, или через некоторое время служба все еще была убита).

Я также пытался использовать службу переднего плана, тоже безуспешно, но ближе к тому, что мне нужно для приложения. Благодаря этому мне удалось сохранить службу работающей, когда я закрываю приложение из диспетчера задач с помощью диспетчера аварийной сигнализации, но служба все равно останавливается через некоторое время.

Я полностью удалил вариант JobIntentService, поэтому я просто опубликую службу переднего плана здесь.

Для моего основного класса у меня есть:

public class MainActivity extends AppCompatActivity {
    Intent mServiceIntent;
    Context ctx;
    public Context getCtx() {
        return ctx;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ctx = this;
        setContentView(R.layout.activity_main);
        SensorService mSensorService = new SensorService();
        mServiceIntent = new Intent(getCtx(), mSensorService.getClass());
        if (!isMyServiceRunning(mSensorService.getClass())) {
        }
    }

    private boolean isMyServiceRunning(Class<?> serviceClass) {
        ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (serviceClass.getName().equals(service.service.getClassName())) {
                Log.i ("isMyServiceRunning?", true+"");
                return true;
            }
        }
        Log.i ("isMyServiceRunning?", false+"");
        return false;
    }


    @Override
    protected void onDestroy() {
        stopService(mServiceIntent);
        Log.i("MAINACT", "onDestroy!");
        super.onDestroy();

    }
}

Для класса обслуживания:

public class SensorService extends Service {

    private static final String SERVER = "gpstracking.ro";
    private static final int PORT = 6090;
    public int counter=0;
    public SensorService() {
        super();
        Log.i("HERE", "here I am!");
    }

    private static String prepareTime() {
        String c;
        c = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        return c.concat(" Hello DEBUG");
    }

    @SuppressLint("WakelockTimeout")
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        @SuppressLint("InvalidWakeLockTag") PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Awake");
        if ((wl != null) && !(wl.isHeld()))
            wl.acquire();
        super.onStartCommand(intent, flags, startId);
        startTimer();
        return START_STICKY;
    }

    @Override
    public void onCreate() {
        Intent notificationIntent = new Intent(this, SensorRestarterBroadcastReceiver.class);
        PendingIntent pendingIntent=PendingIntent.getActivity(this, 0,
                notificationIntent, 0);

        Notification notification=new Notification.Builder(this)
                .setSmallIcon(R.drawable.ic_my_location_black_24dp)
                .setContentText("It's starting")
                .setContentIntent(pendingIntent).build();

        startForeground(420, notification);


    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("EXIT", "ondestroy!");
        Intent broadcastIntent = new Intent(this, SensorRestarterBroadcastReceiver.class);

        sendBroadcast(broadcastIntent);
        stoptimertask();
    }

    private Timer timer;
    private TimerTask timerTask;
    public void startTimer() {

        timer = new Timer();
        initializeTimerTask();

        timer.schedule(timerTask, 0, 30000); //
    }
    public void initializeTimerTask() {
        timerTask = new TimerTask() {
            public void run() {Runnable r = new Runnable() {
                    /*
                    Here it makes the connection to the server and sends if there is internet available.
                    */
                }
                new Thread(r).start();
                Log.i("in timer", "in timer ++++  "+ (counter++));
            }
        };
    }
    public void stoptimertask() {
        //stop the timer, if it's not already null
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
    }

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

А для моего вещателя:

public void onReceive(Context context, Intent intent) {
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        @SuppressLint("InvalidWakeLockTag") PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Alarm");
        if ((wl != null) && !(wl.isHeld()))
            wl.acquire();
        Log.i(SensorRestarterBroadcastReceiver.class.getSimpleName(), "Service Stops! Oooooooooooooppppssssss!!!!");
        context.startForegroundService(new Intent(context, SensorService.class));
    }

Как я уже говорил выше, сервис останавливается через некоторое время, что происходит на любой платформе, не только на Oreo и выше (устройства, на которых я тестировал, были Android 6.0, Huawei P8 lite и Android 7.0, не знать модель, а также эмулятор Android Studio для Pixel 2 с Android 8.0).

Так что любые советы, которые я могу получить, очень мне помогут.

P.S .: Это мой первый пост о stackoverflow, а также мое первое программирование на Android, поэтому, пожалуйста, вытерпите мои ошибки.

...