当手机进入待机状态时,活动识别停止接收更新(屏幕关闭状态)

时间:2014-09-01 13:54:10

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

我在活动识别方面遇到了一些麻烦。我已经在应用程序中实现了它,当设备的屏幕打开时它可以正常工作。我的Activity识别意图服务类中有一个日志条目,我可以看到它何时获得更新。所以,我知道它在屏幕打开时工作正常。

但是,在手机进入待机状态(屏幕关闭)后,它会停止检测使用活动。

我没有调用DetectionRequester类中的onDisconnected(),我使用日志帖子进行了检查。

我的问题:为什么我的应用会在设备进入待机模式后停止跟踪使用活动?如何让它不停止检测用户活动?

如果您需要查看任何代码或是否需要有关我的应用的更多详细信息,请与我们联系。

我的MainActivity类的相关代码位。这是应用程序启动ActivityRecognition请求的位置。

public class MainActivity extends FragmentActivity  {

// The activity recognition update request object
private DetectionRequester mDetectionRequester;

// The activity recognition update removal object
private DetectionRemover mDetectionRemover;


// Store the current request type (ADD or REMOVE)
private REQUEST_TYPE mRequestType;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);     
    //Crashlytics.start(this);
    setContentView(R.layout.activity_main);

    mDetectionRequester = new DetectionRequester(this);
    mDetectionRemover = new DetectionRemover(this);

    // Check for Google Play services
     if (servicesConnected()) 
     {
        /*
         *Set the request type. If a connection error occurs, and Google Play services can
         * handle it, then onActivityResult will use the request type to retry the request
         */

          mRequestType = ActivityUtils.REQUEST_TYPE.ADD;

         // Pass the update request to the requester object
          mDetectionRequester.requestUpdates();

      }
}

 private boolean servicesConnected() {

    Log.wtf("Rakshak", "Service connected method");

    // Check that Google Play services is available
    int resultCode =
            GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);

    // If Google Play services is available
    if (ConnectionResult.SUCCESS == resultCode) 
    {
        Log.wtf("Rakshak", "Service connected method: connection result success");
        // Continue
        return true;

    // Google Play services was not available for some reason
    } else {

        Log.wtf("Rakshak", "Service connected method: connection result failure");

        // Display an error dialog
        GooglePlayServicesUtil.getErrorDialog(resultCode, this, 0).show();
        return false;
    }
}        


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {

    // Choose what to do based on the request code
    switch (requestCode) {

        // If the request code matches the code sent in onConnectionFailed
        case ActivityUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST :

            switch (resultCode) {
                // If Google Play services resolved the problem
                case Activity.RESULT_OK:

                    // If the request was to start activity recognition updates
                    if (ActivityUtils.REQUEST_TYPE.ADD == mRequestType) {

                        // Restart the process of requesting activity recognition updates

                        mDetectionRequester.requestUpdates(); 

                    // If the request was to remove activity recognition updates
                    } else if (ActivityUtils.REQUEST_TYPE.REMOVE == mRequestType ){

                            /*
                             * Restart the removal of all activity recognition updates for the 
                             * PendingIntent.
                            */
                           // mDetectionRemover.removeUpdates(
                              //  mDetectionRequester.getRequestPendingIntent()); 

                    }
                break;

                // If any other result was returned by Google Play services
                default:

                    // Report that Google Play services was unable to resolve the problem.
                    Log.d(ActivityUtils.APPTAG, "unable to resolve Google play services problems");
            }

        // If any other request code was received
        default:
           // Report that this Activity received an unknown requestCode
           Log.d(ActivityUtils.APPTAG,
                   "received an unknown request code");

           break;
    }
 }

我的DetectionRequester类:

public class DetectionRequester
    implements ConnectionCallbacks, OnConnectionFailedListener {

// Storage for a context from the calling client
private Context mContext;

// Stores the PendingIntent used to send activity recognition events back to the app
private PendingIntent mActivityRecognitionPendingIntent;

// Stores the current instantiation of the activity recognition client
private ActivityRecognitionClient mActivityRecognitionClient;

public DetectionRequester(Context context) {
    // Save the context
    mContext = context;

    // Initialize the globals to null
    mActivityRecognitionPendingIntent = null;
    mActivityRecognitionClient = null;

}
/**
 * Returns the current PendingIntent to the caller.
 *
 * @return The PendingIntent used to request activity recognition updates
 */
public PendingIntent getRequestPendingIntent() {
    return mActivityRecognitionPendingIntent;
}

/**
 * Sets the PendingIntent used to make activity recognition update requests
 * @param intent The PendingIntent
 */
public void setRequestPendingIntent(PendingIntent intent) {
    mActivityRecognitionPendingIntent = intent;
}

/**
 * Start the activity recognition update request process by
 * getting a connection.
 */
public void requestUpdates() {
    requestConnection();
}

/**
 * Make the actual update request. This is called from onConnected().
 */
private void continueRequestActivityUpdates() {
    /*
     * Request updates, using the default detection interval.
     * The PendingIntent sends updates to ActivityRecognitionIntentService
     */
    getActivityRecognitionClient().requestActivityUpdates(
            ActivityUtils.DETECTION_INTERVAL_MILLISECONDS,
            createRequestPendingIntent());

    // Disconnect the client
    requestDisconnection();
}

/**
 * Request a connection to Location Services. This call returns immediately,
 * but the request is not complete until onConnected() or onConnectionFailure() is called.
 */
private void requestConnection() {
    getActivityRecognitionClient().connect();
}

/**
 * Get the current activity recognition client, or create a new one if necessary.
 * This method facilitates multiple requests for a client, even if a previous
 * request wasn't finished. Since only one client object exists while a connection
 * is underway, no memory leaks occur.
 *
 * @return An ActivityRecognitionClient object
 */
private ActivityRecognitionClient getActivityRecognitionClient() {
    if (mActivityRecognitionClient == null) {

        mActivityRecognitionClient =
                new ActivityRecognitionClient(mContext, this, this);
    }
    return mActivityRecognitionClient;
}

/**
 * Get the current activity recognition client and disconnect from Location Services
 */
private void requestDisconnection() {
    getActivityRecognitionClient().disconnect();
}

/*
 * Called by Location Services once the activity recognition client is connected.
 *
 * Continue by requesting activity updates.
 */
@Override
public void onConnected(Bundle arg0) {
    // If debugging, log the connection
    Log.w("Rakshak", "Locatin client connected");

    // Continue the process of requesting activity recognition updates
    continueRequestActivityUpdates();
}

/*
 * Called by Location Services once the activity recognition client is disconnected.
 */
@Override
public void onDisconnected() {
    // In debug mode, log the disconnection
     Log.w("Rakshak", "Locatin client dis-connected");

    // Destroy the current activity recognition client
    mActivityRecognitionClient = null;

}

/**
 * Get a PendingIntent to send with the request to get activity recognition updates. Location
 * Services issues the Intent inside this PendingIntent whenever a activity recognition update
 * occurs.
 *
 * @return A PendingIntent for the IntentService that handles activity recognition updates.
 */
private PendingIntent createRequestPendingIntent() {

    // If the PendingIntent already exists
    if (null != getRequestPendingIntent()) {

        // Return the existing intent
        return mActivityRecognitionPendingIntent;

    // If no PendingIntent exists
    } else {
        // Create an Intent pointing to the IntentService
        Intent intent = new Intent(mContext, ActivityRecognitionIntentService.class);

        /*
         * Return a PendingIntent to start the IntentService.
         * Always create a PendingIntent sent to Location Services
         * with FLAG_UPDATE_CURRENT, so that sending the PendingIntent
         * again updates the original. Otherwise, Location Services
         * can't match the PendingIntent to requests made with it.
         */
        PendingIntent pendingIntent = PendingIntent.getService(mContext, 0, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);

        setRequestPendingIntent(pendingIntent);
        return pendingIntent;
    }

}

/*
 * Implementation of OnConnectionFailedListener.onConnectionFailed
 * If a connection or disconnection request fails, report the error
 * connectionResult is passed in from Location Services
 */
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    /*
     * Google Play services can resolve some errors it detects.
     * If the error has a resolution, try sending an Intent to
     * start a Google Play services activity that can resolve
     * error.
     */
    if (connectionResult.hasResolution()) {

        try {
            connectionResult.startResolutionForResult((Activity) mContext,
                ActivityUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST);

        /*
         * Thrown if Google Play services canceled the original
         * PendingIntent
         */
        } catch (SendIntentException e) {
           // display an error or log it here.
        }

    /*
     * If no resolution is available, display Google
     * Play service error dialog. This may direct the
     * user to Google Play Store if Google Play services
     * is out of date.
     */
    } else {
        Dialog dialog = GooglePlayServicesUtil.getErrorDialog(
                        connectionResult.getErrorCode(),
                        (Activity) mContext,
                        ActivityUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST);
        if (dialog != null) {
            dialog.show();
        }
    }
}

}

意图服务:

public class ActivityRecognitionIntentService extends IntentService {   

public ActivityRecognitionIntentService() {
    // Set the label for the service's background thread
    super("ActivityRecognitionIntentService");
}

@Override
protected void onHandleIntent(Intent intent) {

    Log.w("Rakshak", "the on handel intent called"); // I see this only when the devices screen is on 

    // do some fun stuff

  }

2 个答案:

答案 0 :(得分:2)

为避免耗尽电池,一台闲置的Android设备会很快入睡。这是您停止服务的原因。您可以在此处详细了解如何处理它:Keeping the Device Awake。另请查看cwac-wakeful库中的WakefulIntentService。看起来这就是你要找的东西。

答案 1 :(得分:1)

看看“重复警报”:

  

它们在您的应用程序之外运行,因此您可以使用它们来触发事件或操作,即使您的应用程序未运行,也可以即使设备本身处于睡眠状态

https://developer.android.com/training/scheduling/alarms.html

或者在“WakeLock”:

  

使用唤醒锁定的一个合理案例可能是后台服务需要获取唤醒锁定保持CPU运行以在屏幕关闭时正常工作 。但是,再次,这种做法应该最小化,因为它会影响电池寿命。

特别“WakefulBroadcastReceiver”:

  

将广播接收器与服务结合使用,可以管理后台任务的生命周期。

     

WakefulBroadcastReceiver是一种特殊类型的广播接收器,负责为您的应用创建和管理PARTIAL_WAKE_LOCK。 WakefulBroadcastReceiver将工作传递给服务(通常是IntentService),同时确保设备在转换中不会重新进入休眠状态。如果在将工作转换为服务时未保持唤醒锁定,则有效地允许设备在工作完成之前返回休眠状态。最终的结果是应用程序可能无法完成工作,直到将来某个任意点,这不是你想要的。

https://developer.android.com/training/scheduling/wakelock.html#cpu

如果您考虑使用第二种方法,请注意排空电池......