Android终止服务终止服务?

时间:2017-03-23 11:28:55

标签: android service broadcastreceiver realm sensor

我在这里遇到了一些问题,我不知道如何解决。

我使用的是一个简单的服务,它注册了一个StepDetector(不是我想要自己处理步骤的计数器)。它开始粘贴。

另外,我实现了BroadcastReceiver。它侦听BOOT_Completed和Service_Destroyed。据我所知,它在重启或强制退出应用程序时效果很好。它继续在Realm-Database中计算和存储数据。

进一步解释:我将Step-Data存储在两个表中。

  1. 将它们存储在perHour-Basis上,这意味着所采取的每一步都会写入corepodonding Hour-Row。 例: 第5小时 - 采取60步 第7小时 - 30步采取

  2. 将它们存储在perDay-Basis上。这里存储了当天所有步骤。

  3. 我的onStartCommand看起来像这样:

        manager = (SensorManager)getSystemService(SENSOR_SERVICE);
        stepDetectorSensor = manager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR);
        manager.registerListener(this, stepDetectorSensor, SensorManager.SENSOR_DELAY_FASTEST);
    
        return Service.START_STICKY;
    

    这是我的onSensorChanged

     if(stamp == 0){
            stamp = event.timestamp;
        }
        if(stamp != event.timestamp) {
    
            RealmConfiguration config = new RealmConfiguration.Builder()
                    .deleteRealmIfMigrationNeeded()
                    .build();
            Realm realm = Realm.getInstance(config);
    
            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    Date date = new Date();
    
                    DailyValues dailyValues = realm.where(DailyValues.class).equalTo("type", DailyValues.STEPS).findAll()
                            .where().equalTo("Day", date.getDay()).findAll()
                            .where().equalTo("Month", date.getMonth()).findAll()
                            .where().equalTo("Year", date.getYear()).findFirst();
    
    
                    ValuesPerHour valuesPerHour = realm.where(ValuesPerHour.class).equalTo("type", ValuesPerHour.STEPS).findAll()
                            .where().equalTo("hour", date.getHours()).findAll()
                            .where().equalTo("day", date.getDay()).findFirst();
    
                    if (dailyValues != null) {
                        dailyValues.Value += 1;
                    } else {
                        RealmResults<ValuesPerHour> row = realm
                                .where(ValuesPerHour.class).equalTo("type", ValuesPerHour.STEPS).findAll()
                                .where().notEqualTo("day",date.getDay()).findAll();
                        row.deleteAllFromRealm();
                        dailyValues = realm.createObject(DailyValues.class);
                        dailyValues.Day = date.getDay();
                        dailyValues.Month = date.getMonth();
                        dailyValues.Year = date.getYear();
                        dailyValues.Value = 1;
                        dailyValues.type = dailyValues.STEPS;
    
                    }
    
                    if (valuesPerHour != null)
                        valuesPerHour.value += 1;
                    else {
                        valuesPerHour = realm.createObject(ValuesPerHour.class);
                        valuesPerHour.value = 1;
                        valuesPerHour.hour = date.getHours();
                        valuesPerHour.day = date.getDay();
                        valuesPerHour.type = valuesPerHour.STEPS;
                    }
    
    
                }
            });
            stamp = event.timestamp;
        }
    

    这不是最终版本,因此可能存在一些设计缺陷,但正如您所看到的,我看看是否已有数据用于&#34;今天&#34;由日月和年确定。如果有,请添加一个步骤。如果没有,请添加一行,向其添加一个步骤并清除perHour-Table。 然后我用perHour-Table做几乎相同的事情来更新它。

    我的onDestroy()

    super.onDestroy();
        Intent broadcastIntent = new Intent(".RestartSensor");
        sendBroadcast(broadcastIntent);
    

    只需发送重启内容即可。 最后但并非最不重要的是,Receivers onReceive-Methode:

    context.startService(new Intent(context, StepCounterService.class));
            Log.i("Restart", "Restarted");
    

    Manifest也很好,因为我在Force-Close和Restart of Phone上得到了步数。 让我疯狂的唯一一件事是,当新的一天到来时,我开始移动手机而不首先启动应用程序,没有注册任何步骤。 只有在启动应用程序后,一切正常。

    编辑:正确的ATM我使用startForeground来避免这个问题。但应用程序喜欢 sHealth在没有任何粘性通知的情况下完成此操作。所以基本上我想知道如何重新启动服务,无论发生什么。

    正如评论中所提到的,onDestroy不会一直被调用,因此无法保证重启。 另一个问题可能是Android将应用程序置于打瞌睡(?)中,所以也许我需要一个Wakelock?

    我不认为这是关于读/写方法,因为它适用于任何其他情况。

1 个答案:

答案 0 :(得分:0)

嗯,我想我现在已经开始工作了。 我希望有人会评论是否存在错误或不良做法。 如果你看到任何东西,请帮我修理它。 此外,我需要知道这种方法是否会耗尽电池电量。

我的方法有两种机制在接收器中工作。

  1. 使用WakefulBroadcastReceiver并使用startWakefulService。
  2. 在onReceive()中设置AlarmManager以每5秒钟调用onReceive
  3. 这是我的onReceive() - Methode:

        AlarmManager alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        Intent intentReciever = new Intent(context, SensorRestartBroadcastReceiver.class);
        PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, intentReciever, 0);
        alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 5*1000,
                5*1000, alarmIntent);
    
    
        if(isServiceRunning(context,StepCounterService.class) == false){
            sMonitorServiceIntent = new Intent(context, StepCounterService.class);
            startWakefulService(context,sMonitorServiceIntent);
            Log.i("BroadcastReceiver", "Restarted");
        }
        else{
            Log.i("BroadcastReceiver", "Is running");
        }
    

    如您所见,isServiceRunning被调用,如下所示:

    ActivityManager am = (ActivityManager) context
                .getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo serviceInfo : am
                .getRunningServices(Integer.MAX_VALUE)) {
            String className1 = serviceInfo.service.getClassName();
            String className2 = serviceClass.getName();
            if (className1.equals(className2)) {
                return true;
            }
        }
        return false;
    

    它只是检查此服务的实例是否已在运行。 如果没有,请重新启动服务,否则无需执行任何操作。

    问题是: ATM我通过MainActivity启动服务并保存实例。 这样我就可以调用Service.Stop来启动服务中的onDestroy。

    当我通过广播启动服务时,活动会调用该服务 我不能调用Service.Stop,这导致服务不能重新创建自己。 我尝试过这个。使用活动 - &gt;广播 - &gt;如果服务或应用程序被杀,服务将导致无计数。

    我目前的做法是检查MainActivity是否正在运行Service。如果没有,请运行它。 Service在onStartCommand()中调用对Receiver的初始调用,以确保Receiver开始运行。