Намерение службы Android 5.0 (L) должно быть явным в Google analytics


мой код работал в

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

мой код работает, даже сейчас, на 4.4.4 и ниже. Так что же мне нужно сделать? Я опубликую относительный код ниже. Кроме того, во время моего Гугла я нашел это сообщение о java.ленг.IllegalArgumentException: намерение службы должно быть явным в отношении Android 5.0 но я не понимаю, что это средства.

Манифест

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

    ...

}

* * EDIT**

чем больше я смотрю на этот вопрос, тем больше я думаю, что это не GCMIntentService.java. Я должен был опубликовать свою трассировку стека, перед которой стоит:

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)

поэтому я попытаюсь запустить GA как явное намерение.

11 68

11 ответов:

миграция из Google Analytics v2 в v3 решить эту проблему для меня.

если вы попытка чтобы использовать механизм лицензирования Google, решение, которое работало для меня:

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

находится в com/google/android/vending/licensing/LicenseChecker.java. Сделайте поиск "Base64.decode("

Edit:

добавление ссылки на файл Java лицензирования Google, который должен быть исправлен:

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

исправления:

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

Источник:https://code.google.com/p/android/issues/detail?id=78505#c19

так как Android 5.0 (Lollipop) bindService () всегда должен вызываться с явным намерением. Это была ранее рекомендация, но так как леденец он применяется:java.lang.IllegalArgumentException: Service Intent must be explicit бросается каждый раз, когда вызов bindService() производится с использованием неявных намерений. Разница между неявными и явными намерениями заключается в том, что последний указывает компонент, который должен начинаться по имени (Полное имя класса). смотрите документацию о типах намерений здесь.

вопрос у вас возникли из-за того, что вы не обновили до более новой версии библиотек google, которые соответствуют ограничениям Android на неявные намерения при привязке службы на Android 5 Lollipop. Чтобы устранить эту проблему, можно обновить библиотеку до более новой версии, если она доступна, или обновить код библиотеки самостоятельно и построить проект с измененной версией.

если в общем случае нет подходящего обновления библиотеки, вам нужно изменить исходный код (в вашем случае com.google.analytics.tracking.android.AnalyticsGmsCoreClient.connect()), чтобы вызвать intent.setPackage(packageName) перед вызовом bindService() здесь intent это первый аргумент bindService() звонок и packageName - это имя пакета, содержащего службу, которую код пытается запустить (в вашем случае "com.гуглить.андроид.СБМ.аналитика.)"

вы можете использовать этот код в качестве примера, как это сделать: обновленная версия библиотеки лицензирования Google (LVL) Unity, которая вызывает bindService с явным намерением и не приводит к IllegalArgumentException.

еще один способ обойти эту проблему-перестроить свой проект и библиотеки google с помощью targetSDK не позднее 19. Это позволит ему работать без сбоев на Lollipop, но является менее безопасным вариантом и предотвращает использование функций SDK, представленных в более поздних версиях (для Android 5).

У меня просто была эта проблема сама. Проблема заключается в вашей деятельности, которая запускает ваш сервис.

в принципе, явное намерение называет службу непосредственно в намерении при запуске службы. См.http://developer.android.com/guide/components/intents-filters.html для более глубокого объяснения.

поскольку у вас нет кода активности, я не знаю, как вы начинаете его сейчас, но он, вероятно, должен выглядеть что-то вроде этого:

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

Я этой и

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

Я работаю над проектом, в котором мы хотим разрешить пользователям использовать старые устройства. Я придумал то же решение, что и упомянутое в ответе Marias, однако я добавил условное утверждение для setPackage вызов, так как он доступен только в API 4 (Ice Cream Sandwich == SDK 14) и выше. Если разработка для версий ниже, я считаю, что вам не нужно включать setPackage звонок.

функции 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);

Если вы хотите, чтобы запустить службу, которая находится в другом приложении.вы можете использовать это:

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

это сработало для меня..Это работало в lollipop с помощью Android sdk 21..

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

для пользователей PhoneGap / Cordova, которые видят эту ошибку, это потому, что полуофициальный GAPlugin использует устаревшую версию Google Analytics v2 lib. khalidb91 разветвил его и обновил до v3, который на момент написания этой статьи не был объединен в полуофициальный плагин. Возьмите код из его вилки, бросьте его в качестве прямой замены плагинов / com.саман.подключаемый модуль.Гаплугин и больше никаких аварий. Спасибо khalidb91!

https://github.com/khalidb91/GAPlugin

это работает для меня:

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

Если вы пытаетесь запустить службу, попробуйте так:

var intent = new Intent (this,typeof(MyBoundService));
var serviceConnection = new MyBindServiceConnection (this);
BindService (intent, serviceConnection, Bind.AutoCreate);