且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-02-26 21:27:18

要避免耗尽电池,也就是闲置很快睡着了Android设备。这是你的服务停止的原因。你可以阅读更多关于它如何可以在这里办理:保持清醒的设备。另外看看在 WakefulIntentService CWAC-清醒一>库。看起来它是你所期待的。

I am having some trouble with activity recognition. I have implemented it in an app and it works fine when the device's screen is on. I have a log entry in my Activity recognition intent service class and I can see when it gets an update.So, I know it is working fine when the screen is on.

But then after the phone is put to standby(the screen is turned off) it stops detecting the uses activity.

The onDisconnected() in the DetectionRequester class is not getting called, I checked using a log post.

My question: Why does my app stop tracking the uses activity after the device goes to standby mode? And how do I make it not stop detecting the users activity?

Let me know if you need to see any of the code or if you need any more details on my app.

Relevant bits of code from my MainActivity class. This is where the app starts the request for 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;
    }
 }

My DetectionRequester class:

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();
        }
    }
}

}

The intent service:

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

  }

To avoid draining the battery, an Android device that is left idle quickly falls asleep. It's the reason of your service stopping. You can read more about how it can be handled here: Keeping the Device Awake. Also take a look on WakefulIntentService from cwac-wakeful library. Looks like it's what you are looking for.