web-dev-qa-db-fra.com

Android 5.0 (L) L'intention du service doit être explicite dans Google Analytics

Mon code fonctionnait dans <5 mais dans Android 5.0). Je rencontre un problème que je ne comprends pas très bien.

10-23 10:18:18.945: E/AndroidRuntime(8987): Java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.google.Android.gms.analytics.service.START (has extras) }

Mon code fonctionne, même maintenant, sur 4.4.4 et ci-dessous. Alors qu'est-ce que je dois faire? Je posterai le code relatif ci-dessous. En outre, lors de ma recherche sur Google, j'ai trouvé ceci message sur Java.lang.IllegalArgumentException: L'intention de service doit être explicite en ce qui concerne Android 5. mais je ne comprends pas ce que cela signifie veux dire.

Manifeste

<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
    package="xxxxx.Android.phone.xxxxx"
    Android:versionCode="3"
    Android:versionName="v1.2.4065" >

    <uses-sdk Android:minSdkVersion="12"
        Android:targetSdkVersion="21" />

    <!-- Required for Google Analytics -->
    <uses-permission Android:name="Android.permission.ACCESS_NETWORK_STATE" />

    <!-- For Push notifications (GCM) -->
    <permission Android:name="xxxxx.Android.phone.xxxxx.permission.C2D_MESSAGE" Android:protectionLevel="signature" />
    <uses-permission Android:name="xxxxx.Android.phone.xxxxx.permission.C2D_MESSAGE" />
    <!-- App receives GCM messages. -->
    <uses-permission Android:name="com.google.Android.c2dm.permission.RECEIVE" />
    <!-- GCM connects to Google Services. -->
    <uses-permission Android:name="Android.permission.INTERNET" /> 
    <!-- GCM requires a Google account. -->
    <uses-permission Android:name="Android.permission.GET_ACCOUNTS" />
    <!-- Keeps the processor from sleeping when a message is received. -->
    <uses-permission Android:name="Android.permission.WAKE_LOCK" />
    <!-- GCM - We handle notifications differently if the app is running -->
    <uses-permission Android:name="Android.permission.GET_TASKS" /> 

    <!-- Caching -->
    <uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE" />

    <!-- The event subscribe button adds events to the calendar -->
<!--    <uses-permission Android:name="Android.permission.WRITE_CALENDAR" /> -->
<!--    <uses-permission Android:name="Android.permission.READ_CALENDAR" />  -->

    <supports-screens
        Android:resizeable="true"
        Android:smallScreens="false"
        Android:normalScreens="true"
        Android:largeScreens="true"
        Android:xlargeScreens="true"
        Android:anyDensity="true" />

    <application
        Android:name="xxxxx.xxxxxApplication"
        Android:icon="@drawable/app_icon"
        Android:label="@string/app_name"
        Android:allowBackup="true"
        Android:largeHeap="true" >
        <receiver 
            Android:name="com.google.Android.gcm.GCMBroadcastReceiver" 
            Android:permission="com.google.Android.c2dm.permission.SEND" >
            <intent-filter>
                <action Android:name="com.google.Android.c2dm.intent.RECEIVE" />
                <category Android:name="xxxxx.Android.phone.xxxxx" />
            </intent-filter>
            <intent-filter>
                <action Android:name="com.google.Android.c2dm.intent.REGISTRATION" />
                <category Android:name="xxxxx.Android.phone.xxxxx" />
            </intent-filter>
        </receiver>

        <receiver 
            Android:name="xxxxx.ConnectivityReceiver"
            Android:enabled="false" >
            <intent-filter>
                <action Android:name="Android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>
        </receiver>

        <activity 
            Android:name=".SplashActivity"
            Android:configChanges="locale|orientation" 
            Android:theme="@style/Theme.Splash"
            Android:screenOrientation="portrait"
            Android:noHistory="true" >
            <intent-filter >
                <action Android:name="Android.intent.action.MAIN" />
                <category Android:name="Android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            Android:label="@string/app_name"
            Android:theme="@style/Theme"
            Android:windowSoftInputMode="adjustPan|stateVisible"
            Android:name=".LoginActivity"
            Android:configChanges="locale|orientation|screenSize" 
            Android:screenOrientation="portrait" >
        </activity>
        <activity 
            Android:name=".MainActivity" 
            Android:theme="@style/Theme"
            Android:configChanges="locale|orientation|screenSize" 
            Android:screenOrientation="portrait"
            Android:windowSoftInputMode="adjustPan|stateVisible" />

        <activity 
            Android:name=".CountryPickerActivity" 
            Android:theme="@style/Theme.Floating"
            Android:configChanges="locale|orientation|screenSize" 
            Android:screenOrientation="portrait"
            Android:windowSoftInputMode="adjustPan|stateVisible" />
        <activity 
            Android:name=".EventPickerActivity" 
            Android:theme="@style/Theme.Floating"
            Android:configChanges="locale|orientation|screenSize" 
            Android:screenOrientation="portrait"
            Android:windowSoftInputMode="adjustPan|stateVisible" />
        <activity 
            Android:name=".TutorialActivity"
            Android:theme="@style/Theme.Transparent"
            Android:configChanges="locale|orientation|screenSize"
            Android:screenOrientation="portrait" />

        <activity 
            Android:name=".VideoPlayerActivity" 
            Android:theme="@style/Theme"
            Android:configChanges="orientation|screenSize" />

        <service Android:name=".GCMIntentService" Android:enabled="true" />
        <meta-data Android:name="com.crashlytics.ApiKey" Android:value="xxxxxxxxxxxxxxxx"/>
    </application>

</manifest>

GCMIntentService.Java

public class GCMIntentService extends GCMBaseIntentService {
private static final int ATTEMPTS_MAX = 3;

final static boolean USE_DEV = false;
final static String XXXXX = "https://xxxxx/api.php";
final static String XXXXX = "http://dev.xxxxx/api.php";
final static String SUBSCRIPTION_KEY = "xxxxxxxxxxxxxxx"; // unique per app

    public GCMIntentService() {
        super(xxxxxx.SENDER_ID);
        if(GCMIntentService.USE_DEV) {
            Host = XXXXX;
        } else {
            Host = XXXXX;
        }
    }

    ...

}

** MODIFIER **

Plus je regarde cette question plus je pense que ce n'est pas dans GCMIntentService.Java. J'aurais dû poster ma trace de pile avant qui est:

10-23 13:17:08.095: E/AndroidRuntime(10560): FATAL EXCEPTION: GAThread
10-23 13:17:08.095: E/AndroidRuntime(10560): Process: xxxxx.Android.phone.xxxxx, PID: 10560
10-23 13:17:08.095: E/AndroidRuntime(10560): Java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.google.Android.gms.analytics.service.START (has extras) }
10-23 13:17:08.095: E/AndroidRuntime(10560):    at Android.app.ContextImpl.validateServiceIntent(ContextImpl.Java:1674)
10-23 13:17:08.095: E/AndroidRuntime(10560):    at Android.app.ContextImpl.bindServiceCommon(ContextImpl.Java:1773)
10-23 13:17:08.095: E/AndroidRuntime(10560):    at Android.app.ContextImpl.bindService(ContextImpl.Java:1751)
10-23 13:17:08.095: E/AndroidRuntime(10560):    at Android.content.ContextWrapper.bindService(ContextWrapper.Java:538)
10-23 13:17:08.095: E/AndroidRuntime(10560):    at com.google.analytics.tracking.Android.AnalyticsGmsCoreClient.connect(AnalyticsGmsCoreClient.Java:82)
10-23 13:17:08.095: E/AndroidRuntime(10560):    at com.google.analytics.tracking.Android.GAServiceProxy.connectToService(GAServiceProxy.Java:279)
10-23 13:17:08.095: E/AndroidRuntime(10560):    at com.google.analytics.tracking.Android.GAServiceProxy.createService(GAServiceProxy.Java:163)
10-23 13:17:08.095: E/AndroidRuntime(10560):    at com.google.analytics.tracking.Android.GAThread.init(GAThread.Java:95)
10-23 13:17:08.095: E/AndroidRuntime(10560):    at com.google.analytics.tracking.Android.GAThread.run(GAThread.Java:493)

Je vais donc essayer d'exécuter GA comme intention explicite.

68
Jacksonkr

La migration de Google Analytics v2 vers v3 résout le problème pour moi.

21
nickkadrov

Si vous essayez d'utiliser le mécanisme de gestion des licences de Google, solution qui a fonctionné pour moi:

// explicit Intent, safe
Intent serviceIntent = new Intent(ILicensingService.class.getName());
serviceIntent.setPackage("com.Android.vending");
boolean bindResult = mContext.bindService(serviceIntent, this, Context.BIND_AUTO_CREATE);

Ceci est situé dans com/google/Android/vending/licensing/LicenseChecker.Java. Effectuer une recherche sur "Base64.decode( "

Modifier:

Ajout d'une référence à Google Licensing Java à corriger):

com.google.Android.vending.licensing.LicenseChecker.checkAccess(LicenseChecker.Java:150)

pièce:

new String(
-    Base64.decode("Y29tLmFuZHJvaWQudmVuZGluZy5saWNlbnNpbmcuSUxpY2Vuc2luZ1NlcnZpY2U="))),
+    Base64.decode("Y29tLmFuZHJvaWQudmVuZGluZy5saWNlbnNpbmcuSUxpY2Vuc2luZ1NlcnZpY2U=")))
+    .setPackage("com.Android.vending"), // this fix the 'IllegalArgumentException: Service Intent must be explicit'
     this, // ServiceConnection.

Source: https://code.google.com/p/Android/issues/detail?id=78505#c19

44
milosmns

Depuis Android 5.0 (Lollipop) bindService () doit toujours être appelé avec une intention explicite. C’était auparavant une recommandation, mais depuis Lollipop, elle est appliquée: Java.lang.IllegalArgumentException: Service Intent must be explicit Est lancé à chaque fois. un appel à bindService() est effectué à l'aide d'intentions implicites. La différence entre les intentions implicites et explicites est que ce dernier spécifie le composant à démarrer par son nom (nom de classe qualifié complet). Voir la documentation sur les types d'intention ici.

Le problème que vous rencontrez est dû au fait que vous n'avez pas effectué la mise à niveau vers une version plus récente des bibliothèques Google, qui est conforme aux restrictions d'Android sur les intentions implicites lors de la liaison d'un service sur Android 5 Lollipop. Pour résoudre le problème , vous pouvez mettre à niveau la bibliothèque vers une version plus récente, si disponible, ou mettre à jour le code de la bibliothèque vous-même et générer votre projet avec la version modifiée.

S'il n'y a pas de mise à niveau de bibliothèque appropriée dans le cas général, vous devez modifier le code source (dans votre cas, com.google.analytics.tracking.Android.AnalyticsGmsCoreClient.connect()) pour appeler intent.setPackage(packageName) avant d'appeler bindService()intent est le premier argument de l'appel bindService() et packageName est le nom du package contenant le service que le code tente de démarrer (dans votre cas, "com.google. Android.gms.analytics ").

Vous pouvez utiliser ce code comme exemple pour procéder ainsi: La version mise à jour de Unity de la bibliothèque de licences Google (LVL), qui appelle bindService avec une intention explicite et ne génère pas d'IllegalArgumentException.

Une autre façon de contourner le problème consiste à reconstruire votre projet et les bibliothèques Google à l'aide de targetSDK au plus tard à 19h. Cela le fera fonctionner sans se planter sur Lollipop, mais constitue l'option la moins sécurisée et vous empêche d'utiliser les fonctionnalités du SDK introduites dans les versions ultérieures. (pour Android 5).

38
Maria

Je viens d'avoir ce problème moi-même. Le problème réside dans votre activité qui commence votre service.

En gros, une intention explicite nomme le service directement dans l'intention lorsque le service est démarré. Voir http://developer.Android.com/guide/components/intents-filters.html pour une explication plus détaillée.

Depuis, votre code d'activité n'est pas affiché, je ne sais pas comment vous le démarrez maintenant, mais il devrait probablement ressembler à ceci:

Intent startIntent = new Intent(this, ServiceToStart.class);
this.startService(startIntent); // or bindService(...)
14
Joe Grande

J'ai utilisé this et cela fonctionne très bien

 public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) {
     //Retrieve all services that can match the given intent
     PackageManager pm = context.getPackageManager();
     List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);

     //Make sure only one match was found
       if (resolveInfo == null || resolveInfo.size() != 1) {
        return null;
       }

     //Get component info and create ComponentName
     ResolveInfo serviceInfo = resolveInfo.get(0);
     String packageName = serviceInfo.serviceInfo.packageName;
     String className = serviceInfo.serviceInfo.name;
     ComponentName component = new ComponentName(packageName, className);

     //Create a new intent. Use the old one for extras and such reuse
     Intent explicitIntent = new Intent(implicitIntent);

     //Set the component to be explicit
     explicitIntent.setComponent(component);

     return explicitIntent;
 }
8
Leebeedev

Je travaille sur un projet dans lequel nous voulons permettre aux utilisateurs d'utiliser des appareils plus anciens. Je suis venu avec la même solution que celle mentionnée dans la réponse de Marias, cependant j'ai ajouté une déclaration conditionnelle pour l'appel setPackage car elle est uniquement disponible dans API 4 (Sandwich à la crème = = SDK 14) et au dessus de. Si vous développez des versions ci-dessous que je pense, vous n'avez pas besoin d'inclure l'appel setPackage.

En fonction com.google.Android.vending.licensing.LicenseChecker.checkAccess(callback)

Intent serviceIntent = new Intent(new String(
Base64.decode("Y29tLmFuZHJvaWQudmVuZGluZy5saWNlbnNpbmcuSUxpY2Vuc2luZ1NlcnZpY2U=")));

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
    serviceIntent.setPackage("com.Android.vending");
}

boolean bindResult =
    mContext.bindService(
        serviceIntent,
        this, // ServiceConnection.
        Context.BIND_AUTO_CREATE);
4
kumaheiyama

Si vous souhaitez démarrer un service qui se trouve dans une autre application, vous pouvez utiliser ceci:

Intent serviceIntent = new Intent("action name for the service");
serviceIntent.setPackage("the PackageName for which the service in)");//the destination packageName
context.startService(serviceIntent);
2
yu xiaofei

Cela a fonctionné pour moi .. Cela a fonctionné dans Lollipop en utilisant Android sdk 21 ..

Intent intent = new Intent(this, Class.forName(ServiceClassName.class.getName()));
bindService(intent,serviceConnection, Service.BIND_AUTO_CREATE);
1
Mayur

Pour les utilisateurs de PhoneGap/Cordova qui constatent cette erreur, c'est parce que GAPlugin, un agent semi-officiel, utilise la version obsolète de Google Analytics v2. khalidb91 l'a bifurqué et mis à jour vers la v3 qui, à ce jour, n'a pas été fusionné dans le plugin semi-officiel. Prenez le code de sa fourche, déposez-le en remplacement direct de plugins/com.Adobe.plugins.GAPlugin et ne bloquez plus. Merci khalidb91!

https://github.com/khalidb91/GAPlugin

1
pmont

Cela fonctionne pour moi:

Intent intent = new Intent(ACTION);
intent.setPackage(context.getPackageName());
context.startService(intent);
0
researcher