13

如果应用程序在前台,后台或终止运行,则应用程序显示预期的行为。然而,一旦它被重新引导PeriodicTask停止运行重新启动后GCMNetworkManager未运行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配置:

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:经过分析的一些日子里,我已经想通了以下内容:

  1. 这是一个设备特定问题。例如,在nexus设备上不会发生这种情况。
  2. 这是一个更大问题的一部分。显示此行为的设备也不能如预期的那样使用AlarmManagerFirebaseJobSchedulerRECEIVE_BOOT_COMPLETED broadcast receiver
  3. 一种解决方法是this solution。但是,此解决方案至少有两个问题。 (1)当你杀了应用程序,AccessibilityService权限被重置。这意味着每次你打开应用程序后,手动权限将被给予。 (2)如果应用程序被杀害,那么重启之后将不会命中RECEIVE_BOOT_COMPLETED broadcast receiver
  4. 疯狂的发现:在一个以上的设备中,如果您的应用程序在包结构中包含字test,则一切正常!
  5. 如果您将应用程序列入设置>应用程序(不同设备的位置和名称可能不同),则所有内容均按预期工作。
  6. 启动应用程序,您必须手动添加您的应用程序包含众所周知的应用程序,如WhatsApp,Facebook,Instagram和许多其他应用程序。当你安装这些应用程序时,它们会自动添加到这个列表中!我还没有看到这些制造商发布的自定义API。这使我认为这些应用程序是从制造商的终端白名单。
+0

在查看日志时,我偶然发现谷歌自己的Youtube for Kids应用也存在相同的问题:** E/NetworkScheduler.TED:无法启动服务:Intent {act = com.google.android。 gms.gcm.ACTION_TASK_READY cmp = com.google.android.apps.youtube.kids/com.google.android.libraries.youtube.common.gcore.gcoreclient.gcm.impl.GcmTaskServiceDelegator(有额外信息)} ** – ranjjose

+1

是否发生在多个设备上? – user2450263

+0

是的..它确实发生在多个设备上。我已经体验到了这一点,MI设备。 – ranjjose

回答

0

PeriodicTask配置:

PeriodicTask task = new PeriodicTask.Builder() 
       .setService(MyTaskService.class) 
       .setTag(TASK_TAG_PERIODIC) 
       .setPeriod(30L) 
       .setFlex(10L) 
       .setExtras(bundle) **/* you put this line here */** 
       .setPersisted(true) 
       .build(); 


    PeriodicTask task = new PeriodicTask.Builder() 
        .setService(MyTaskService.class) 
        .setTag(TASK_TAG_PERIODIC) 
/* you don't have ".setExtras(bundle)" line here */ 
/* try adding this line from above, as logcat is showing this */ 
        .setPeriod(5) 
        .setPersisted(true) 
        .build(); 
+0

感谢您的注意。但是,这不是问题。我猜想当我复制粘贴时,我复制了错误的文件。问题是设备特定的。例如,在oneplus和MI设备中,会发生这些问题。它也不一致。事实上,在oneplus(3T)中,如果你在包boot_completed中有“测试”这个词,那么命中!在MI中没有任何作用。暂时,我得到了无障碍服务的工作,如此处所述https://stackoverflow.com/a/41627296/1349159 – ranjjose

+1

是的,它是非常具体的设备案例。许多制造商提出了android的风味,并且有自己的安全层,它会阻止应用程序的后台服务启动,直到用户去授予独家许可。在我们的开发中,我们在Xiomi手机中复制了这种行为。在这种情况下,您必须向用户提供某种帮助文档。 – Devesh

2

更新: 发现一个Won't Fix (Infeasible) bug可能涉及到的话题。 似乎可访问性服务行为在各个设备上不一致。有些会停用服务,有些会恢复,等等。它适合用户在网上发现的投诉,并与您的观察很好。

我可以给出的最好建议是尽可能在不同的进程上尽可能减少服务(所以不会因为应用程序被终止而中止),并且在启动时检查它是否启用,以及如果不是 - 使用通知系统允许快速访问Android Accessibility设置屏幕,以便于实现。


我对特定问题并不熟悉,但我相信这个解决方法对您有用。我在生产中为AlarmManager使用此代码。

在AndroidManifest.xml:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> 

    <receiver android:name=".BootListener"> 
     <intent-filter> 
      <category android:name="android.intent.category.DEFAULT"/> 

      <action android:name="android.intent.action.BOOT_COMPLETED"/> 
     </intent-filter> 
    </receiver> 

,并创建一个类

public class BootListener extends BroadcastReceiver { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     // If your bootstrap is in Application class, then it will be called anyway - nothing to do here. 
     // else - call your bootsrap here 
    } 
} 

我相信

(2)如果应用程序被终止,重启赢得后” t打 RECEIVE_BOOT_COMPLETED广播接收器

错误,重新启动时,Android不知道您的应用程序已被杀死。这对我的应用(+ 1.2M用户)来说从来都不是问题。

+0

谢谢auval。我已经尝试过使用'android.intent.category.DEFAULT'过滤器。不幸的是,它没有在三到四个测试设备(一个加上3T,MI,redmi)上工作。应用程序终止问题后的重新启动与'辅助服务'有关' – ranjjose

+0

我没有在您发布的代码中看到BroadcastReceiver。 – auval

+0

另外我读到关于'无障碍服务'的是,当你杀了应用程序,它重置无障碍服务权限 – ranjjose

相关问题