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

相關問題