My app widget stops working after upgrading to targetSDk to 28.
It is flawlessly working on old targetsdk devices.
I am getting the following error:
W/BroadcastQueue: Background execution not allowed: receiving Intent { act=ch.corten.aha.worldclock.WIDGET_DATA_CHANGED flg=0x10 } to ch.corten.aha.worldclock/.WorldClockWidgetProvider
W/BroadcastQueue: Background execution not allowed: receiving Intent { act=ch.corten.aha.worldclock.WIDGET_DATA_CHANGED flg=0x10 } to ch.corten.aha.worldclock/.WeatherWidgetProvider
androidmanifest.xml file contents are given below-
<!-- clock widget -->
<receiver
android:name=".WorldClockWidgetProvider"
android:exported="false"
android:label="#string/clock_widget_name" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_DISABLED" />
</intent-filter>
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_ENABLED" />
</intent-filter>
<intent-filter>
<action android:name="ch.corten.aha.worldclock.WIDGET_DATA_CHANGED" />
</intent-filter>
<intent-filter>
<action android:name="ch.corten.aha.worldclock.CLOCK_TICK" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/world_clock_appwidget_info" />
</receiver>
<receiver
android:name=".WeatherWidgetProvider"
android:enabled="#bool/enable_weather_widget"
android:exported="false"
android:label="#string/weather_widget_name" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_DISABLED" />
</intent-filter>
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_ENABLED" />
</intent-filter>
<intent-filter>
<action android:name="ch.corten.aha.worldclock.WIDGET_DATA_CHANGED" />
</intent-filter>
<intent-filter>
<action android:name="ch.corten.aha.worldclock.CLOCK_TICK" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/weather_appwidget_info" />
</receiver>
And my reviever class code(
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (WIDGET_DATA_CHANGED_ACTION.equals(intent.getAction())
|| CLOCK_TICK_ACTION.equals(intent.getAction())) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (pm.isScreenOn()) {
onClockTick(context);
}
}
}
Where clock widget provider is extending AppWidgetProvider.
world clock activity
private static void sendWidgetRefresh(Context context) {
// send update broadcast to widget
Intent broadcast = new Intent(ClockWidgetProvider.WIDGET_DATA_CHANGED_ACTION);
context.sendBroadcast(broadcast);
}
project link for reference. Followed previous posts but did not worked.
Oreo - Widget services and broadcast receiver: Not allowed to start service Intent
The problem is in implicit broadcast that you're making in sendWidgetRefresh.
You can break through the ban by defining a component name in your intent.
private static void sendWidgetRefresh(Context context) {
// send update broadcast to widget
Intent broadcast = new Intent(ClockWidgetProvider.WIDGET_DATA_CHANGED_ACTION);
ComponentName componentName = new ComponentName(context, WorldClockWidgetProvider.class);
broadcast.setComponent(componentName);
context.sendBroadcast(broadcast);
}
This worked for me!
Change your implicit intent to explicit intent, because starting Oreo implicit intents don't run in background!
https://developer.android.com/about/versions/oreo/background.html
Related
I found many topic but no case fit for my question.
The first my app working smooth, it is always startup with device by code bellow:
In AndroidManifest:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
and receiver:
<!-- start when module start broadcast -->
<receiver android:name=".StartOnBoot"
android:exported="true">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<!-- listen messenger received -->
<receiver
android:name=".Phone.SmsListener"
android:exported="true">
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
And class StartOnBoot
public class StartOnBoot extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
Intent serviceIntent = new Intent(context, MainActivity.class);
serviceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(serviceIntent);
}
} }
And now I added 2 broadcast to listen state of SD card and SIM card. But when I finish, My app can not start when my device restarted. And I don't know, where is problem, nothing clue.
<!-- broad cast SDCard receive-->
<receiver android:name=".Peripheral.SDCardListener">
<intent-filter>
<action android:name="android.intent.action.MEDIA_EJECT" />
<action android:name="android.intent.action.MEDIA_MOUNTED" />
<data android:scheme="file" />
</intent-filter>
</receiver>
<receiver android:name=".Phone.SimCardReceiver">
<intent-filter>
<action android:name="android.intent.action.SIM_STATE_CHANGED"/>
</intent-filter>
</receiver>
And 2 classes receiver:
public class SDCardListener extends BroadcastReceiver {
//restart app when SD card mounted
#Override
public void onReceive(Context context, Intent intent) {
Log.d("TAG","SDcard state : " + intent.getAction());
if (intent.getAction().equals(Intent.ACTION_MEDIA_EJECT)){
//sdcard eject
}else if (intent.getAction().equals(Intent.ACTION_MEDIA_MOUNTED)){
SDCard.getInstance().SDCardMounted();
}
}
}
for sim state:
public class SimCardReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("TAG", "Sim state :" + intent.getAction());
}
}
My device target is only Android 7.1, SDK lv 25.
Some methods I tried but not work:
I removed SimCardReceiver
I added "android:priortity to StartBoot" like this:
<intent-filter android:priority="1000">
But still not working, Remember, my app always work without 2 broadcast SDCardListener and SimCardReceiver
Extra question:
How many broadcast are available to use in one app. How many is good ? one or not limit
Could I merge all receiver to one broadcast
my program extends From BroadCastReciever to set Alarm, after the device is reboot receiver is not called, this is my code
1- BroadcastReceiver
public class myReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction()!=null) {
if (intent.getAction().equalsIgnoreCase("android.intent.action.BOOT_COMPLETED")) {
Log.d("myActivity","repooted");
// alarm settings
}
}
}
2-xml
<receiver
android:name=".sync.myReceiver"
android:enabled="true"
android:exported="true"
>
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="android.intent.action.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE" />
</intent-filter>
</receiver>
In your AndroidManifest.xml have you added permission to receive boot complete?
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
how to call a single activity(screen lock) of my lock screen app when my phone screen on and off,
I am trying but not achive my target. please help me I am tired. I call activity from the Broadcast Receiver but this launches activity only my app is running when the app close the activity not launches.
REciver is `
#Override
public void onReceive(Context context, Intent intent) { Toast.makeText(context, "BroadcastReceiver", Toast.LENGTH_SHORT).show();
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
Intent lockIntent = new Intent(context, Lockview.class);
lockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(lockIntent);
Toast.makeText(context, "Screen is lock", Toast.LENGTH_SHORT).show();
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
Toast.makeText(context, "Screen is unlocked", Toast.LENGTH_SHORT).show();
} else if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Intent lockIntent = new Intent(context, Lockview.class);
lockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(lockIntent);
Toast.makeText(context, "Screen is book", Toast.LENGTH_SHORT).show();
}`
and the MAnifest is `
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<receiver
android:name=".AEScreenOnOffReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.SCREEN_ON" />
<action android:name="android.intent.action.SCREEN_OFF" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>` and the activity where I trigger the Reciver is ` BroadcastReceiver mybroadcast=new AEScreenOnOffReceiver();
registerReceiver(mybroadcast, new IntentFilter(Intent.ACTION_SCREEN_ON));
registerReceiver(mybroadcast, new IntentFilter(Intent.ACTION_SCREEN_OFF));
registerReceiver(mybroadcast, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));` in the oncreate
I have solved my Problem of launching the activity as a Screen lock direct from the Broadcast Receiver when the screen on. only by changing my Manifest receiver declaration as bellow <receiver
android:name=".AEScreenOnOffReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.SCREEN_ON" />
<action android:name="android.intent.action.SCREEN_OFF" />
<category android:name="android.intent.category.HOME" />
<action android:name="android.intent.action.USER_PRESENT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
I use this code to send data to my BroadcastReceiver.
Log.d("recive message message message", message);
Intent resultBroadCastIntent = new Intent();
resultBroadCastIntent.setAction(Intent.ACTION_SEND);
resultBroadCastIntent.addCategory(Intent.CATEGORY_DEFAULT);
resultBroadCastIntent.putExtra(OUTPUT_TEXT, message);
sendBroadcast(resultBroadCastIntent);
and the BroadcastReceiver code
public class Broadcast_Receiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, Notification_Intent_Service.class));
String resultText =intent.getStringExtra(Notification_Intent_Service.OUTPUT_TEXT);
Log.d("recive dwwwwwwwwwwwwwwww", resultText);
// this never run when message arrive
}
}
and this is my manifest
<receiver
android:name=".Service.Broadcast_Receiver"
android:enabled="true"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
now in
Log.d("recive message message message", message);
the message is printed and I see it but it wasn't sent to the BroadcastReceiver or is it that the BroadcastReceiver didn't receive the data? I'm not sure where the problem is.
You can use the BOOT_COMPLETED id when sending a broadcast
Intent resultBroadCastIntent = new Intent("android.intent.action.BOOT_COMPLETED");
resultBroadCastIntent.putExtra(OUTPUT_TEXT, message);
sendBroadcast(resultBroadCastIntent);
or Specify SEND action in <intent-filter>
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.SEND" />
</intent-filter>
Note: Make sure your BroadcastReceiver isn't an Inner class otherwise add static into it or move it in upper level.
You need to register Intent.ACTION_SEND for Broadcast receiver in manifest
<receiver
android:name=".Service.Broadcast_Receiver"
android:enabled="true"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.SEND" />
</intent-filter>
</receiver>
Roger,
I see that you've been tinkering with camera intents. I'm having real trouble just getting
a simple app to tell me when the camera button has been pressed. Do you have some code to help me on my way.
Thanks.
David
In the manifest, you need to state you want to receive the intent for the camera button:
<receiver android:name="domain.namespace.CameraReceiver">
<intent-filter>
<action android:name="android.intent.action.CAMERA_BUTTON"/>
</intent-filter>
</receiver>
<activity android:name="domain.namespace.MyCameraActivity"
android:label="#string/app_name" android:screenOrientation="landscape" android:icon="#drawable/camera"
android:clearTaskOnLaunch="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.media.action.IMAGE_CAPTURE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
In the receiver:
public void onReceive(Context context, Intent intent) {
KeyEvent event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (event == null) {
return;
}
//prevent the camera app from opening
abortBroadcast();
Intent i = new Intent(Intent.ACTION_MAIN);
i.setClass(context, MyCameraActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}