[英]Activity Recognition stops receiving updates when phone goes to standby(screen off state)
我在活動識別方面遇到了一些麻煩。 我已經在應用程序中實現了它,並且在打開設備屏幕時可以正常工作。 我的活動識別意圖服務類中有一個日志條目,我可以看到它何時有更新,因此,我知道在屏幕打開時它可以正常工作。
但是,當電話置於待機狀態(屏幕關閉)后,它將停止檢測用戶活動。
我未使用日志發布檢查過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
}
為避免耗盡電池,處於空閑狀態的Android設備會迅速進入睡眠狀態。 這是您的服務停止的原因。 您可以在此處閱讀有關如何處理它的更多信息: 保持設備處於喚醒狀態 。 還可以從cwac-wakeful庫中了解WakefulIntentService
。 看起來就是您要的東西。
看一下“重復警報”:
它們在您的應用程序外部運行,因此即使您的應用程序未運行, 甚至設備本身處於睡眠狀態 ,您也可以使用它們來觸發事件或操作。
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
如果您考慮使用第二種方法,請小心耗盡電池電量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.