0

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

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

我的意思是我在调试控制台中得到如下内容: Activity-Logging --- onCreate Activity-Logging --- onDestroy Activity-Logging --- onCreate Activity-Logging --- onDestroy Activity-Logging --- onCreate Activity-Logging --- 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");
    }
}
4

2 回答 2

2

IntentService根据 IntentService 的描述,onHandleIntent根据源代码(请参阅ServiceHandler.handleMessage())完成时自动停止自身:

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

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

于 2013-10-29T22:55:22.903 回答
0

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

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