Die Dienstabsicht für Android 5.0 (L) muss in Google Analytics explizit angegeben werden

68

Mein Code funktionierte in <5, aber in Android 5.0 stoße ich auf ein Problem, das ich nicht ganz verstehe.

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) }

Mein Code funktioniert auch jetzt noch unter 4.4.4 und darunter. Was muss ich also tun? Ich werde den relativen Code unten posten. Während meines Googelns habe ich diesen Beitrag über java.lang.IllegalArgumentException gefunden: Die Dienstabsicht muss in Bezug auf Android 5.0 explizit sein, aber ich verstehe nicht, was dies bedeutet.

Manifest

<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;
        }
    }

    ...

}

** BEARBEITEN **

Je mehr ich mir dieses Thema anschaue, desto mehr denke ich, dass es nicht in ist GCMIntentService.java . Ich hätte meinen Stack-Trace veröffentlichen sollen, bevor:

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)

Also werde ich versuchen, GA als explizite Absicht auszuführen.

Jacksonkr
quelle
Leider kenne ich diesen Bereich nicht so gut, aber hier ist ein Beitrag zu reddit in Bezug auf Lizenzierungsservice und explizite Absicht; reddit.com/r/androiddev/comments/2jspqi/… .
Harismus

Antworten:

21

Die Migration von Google Analytics v2 auf v3 löst das Problem für mich.

Nickkadrov
quelle
3
Hallo! Ich verwende Analytics v4 und habe heute diese Ausnahme auf dem Lollipop LGE-Gerät (Nexus 5) erhalten. Irgendwelche Hinweise dafür. Ich habe eine separate Datei erstellt, die für das Senden von Bildschirmnamen und Ereignissen verantwortlich ist. TrackerName ist App_Tracker.
Ankit Garg
1
Ich hatte nicht versucht, v4 zu verwenden, aber möglicherweise haben Sie dieses Problem aufgrund eines anderen Dienstes. Versuchen Sie, es vollständig auszuschalten.
Nickkadrov
1
@AnkitGarg Es hört sich so an, als würden wir über verschiedene Software sprechen, da Google Analytics SDK immer noch nur in der Hauptversion von 3 enthalten ist.
Jacksonkr
Das ist komisch, ich erhalte den gleichen Fehler wie Google Analytics v3 ... Ich denke, ich werde die neueste Version ausprobieren.
Arne.jans
2
Ich verwende Version v3, erhalte aber immer noch den gleichen Fehler in Android 5.0 mit targetSdkVersion = 21. Aber ich bekomme diesen Fehler nicht mit targetSdkVersion = 19 in Android 5.0 Gerät. Ich verstehe den Grund nicht. Was kann ich tun?
Realuser
44

Wenn Sie versuchen , den Lizenzierungsmechanismus von Google zu verwenden, hat diese Lösung für mich funktioniert:

// 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);

Dies befindet sich in com/google/android/vending/licensing/LicenseChecker.java. Suche nach " Base64.decode("

Bearbeiten:

Hinzufügen eines Verweises auf die Java-Datei von Google Licensing, die gepatcht werden muss:

com.google.android.vending.licensing.LicenseChecker.checkAccess(LicenseChecker.java:150)

Patch:

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

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

milosmns
quelle
Müssen wir einen Absichtsfilter für den Dienst im Manifest haben? Was soll der Wert dort sein?
Ashutosh Nigam
@AshutoshNigam Ich habe alles so gelassen, wie es ist, also deklariere ich den Dienst normalerweise im Manifest, wie in der Dokumentation beschrieben.
Milosmns
Dies sollte die akzeptierte Antwort sein, da sie das Problem in Android Lollipop behebt.
IgorGanapolsky
Wie finde ich die obige Java-Datei?
h_k
@h_k Ich habe angenommen, dass Sie das Lizenzbibliotheksprojekt aus SDK-Extras importiert haben. Wenn Sie den Import durchführen, steht Ihnen diese Klasse zur Verfügung (auch zum Bearbeiten, aber nicht)
milosmns
38

Seit Android 5.0 (Lollipop) muss bindService () immer mit expliziter Absicht aufgerufen werden. Dies war zuvor eine Empfehlung, aber seit Lollipop wird sie erzwungen: java.lang.IllegalArgumentException: Service Intent must be explicit Wird jedes Mal ausgelöst, wenn ein Aufruf bindService()mit impliziten Absichten erfolgt. Der Unterschied zwischen impliziten und expliziten Absichten besteht darin, dass letztere die Komponente angibt, die mit dem Namen beginnen soll (den vollständig qualifizierten Klassennamen). Weitere Informationen zu Absichtstypen finden Sie hier.

Das Problem, das Sie haben, ist darauf zurückzuführen, dass Sie nicht auf eine neuere Version der Google-Bibliotheken aktualisiert haben, die den Einschränkungen von Android für implizite Absichten beim Binden eines Dienstes auf Android 5 Lollipop entsprechen. Um das Problem zu beheben, können Sie die Bibliothek auf eine neuere Version aktualisieren, falls verfügbar, oder den Bibliothekscode selbst aktualisieren und Ihr Projekt mit der geänderten Version erstellen.

Wenn es im allgemeinen Fall kein geeignetes Bibliotheks-Upgrade gibt, müssen Sie den Quellcode (in Ihrem Fall com.google.analytics.tracking.android.AnalyticsGmsCoreClient.connect()) für den Aufruf ändern , intent.setPackage(packageName)bevor Sie aufrufen, bindService()wo intentdas erste Argument des bindService()Aufrufs und istpackageName den Namen des Pakets, das den Dienst enthält, den der Code versucht Start (in Ihrem Fall "com.google.android.gms.analytics").

Sie können diesen Code als Beispiel dafür verwenden: Unitys aktualisierte Version der Google Licensing Library (LVL), die bindService mit expliziter Absicht aufruft und nicht zu IllegalArgumentException führt.

Eine weitere Möglichkeit, das Problem zu umgehen, besteht darin, Ihr Projekt und die Google-Bibliotheken mit targetSDK bis spätestens 19 neu zu erstellen. Dadurch wird es ohne Absturz auf Lollipop ausgeführt, ist jedoch die weniger sichere Option und verhindert, dass Sie die in späteren Versionen eingeführte SDK-Funktionalität verwenden (für Android 5).

Maria
quelle
Die obigen Antworten haben dazu geführt, dass meine Lizenzprüfung fehlgeschlagen ist, aber die Unity-Lösung hat funktioniert. Danke, +1
Marcus
Ich habe targetSDK = 18 gesetzt, stoße aber immer noch auf dieses Problem.
Yeung
14

Ich hatte dieses Problem nur selbst. Das Problem liegt in Ihrer Aktivität, mit der Ihr Dienst gestartet wird.

Grundsätzlich benennt eine explizite Absicht den Dienst direkt in der Absicht, wenn der Dienst gestartet wird. Weitere Informationen finden Sie unter http://developer.android.com/guide/components/intents-filters.html .

Da Sie Ihren Aktivitätscode nicht veröffentlicht haben, weiß ich nicht, wie Sie ihn jetzt starten, aber er sollte wahrscheinlich ungefähr so ​​aussehen:

Intent startIntent = new Intent(this, ServiceToStart.class);
this.startService(startIntent); // or bindService(...)
Joe Grande
quelle
Ich bin mir immer noch nicht sicher, was los ist. Meine Hauptaktivität ist riesig, sollte ich also einfach meine posten onCreate? Hier wird der GA-Dienst gestartet.
Jacksonkr
Sicher, posten Sie einfach, wo der Dienst gestartet wird.
Joe Grande
1
Inhärente Absicht war das Problem, aber innerhalb der GA-Bibliothek (Google Analytics). Ich hatte sowieso vor, auf die neue Version (3.0) zu aktualisieren, also bin ich einfach von 2 auf 3 und Viola umgestiegen.
Jacksonkr
4
Das hat es für mich gelöst. Ich habe verwendet new Intent(ISomeService.class.getName());, was in 4.4 gut funktioniert, aber nicht in 5.0. Nach dem Umschalten auf diese Leitung new Intent(getApplicationContext(), ISomeService.class);funktionierte sie wieder. Beachten Sie, dass ich bereits in 4.4 eine Warnung dazu hatte. Ich habe sie einfach ignoriert, da ich nur eine Einweg-Testklasse schreibe.
Daniel
Kleines Update: Der Fehler ist verschwunden, aber jetzt kann ich keine Verbindung zum Dienst herstellen. Ich habe mein Ziel-SDK auf 19 gesetzt, bis Google mit Google spricht und einige Korrekturen angezeigt werden.
Daniel
8

Früher habe ich diese und es funktioniert super

 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;
 }
Leebeedev
quelle
4

Ich arbeite an einem Projekt, in dem wir Benutzern die Verwendung älterer Geräte ermöglichen möchten. Ich habe die gleiche Lösung wie die in Marias Antwort erwähnte gefunden, jedoch eine bedingte Anweisung für den setPackageAufruf hinzugefügt , da diese nur in API 4 (Ice Cream Sandwich == SDK 14) und höher verfügbar ist. Wenn Sie für Versionen entwickeln, die darunter liegen, müssen Sie den setPackageAufruf meiner Meinung nach nicht einschließen .

In Funktion 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);
kumaheiyama
quelle
2

Wenn Sie einen Dienst starten möchten, der sich in einer anderen Anwendung befindet, können Sie Folgendes verwenden:

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

Dies funktionierte für mich .. Dies funktionierte in Lutscher mit Android SDK 21 ..

Intent intent = new Intent(this, Class.forName(ServiceClassName.class.getName()));
bindService(intent,serviceConnection, Service.BIND_AUTO_CREATE);
Mayur
quelle
4
Was ist, wenn sich der ServiceClassName in einer anderen apk befindet?
Shrenik
1

Für PhoneGap / Cordova-Benutzer, bei denen dieser Fehler auftritt, liegt dies daran, dass das halboffizielle GAPlugin die veraltete Google Analytics v2-Bibliothek verwendet. khalidb91 gabelte es und aktualisierte es auf v3, das zum jetzigen Zeitpunkt noch nicht in das halboffizielle Plugin integriert wurde. Nehmen Sie den Code von seiner Gabel, legen Sie ihn als direkten Ersatz für plugins / com.adobe.plugins.GAPlugin ab und stürzen Sie nicht mehr ab. Danke khalidb91!

https://github.com/khalidb91/GAPlugin

pmont
quelle
0

Das funktioniert bei mir:

Intent intent = new Intent(ACTION);
intent.setPackage(context.getPackageName());
context.startService(intent);
Forscher
quelle
-2

Wenn Sie versuchen, den Dienst zu starten, versuchen Sie es folgendermaßen:

var intent = new Intent (this,typeof(MyBoundService));
var serviceConnection = new MyBindServiceConnection (this);
BindService (intent, serviceConnection, Bind.AutoCreate);
Augis
quelle
2
typeof ist keine richtige Java-Methode.
Romain