【问题标题】:Google Play Service Activity recognition start and stops itself constantlyGoogle Play 服务活动识别不断地自行启动和停止
【发布时间】:2013-10-29 22:23:49
【问题描述】:

我需要通过一个服务(不是activity)调用谷歌活动识别服务并在后台运行它,当然当用户启动应用程序时,它有一个活动(但服务不是直接从活动调用) .

因此,我创建了一个服务类 (ActivitySensor) 和另一个类 (ActivityRecognitionScan)。 当我在我的 Galaxy Nexus S 设备上安装应用程序时,该服务开始自动调用 onCreate 和 onDestroy。即使没有在 GUI 中做任何事情 这是非常奇怪的行为。有没有人有相同的经验或解决方案?

我的意思是我在调试控制台中得到如下信息: 活动记录 --- onCreate 活动记录 --- onDestroy 活动记录 --- onCreate 活动记录 --- onDestroy 活动记录 --- onCreate 活动记录 --- onDestroy ...

这是我的两个课程:

    public class ActivitySensor extends IntentService {

        private ActivityRecognitionScan myascan;
        private Intent inIntent;
        private static long ACTIVITY_LOG_INTERVAL = 30000L;
        private static JsonEncodeDecode jsonencoder = new JsonEncodeDecode(); 
        public ActivitySensor() {
            super("ActivitySensor");
        }   

        @Override
        public void onCreate(){
            super.onCreate();
            Log.d("Activity-Logging", "--- onCreate");
            try {
                myascan = new ActivityRecognitionScan(getApplicationContext());
                myascan.startActivityRecognitionScan();
            } catch (Exception e) {
                Log.e("[Activity-Logging]","----------Error:"+e.getLocalizedMessage());
                e.printStackTrace();
            }   
        }

        @Override
        public void readSensor() {   
    //      Log.e("Activity-Logging", "ActivityRecognitionResult.hasResult: "+String.valueOf(ActivityRecognitionResult.hasResult(inIntent)));
            if (ActivityRecognitionResult.hasResult(inIntent)) {
                ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(inIntent);
                DetectedActivity activity = result.getMostProbableActivity();
                final int type = activity.getType();
                String strType = new String();
                switch(type){
                  case DetectedActivity.IN_VEHICLE:
                      strType = "invehicle";
                      break;
                  case DetectedActivity.ON_BICYCLE:
                      strType ="onbicycle";
                      break;
                  case DetectedActivity.ON_FOOT:
                      strType = "onfoot";
                      break;
                  case DetectedActivity.STILL:
                      strType = "still";
                      break;
                  case DetectedActivity.TILTING:
                      strType ="tilting";
                      break;
                  case DetectedActivity.UNKNOWN:
                      strType ="unknown";
                      break;
                }
                SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
                Editor edt = prefs.edit();
                String previousActv = prefs.getString("PREVIOUS_ACTIVIY","");
                long previousDate = prefs.getLong("PREVIOUS_DATE", 0);
                if (previousActv.length()==0){ // nothing was in the string and it is the first time just initialize
                    previousActv = strType;
                    previousDate = new Date().getTime();
    //              Log.e("-----FIRST TIME: type:", previousActv+" date:"+String.valueOf(previousDate));
                    edt.putString("PREVIOUS_ACTIVIY", strType);
                    edt.putLong("PREVIOUS_DATE", previousDate);
                    edt.commit();
                }else {
                    if (!strType.equalsIgnoreCase(previousActv)){
                        Date readablePrevDate = new Date(previousDate);
                        Date nowDate = new Date();
                        String jsonstr = jsonencoder.EncodeActivity("Activity", readablePrevDate, nowDate, strType, activity.getConfidence());
    //                  Log.e("[Activity-Logging] ----->",jsonstr);
                        edt.putString("PREVIOUS_ACTIVIY", strType);
                        edt.putLong("PREVIOUS_DATE", nowDate.getTime());
                        edt.commit();
                        DataAcquisitor.dataBuff.add(jsonstr);
                    }
                }
            }
        }

        @Override
        protected void onHandleIntent(Intent intent) {
            Log.d("Activity-Logging", "--- onHandleIntent"+ "---"+intent.getAction());
            intent.putExtra("LOG_INTERVAL",ACTIVITY_LOG_INTERVAL );
            intent.putExtra("STOP",false);
            inIntent = intent;
            readSensor();
        }   

        @Override
        public void onDestroy(){
            Log.d("Activity-Logging", "--- onDestroy");
            myascan.stopActivityRecognitionScan();
            myascan=null;
            //super.onDestroy();
        }
}

这是调用 Google Activity Recognition Service 的类:

ActivityRecognitionScan implements GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener {

    private Context ctx;
    private static final String TAG = "ActivityRecognition";
    private static ActivityRecognitionClient actrecClient;
    private static PendingIntent callbackIntent;
    private long ACTIVITY_LOG_INTERVAL=30000;
    public ActivityRecognitionScan(Context context) {
        ctx=context;
    }

    public void startActivityRecognitionScan(){
        int resp = GooglePlayServicesUtil.isGooglePlayServicesAvailable(ctx);
        if(resp == ConnectionResult.SUCCESS){
            actrecClient = new ActivityRecognitionClient(ctx, this, this);
            if (!actrecClient.isConnected()){
                actrecClient.connect();
            } else{
                Log.e("ActivityRecognitionScan"," ---Activity recognition client is already connected");
            }
        }else{
                Log.e("[Activity-Logging]", "Google Play Service hasn't installed");
        }

    }

    public void stopActivityRecognitionScan(){
        try{
            if (actrecClient.isConnected() || actrecClient.isConnecting() ){
                actrecClient.removeActivityUpdates(callbackIntent);
                actrecClient.disconnect();
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        Log.e("[ActivityRecognitionScan]", "Connection Failed");
    }

    @Override
    public void onConnected(Bundle connectionHint) {
        try{
            Intent intent = new Intent(ctx, ActivitySensor.class); 
            Bundle bundle = intent.getExtras(); 
            callbackIntent = PendingIntent.getService(ctx, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
            long interval = 5000;
            if ( null!= bundle && bundle.containsKey("LOG_INTERVAL") ){
                interval = bundle.getLong("LOG_INTERVAL");
            }
            actrecClient.requestActivityUpdates(interval, callbackIntent);  
            actrecClient.disconnect();
        }catch(Exception ex){
            Log.e("[Activity-Logging]","Error in requesting Activity update "+ex.getMessage());
            ex.printStackTrace();
        }
    }

    @Override
    public void onDisconnected() {
        callbackIntent.cancel();
        actrecClient = null;
        Log.e("[ActivityRecognitionScan]","---onDisconnected");
    }
}

【问题讨论】:

    标签: android google-play-services activity-recognition


    【解决方案1】:

    IntentService 按照the source code(参见ServiceHandler.handleMessage())在完成onHandleIntent 时自动停止,按照the description of an IntentService

    客户端通过 startService(Intent) 调用发送请求;服务根据需要启动,使用工作线程依次处理每个 Intent,并在工作结束时自行停止。

    如果您希望它在后台连续运行,请使用Service

    【讨论】:

    • 感谢您的回答,但据我所知,为了更新活动请求,我需要传递一个意图,该服务是不可能的。我的意思是:actrecClient.requestActivityUpdates(interval, callbackIntent); 如果有解决方案可以让它在没有 callbackIntent 的情况下运行,我会立即切换到该服务。
    • 您无需使用IntentService 即可访问传入的Intent - Service.onStartCommand 可让您访问与onHandleIntent 相同的Intent
    • 我使用了Service 类,但奇怪的行为仍然存在。我停止服务是自动启动的。所以不是 IntentService 或 Service 的问题,是别的地方,我还认不出来。
    【解决方案2】:

    您的代码有 2 个问题导致您遇到的问题。

    1. 当检测到活动时,被调用的未决意图调用(并创建,因为它是一个 IntentService)ActivitySensor。 onCreate 将连接另一个 ActivityRecognitionClient,这是不必要的。这会导致检测到另一个活动,从而导致您的日志记录循环。
    2. 您应该将 ActivityRecognitionClient 的创建与检测到的活动的处理分开。您不需要继续重新创建它,因为后续检测将使用相同的 PendingIntent。这将防止日志记录循环。

    【讨论】:

    • 非常感谢。你有一个在代码中解决这个问题的例子吗?我不明白第一点,我认为这是这个问题的根源。您还可以解释为什么我需要在您的第 2 点中将它们分开吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-27
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多