I am working on an app which needs receive BOOT_COMPLETED broadcast when the device boots.
According to the documents in Android Developers, I already know that since android 3.1, apps that never run after installing or force killed by user will not receive the boot broadcast when device boots, so with the rules, how can I receive boot broadcast? By the way, I have already tried open my app when boot is finished, but it is still not working.
Here's the code:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.guoyonghui.todo"
android:installLocation="auto">
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:name=".BaseApplication"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".tasks.TasksActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".taskdetail.TaskDetailActivity"/>
<activity android:name=".addedittask.AddEditTaskActivity"/>
<activity android:name=".statistics.StatisticsActivity"/>
<receiver android:name=".alarm.AlarmReceiver">
<intent-filter>
<action android:name="com.guoyonghui.todo.alarm.ACTION_TASK_ALARM"/>
</intent-filter>
</receiver>
<receiver
android:name=".alarm.BootReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
</application>
</manifest>
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Toast.makeText(context, action, Toast.LENGTH_SHORT).show();
Log.d("AlarmReceiver", action);
if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
TasksRepository tasksRepository = TasksRepository.getInstance(TasksLocalDataSource.getInstance(context));
List<Task> tasks = tasksRepository.loadTasks();
for (Task task : tasks) {
if (task.isActive()) {
AlarmReceiver.setAlarm(context, task);
}
}
}
}
}
You don't want to use the Default category in this case. According to the documentation of this category, it is used for the following purpose:
Set if the activity should be an option for the default action (center press) to perform on a piece of data. Setting this will hide from the user any activities without it set when performing an action on some data. Note that this is normally -not- set in the Intent when initiating an action -- it is for use in intent filters specified in packages. (Emphasis mine)
See the list of categories and what they're for here:
https://developer.android.com/reference/android/content/Intent.html
Related
I've implemented a BroadcastReceiver according to https://developer.android.com/guide/components/broadcasts but it does not seem to work.
The receiver part of my Manifest.xml looks like this (I use android.permission.ACCESS_NETWORK_STATE and android.permission.ACCESS_WIFI_STATE):
...
<receiver android:name=".BackgroundTask">
<intent-filter>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED"/>
<action android:name="android.net.wifi.STATE_CHANGE" />
</intent-filter>
</receiver>
...
and it's declared within my application.
My BroadcastReceiver class looks like this:
public class BackgroundTask extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("Connection changed!");
Toast.makeText(context, "Network state changed", Toast.LENGTH_LONG).show();
}
}
Neither the toast is displayed nor I receive the println-ed output on my logcat.
I also read the note which recommends me to use scheduled jobs instead of receivers, but I could not find an example how to use this for listening to network changes.
The reason I want to use this is because I want my (background)-app only to run while my phone is connected to my WiFi - if you have any different suggestions on how to implement this, I'm also very thankful.
Btw. I'm using Android 8.0.0.
Cheers,
Nikolar
Update:
Somehow it still does not work. Am I forgetting anything?
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="mypackagename">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".BootReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
<receiver android:name=".BackgroundPoller">
</receiver>
</application>
</manifest>
Just for clearence I renamed my BackgroundTask-Class to BootReceiver:
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("INFO", "BootReceiver started");
Intent newIntent = new Intent(context, BackgroundPoller.class);
context.sendBroadcast(newIntent);
Log.d("INFO", "BackgroundPoller activated");
}
}
When I successfully send my broadcast
adb.exe shell am broadcast -a android.intent.action.ACTION_BOOT_COMPLETED
I still don't get a log output.
To get around Oreo's broadcast receiver restrictions, you have to register your receivers using Context.registerReceiver(). You could do this by subclassing Application and registering receivers in onCreate(). The only downside to doing this is your app would have to be launched to have Application.onCreate() get called. To get around this, you could register an ACTION_BOOT_COMPLETED receiver in your manifest as this action is exempt from the restriction. Your ACTION_BOOT_COMPLETED receiver doesn't have to do anything, but it will force your app to start running on boot and therefore Application.onCreate() will get called. Then the only challenge is keeping your app running because the system will kill it if the user doesn't go into it. There's a couple options to solve this. You could write a foreground service whose only purpose is to keep the app alive. Or perhaps use AlarmManager to schedule some intent that will wake your app back up, which will register your receivers again.
I install and open it , and reboot my phone , but my receiver did't receive broadcast to start my service and without log.
My phone is Asus LF2 .
How can I start my service in device boot completed?
My Receiver
public class BootReceiver extends BroadcastReceiver {
private final String TAG = getClass().getSimpleName();
public BootReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG , "Deyu onReceive " + intent.getAction());
context.startService(new Intent(context, AlarmMessageService.class));
}
}
My manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="go.deyu.dailytodo"
android:installLocation="internalOnly">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:name=".app.App"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".receiver.BootReceiver"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<service
android:name=".AlarmMessageService"
android:enabled="true">
</service>
</application>
</manifest>
I find why my app in my phone can't get boot complete broadcast.
There is a Auto-start Manager setting in my Asus Phone.
When I allow my app to Auto-start , my App work fine....
Remove android:permission="android.permission.RECEIVE_BOOT_COMPLETED" from the <receiver> element.
Try below code
<receiver
android:name=".receivers.RestartReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Android 3.1 or above,if you want to deal with android.intent.action.BOOT_COMPLETED broadcastreceiver.You must pay attention to this:
http://developer.android.com/about/versions/android-3.1.html#launchcontrols
1.Make sure you have turned on your app after you installed.I think you did it.
2.Check your android mobile device settings: Settings -> Apps -> Your App -> Force Stop.If the Force Stop is turned on,please turn off it.
3.Another point you should check is android:name=".receiver.BootReceiver",be careful of the path,maybe system can not find your BootReceiver.
I want to start my application automatically when the phone boots.
I declared a BroadcastReceiver in the manifest file.
<receiver android:name=".Autostart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
I made a java file for the receiver.
Autostart.java
public class Autostart extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Intent pushIntent = new Intent(context, MushTouchActivity.class);
pushIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(pushIntent);
}
}
}
But, the application does not launch when I switch my phone on. Can anyone tell me what I am missing here ?
try your if statement like this:
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
Intent i = new Intent(context, MushTouchActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
In case you are on Android 3.1 or newer:
Make sure that you started your application at least once manually (e.g. by opening it from the app drawer). Otherwise your app is marked as stopped by the system:
Applications are in a stopped state when they are first installed but are not yet launched
Stopped apps do not receive any broadcast intents, including BOOT_COMPLETED.
See Android 3.1. Platform - Launch controls on stopped applications for more information.
The best answer would be to show a Notification and ask the user to launch the app from that notification and use a pending intent for that activity in the notification.
Tested on Android 10
1. Create A Broadcast Listener
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == "android.intent.action.ACTION_SHUTDOWN") {
// Your tasks for shut down
} else {
// Your tasks for Boot up
}
}
}
2. Config Manifest
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:theme="#style/AppTheme">
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.ACTION_BOOT_COMPLETED" />
<action android:name="android.intent.action.REBOOT" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
<action android:name="android.intent.action.ACTION_SHUTDOWN" />
</intent-filter>
</receiver>
</application>
If you search for a sample application code for working with services in background and control actions on screen off/on then visit this repo:
https://github.com/varunon9/DynamicWallpaper
you can update this repo source code with step 1 and 2 for control boot and shutdown events in addition to screen on/off.
I need to write data in to a file ,when system reboots not on boot complete.
i am using broadcast receiver "android.intent.action.REBOOT" Below is my code and manifest files
public class broadcastreceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Log.i("LOG_TAG","rebooted");
}
manifest file:
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".broadcast"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="com.example.broadcastreceiver.broadcastreceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.REBOOT">
<intent-filter>
<action android:name="android.intent.action.REBOOT" />
</intent-filter>
</receiver>
</application>
but i am not able to write even a log when reboots.
note:i donot want to use Bootcompleted action in broadcast receiver
I can't see why you don't want to use BootCompleted, could you provide your reasons?
There is no other action that will alert your broadcast receiver of the boot. You will have to use BootCompleted.
As a note, I hope you are registering you BroadcastReceiver with the context (since you didn't include that code). If you're not using BootComplete, I don't know what action you've registered to expect your above code to execute.
Add this, to me work, but on new devices, there are no testing.
For example in the recent nexus not working.
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
I really read 10 or 20 topics about that and unfortunately I didn't make it working. My receiver can capture broadcast but only if I send it via sendBroadcast(intent) from my app. I want it to capture broadcast from NFC adapter. F.e someone puts NFC Tag near my device and then my app should start or show in browsing menu, however that doesn't happen. Even if my app starts, and I put NFC Tag near device, it can't capture it, and in browsing menu I see other apps, which can.
My receiver:
public class SomeBroadcastReceiver extends BroadcastReceiver {
private final String TAG = "SomeBroadcastReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Got intent: " + intent);
}
}
And my manifest file:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.nfc">
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:icon="#drawable/icon"
android:label="#string/app_name">
<receiver android:enabled="true" android:name=".broadcast.SomeBroadcastReceiver">
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="#xml/technologies"/>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
</intent-filter>
</receiver>
<activity android:name=".simulator.FakeTagsActivity"
android:theme="#android:style/Theme.NoTitleBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="TagViewer"
android:theme="#android:style/Theme.NoTitleBar">
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="10" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />
In FakeActivity i have this lines:
Intent exampleIntent = new Intent("android.nfc.action.NDEF_DISCOVERED");
sendBroadcast(exampleIntent);
And when app reches them, my receiver captures intent, so I think that receiver is fine, but maybe I miss something in manifest? Are there special permission to capture global broadcast? Or should I start service or sth?
You can't capture those intents with a BroadcastReceiver, because only Activities can receive NFC intents. You can find more information about it in the NFC guide.
I use technique described in this answer - it provides the same effect as a broadcast receiver.
According to here (https://stackoverflow.com/a/5320694/3736955), you cant catch NFC intent by BroadcastReceiver. The only way to handle it is by ForegroundDispatch and onNewIntent() function within activity. When NFC Tag is tapped, it looks for foreground activity to handle him.