Приложение показывает ожидаемое поведение, если приложение работает на переднем плане, в фоновом режиме или убито. Однако после перезагрузки PeriodicTask
перестает работать
Ниже приведены соответствующие биты кода:
В AndroidManifest
:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<service android:name=".tracking.MyTaskService"
android:exported="true"
android:permission="com.google.android.gms.permission.BIND_NETWORK_TASK_SERVICE">
<intent-filter>
<action android:name="com.google.android.gms.gcm.ACTION_TASK_READY" />
</intent-filter>
</service>
PeriodicTask config:
PeriodicTask task = new PeriodicTask.Builder()
.setService(MyTaskService.class)
.setTag(TASK_TAG_PERIODIC)
.setPeriod(30L)
.setFlex(10L)
.setExtras(bundle)
.setPersisted(true)
.build();
mGcmNetworkManager.schedule(task);
В Logcat я получаю следующее:
E/NetworkScheduler.TED: Couldn't start service: Intent
{ act=com.google.android.gms.gcm.ACTION_TASK_READY
cmp=xxx.xxxxxx.xxx/.tracking.MyTaskService (has extras)
}
Добавление всех необходимых сведений:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.example.gcmnetworkmanagerquickstart">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- [START manifest_service] -->
<service
android:name=".MyTaskService"
android:exported="true"
android:permission="com.google.android.gms.permission.BIND_NETWORK_TASK_SERVICE">
<intent-filter>
<action android:name="com.google.android.gms.gcm.ACTION_TASK_READY" />
</intent-filter>
</service>
<!-- [END manifest_service] -->
</application>
</manifest>
MainActivity
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static final int RC_PLAY_SERVICES = 123;
public static final String TASK_TAG_PERIODIC = "periodic_task";
private GcmNetworkManager mGcmNetworkManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGcmNetworkManager = GcmNetworkManager.getInstance(this);
if(checkPlayServicesAvailable()){
startPeriodicTask();
}
}
public void startPeriodicTask() {
Log.d(TAG, "startPeriodicTask");
PeriodicTask task = new PeriodicTask.Builder()
.setService(MyTaskService.class)
.setTag(TASK_TAG_PERIODIC)
.setPeriod(5)
.setPersisted(true)
.build();
mGcmNetworkManager.schedule(task);
}
private boolean checkPlayServicesAvailable() {
GoogleApiAvailability availability = GoogleApiAvailability.getInstance();
int resultCode = availability.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (availability.isUserResolvableError(resultCode)) {
// Show dialog to resolve the error.
availability.getErrorDialog(this, resultCode, RC_PLAY_SERVICES).show();
} else {
// Unresolvable error
Toast.makeText(this, "Google Play Services error", Toast.LENGTH_SHORT).show();
}
Log.d(TAG, "Play Services NOT Available");
return false;
} else {
Log.d(TAG, "Play Services Available");
return true;
}
}
}
MyTaskService
public class MyTaskService extends GcmTaskService {
private static final String TAG = "MyTaskService";
@Override
public void onInitializeTasks() {
}
@Override
public int onRunTask(TaskParams taskParams) {
Log.d(TAG, "onRunTask: " + taskParams.getTag());
return doPeriodicTask();
}
private int doPeriodicTask() {
Log.d(TAG, "doPeriodicTask Called");
return GcmNetworkManager.RESULT_SUCCESS;
}
}
build.gradle(модуль приложения)
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
defaultConfig {
applicationId "com.google.example.gcmnetworkmanagerquickstart"
minSdkVersion 14
targetSdkVersion 26
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
allprojects {
repositories {
jcenter()
google()
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
implementation 'com.android.support:appcompat-v7:26.0.0-beta2'
compile 'com.squareup.okhttp:okhttp:2.7.0'
compile 'com.google.android.gms:play-services-gcm:11.0.2'
}
Edit1: После нескольких дней анализа я выяснил следующее:
- Это проблема, связанная с устройством. Например, не происходит на устройствах связи.
- Это часть более крупной проблемы. Устройства, демонстрирующие это поведение, также не работают с
AlarmManager
,FirebaseJobScheduler
иRECEIVE_BOOT_COMPLETED broadcast receiver
. - Обходным решением является это решение. Однако это решение имеет как минимум 2 проблемы. (1) Когда вы убиваете приложение, разрешение
AccessibilityService
reset. Это означает, что каждый раз, когда вы открываете приложение после этого, нужно дать разрешение вручную. (2) Если приложение убито, перезагрузка после этого не ударит поRECEIVE_BOOT_COMPLETED broadcast receiver
- Сумасшедший поиск: в устройствах с одним плюсом, если ваше приложение имеет слово
test
в структуре пакета, все работает!! - Если вы настроите белый список приложений на настройки > Приложения (расположение и имя этого могут отличаться на разных устройствах), все работает так, как ожидалось.
- Запуск приложений, к которым вы должны вручную добавить свое приложение, содержит известные приложения, такие как WhatsApp, Facebook, Instagram и многие другие. Когда вы устанавливаете эти приложения, они автоматически добавляются в этот список! Я еще не видел пользовательский API, опубликованный любым из этих производителей для этого. Это заставляет меня думать, что эти приложения белые, перечисленные со стороны производителей.