Reputation: 41
I am working on a widget and code is working fine on pre Lollipop devices but when I run my code on Lollipop, it gives me error Service Intent must be explicit: Intent { act=org.clangen.widget.clock.action.UPDATE }
.
I have Google this error but I did't understand even this [question] Android 5.0 (L) Service Intent must be explicit in Google analytics.
Here is the logcat
02-19 15:07:21.888: E/AndroidRuntime(31621): FATAL EXCEPTION: main
02-19 15:07:21.888: E/AndroidRuntime(31621): Process: com.brainlogix.mezanhijricaleandarapp, PID: 31621
02-19 15:07:21.888: E/AndroidRuntime(31621): java.lang.RuntimeException: Unable to start receiver com.brainlogix.widget.ClockWidget: java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=org.clangen.widget.clock.action.UPDATE }
02-19 15:07:21.888: E/AndroidRuntime(31621): at android.app.ActivityThread.handleReceiver(ActivityThread.java:2586)
02-19 15:07:21.888: E/AndroidRuntime(31621): at android.app.ActivityThread.access$1700(ActivityThread.java:144)
02-19 15:07:21.888: E/AndroidRuntime(31621): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1355)
02-19 15:07:21.888: E/AndroidRuntime(31621): at android.os.Handler.dispatchMessage(Handler.java:102)
02-19 15:07:21.888: E/AndroidRuntime(31621): at android.os.Looper.loop(Looper.java:135)
02-19 15:07:21.888: E/AndroidRuntime(31621): at android.app.ActivityThread.main(ActivityThread.java:5221)
02-19 15:07:21.888: E/AndroidRuntime(31621): at java.lang.reflect.Method.invoke(Native Method)
02-19 15:07:21.888: E/AndroidRuntime(31621): at java.lang.reflect.Method.invoke(Method.java:372)
02-19 15:07:21.888: E/AndroidRuntime(31621): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
02-19 15:07:21.888: E/AndroidRuntime(31621): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
02-19 15:07:21.888: E/AndroidRuntime(31621): Caused by: java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=org.clangen.widget.clock.action.UPDATE }
02-19 15:07:21.888: E/AndroidRuntime(31621): at android.app.ContextImpl.validateServiceIntent(ContextImpl.java:1674)
02-19 15:07:21.888: E/AndroidRuntime(31621): at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1703)
02-19 15:07:21.888: E/AndroidRuntime(31621): at android.app.ContextImpl.startService(ContextImpl.java:1687)
02-19 15:07:21.888: E/AndroidRuntime(31621): at android.content.ContextWrapper.startService(ContextWrapper.java:515)
02-19 15:07:21.888: E/AndroidRuntime(31621): at android.content.ContextWrapper.startService(ContextWrapper.java:515)
02-19 15:07:21.888: E/AndroidRuntime(31621): at com.brainlogix.widget.ClockWidget.onUpdate(ClockWidget.java:122)
02-19 15:07:21.888: E/AndroidRuntime(31621): at android.appwidget.AppWidgetProvider.onReceive(AppWidgetProvider.java:66)
02-19 15:07:21.888: E/AndroidRuntime(31621): at android.app.ActivityThread.handleReceiver(ActivityThread.java:2579)
02-19 15:07:21.888: E/AndroidRuntime(31621): ... 9 more
Here is widget class with inner service
public class ClockWidget extends AppWidgetProvider {
private static final String SHOW_POPUP_DIALOG_ACTION = "com.brainlogix.widget.Widget_PopUp";
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
context.startService(new Intent(UpdateService.ACTION_UPDATE));
}
public static final class UpdateService extends Service {
static final String ACTION_UPDATE = "org.clangen.widget.clock.action.UPDATE";
@Override
public void onCreate() {
super.onCreate();
registerReceiver(mTimeChangedReceiver, sIntentFilter);
}
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mTimeChangedReceiver);
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
private void update() {
//some code
}
private final BroadcastReceiver mTimeChangedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(Intent.ACTION_TIME_CHANGED)
|| action.equals(Intent.ACTION_TIMEZONE_CHANGED)) {
// some code
}
update();
}
};
}
}
Here is my manifest file.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.brainlogix.mezanhijricaleandarapp"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/CustomTheme" >
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<receiver
android:name="com.brainlogix.widget.ClockWidget"
android:label="@string/widget_name" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/clock_widget" />
</receiver>
<service
android:name="com.brainlogix.widget.ClockWidget$UpdateService"
android:label="UpdateService" >
<intent-filter>
<action android:name="org.clangen.widget.clock.action.UPDATE" />
</intent-filter>
</service>
<receiver android:name="com.brainlogix.widget.ClockWidget" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/demo_widget_provider" />
</receiver>
<receiver
android:name="com.brainlogix.widget.MyWidgetIntentReceiver"
android:label="@string/widget_name" >
<intent-filter>
<action android:name="com.javatechig.intent.action.UPDATE_WIDGET" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/demo_widget_provider" />
</receiver>
</application>
</manifest>
Upvotes: 0
Views: 5154
Reputation: 39191
Instantiating an Intent with only an action creates what is referred to as an implicit Intent, since any component registered to handle that action will be started in order to do so. As of Lollipop, Services can no longer be started with implicit Intents due to security concerns. You merely need to be specific about the class the Intent is meant for; i.e., use an explicit Intent.
context.startService(new Intent(context, UpdateService.class));
You should also remove the <intent-filter>
element from the Service in the manifest, as that is what allows your Service to be started with an implicit Intent, which is no longer allowed.
Upvotes: 7