I'm trying to create a simple BroadcastReceiver that can receive the android.intent.action.BOOT_COMPLETED intent as well as the android.intent.action.MEDIA_MOUNTED intent. The idea is to start a service on receiving either of these intents. Thus the service should be started after Android boot is complete or when an USB storage device is connected to the Android target(if the service is not already started by then).
Permissions used by the application are defined in this section
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
The following section defines the BroadcastReceiver responsible for handling the intents and starting the corresponding service.
<receiver
android:name="com.example.systemupgradeapplication.IntentReceiver"
android:label="USB Detection Receiver"
android:enabled="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_REMOVED" />
<action android:name="android.intent.action.MEDIA_EJECT" />
<action android:name="android.intent.action.MEDIA_BAD_REMOVAL" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MEDIA_MOUNTED" />
<data android:scheme="file" />
</intent-filter>
<intent-filter android:priority="999" >
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
The corresponding service that should be started from the Broadcast Receiver is defined in the following section
<service android:name=".SysUpgradeService" />
Note: The receiver and service components are defined within the <application> section of the Android Manifest.
The following snippet is the Class responsible for handling the intents broadcasted
public class IntentReceiver extends BroadcastReceiver {
private final static String TAG = "IntentReceiver";
private static boolean m_UsbInserted = false;
private static boolean m_UsbRemoved = true;
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "LaunchReceiver::ACTION_MEDIA_MOUNTED :: intent received with path= ");
// TODO Auto-generated method stub
//if(intent.)
String action = intent.getAction();
if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
String path = intent.getDataString();
if(path.contains("usb")) {
m_UsbInserted = true;
Log.d(TAG, "LaunchReceiver::ACTION_MEDIA_MOUNTED :: intent received with path= "+path);
Intent myIntent = new Intent(context, SysUpgradeService.class);
myIntent.putExtra("path", path);
context.startService(myIntent);
}
}else if(action.equals(Intent.ACTION_BOOT_COMPLETED)) {
Log.d(TAG, "BOOT Completed intent received");
context.startService(new Intent(context, SysUpgradeService.class));
}
The problem I am facing is that none of the intents are arriving at my broadcast receiver(None of the Logs in the IntentReceiver class are being printed in logcat) even though I can see in the Android Debug logs that the BOOT_COMPLETE and MEDIA_MOUNTED intents are being broadcast. Also This application is not starting after android system is booting up.
I appreciate your help in this regard, what may be wrong with my approach and some possible solutions.
Okay, so I pushed the apk to /system/priv-app which is where System Applications which are part of custom ROM are placed. Now I do not need any activity in my application since it is part of the custom ROM and is recognized as a system application. It seems that if your application is a 3rd party application it must have an activity to be able to receive broadcasted intents.
However in this case I have control over the custom ROM source code as well as root access on the device. So both the approaches work
Make your application part of the custom ROM source, build and flash on device.
Get root access on device, push your apk to /system/priv-app (4.4 onwards), reboot and voila!
Make Sure you have atleat one activity present in your Application.From Android 3.1, BroadcastReceiver will not work until the user has manually launched an activity, This is for provide security . once the user runs the app for the first time then your BroadcastReceiver will run always except it does not Force Stop it. Once activity launch at first time your broadcast receiver will run even after reboot your deice.
Related
Here is my code:
public class CallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
showToast(context,"Call started...");
}
else if(intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_IDLE)){
showToast(context,"Call ended...");
}
else if(intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING)){
showToast(context,"Incoming call...");
}
}
void showToast(Context context,String message){
Toast toast=Toast.makeText(context,message,Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER,0,0);
toast.show();
}
}
//here i have registered my receiver in manifest
<receiver android:name=".CallReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
I am detecting incoming and outgoing calls in my Android application. This code is not working with the device Redmi and Oppo, and I want the code to be working for all the devices. How can I determine what the issue is?
As part of the Android 8.0 (API level 26) Background Execution Limits, apps that target the API level 26 or higher can no longer register broadcast receivers for implicit broadcasts in their manifest. you can register your receiver dynamically in Activity by calling registerReceiver(new CallReceiver(), new IntentFilter().addAction("android.intent.action.PHONE_STATE"));
also, a bad thing about this approach is your receiver will only work when your app is in the foreground. If you close your app then you don't trigger any broadcasts in background. also, refer this if you are looking for call log data.
I am building an app that sends a notification when wifi connection is established. Since I am using android 9 setting intent filter in AndroidManifest.xml doesn't work.
I created a custom BroadcastReceiver, that creates a notification, and it works if I register receiver in onCreate.
Here is the registerReceiver part of the code in onCreate (it works when app is opened)
receiver = new WifiStateReceiver();
IntentFilter filter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
registerReceiver(receiver, filter);
Here is my BroadcastReceiver:
public class WifiStateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("TEST", "IT WORKS!");
}
}
And here is my AndroidManifest.xml
.
.
.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
.
.
.
<receiver
android:name=".WifiStateReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.net.wifi.STATE_CHANGE"/>
</intent-filter>
</receiver>
.
.
.
After I close my app this doesn't work anymore. So I need some kind of service that never closes, but I'm not sure how battery inefficient this method is. Is there a way to run a service when wifi connection/state changes? And as I already said, putting intent-filter in AndroidManifest doesn't seem to work as I am using android 9.
This question already has answers here:
Android - Start service on boot
(7 answers)
Closed 8 years ago.
How can I write a service, which starts automatically when the device boots? For example: when I start my phone, I get my new WhatsApp Messages, without opening WhatsApp before.
Two addition to Himanshu's answer:
A boot-listening app must not be installed on the sdcard. Remember that the device boot may be completed
before the sdcard is even mounted resulting in your app's boot listener not being activated
The boot-listener will not be activated until the user will activate your
app for the first time. Starting 4.2 (not sure here) android prevents all services &
listeners declared by a newly installed app from being activated until it is explicitly activated by the user.
Explicitly activated as in user clicking the homescreen icon.
You can use this to make it working:
Your manifest file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.jjoe64">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application>
<receiver android:name=".BootCompletedIntentReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service android:name=".BackgroundService" />
</application>
</manifest>
Add this class BootCompletedIntentReceiver.java
public class BootCompletedIntentReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Intent pushIntent = new Intent(context, BackgroundService.class);
context.startService(pushIntent);
}
}
}
this will make it auto start your service after boot of device
I creating an app that's using GCM to receive notifications from our servers, am using Google's gcm.jar, and have a customGCMIntentService class handling it. My problem is that only one handset is actually getting a response (or more likely routing the response correctly) from GCM when calling GCMRegistrar.register().
What I'm seeing is that the GCMRegistrar (from the gcm library) is correctly setting my custom broadcast receiver as the retry receiver on the nexus 3 phone, the only one that works, but not on the others. This makes me believe that I might be getting a response from GCM but its not being processed on the three other phones (detail below).
GCMRegistrar Setting the name of retry receiver class to <My_application_package>.CustomGCMBroadcastReceiver
All of them have a data connection that allows communication with GCM, all have an active gmail account on them ( all of them have the playstore working ). I've also run Google's GCM demo on them all without a problem.
The registration code:
//This is almost identical to how Google's GCM demo does it.
private void registerOnGCM(){
checkNotNull(SERVER_URL, "SERVER_URL"); //What it says on the tin
checkNotNull(SENDER_ID, "SENDER_ID");
// Make sure the device has the proper dependencies.
GCMRegistrar.checkDevice(this);
// Make sure the manifest was properly set - comment out this line
// while developing the app, then uncomment it when it's ready.
GCMRegistrar.checkManifest(this);
/*
registerReceiver(mHandleMessageReceiver,
new IntentFilter(HANDLE_MESSAGE));
*/
final String regId = GCMRegistrar.getRegistrationId(getApplicationContext());
if (regId.equals("")) {
// Automatically registers application on startup.
GCMRegistrar.register(getApplicationContext(), SENDER_ID);
}
else {
// Device is already registered on GCM, check server.
if (GCMRegistrar.isRegisteredOnServer(getApplicationContext())) {
// Skips registration.
Log.i(TAG, "Already registered");
} else {
// Try to register again, but not in the UI thread.
// It's also necessary to cancel the thread onDestroy(),
// hence the use of AsyncTask instead of a raw thread.
final Context context = this;
mRegisterTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
boolean registered = ServerUtilities.register(context, regId);
if (!registered) {
GCMRegistrar.unregister(context);
}
return null;
}
#Override
protected void onPostExecute(Void result) {
mRegisterTask = null;
}
};
mRegisterTask.execute(null, null, null);
}
}
The code for CustomGCMBroadcastReceiver doesn't matter, nor does the GCMIntentService, since neither of them is ever call'd. Problem isn't with them.
Devices I'm testing on:
HTC Desire GSM running CyanogenMod 7
Google nexus 3 running Android 4.1.1 (Application works on this one)
Motorola T910 running Android 4.0.1
Samsung Galaxy mini running Android 4.2.6
Manifest:
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- App has permission to read/write files on sd card. Used for RSS document -->
<uses-permission android:name = "android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 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" />
<permission
android:name="<My_package_name>.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission
android:name="<My_package_name>.permission.C2D_MESSAGE" />
<!-- This app has permission to register and receive data message. -->
<uses-permission
android:name="com.google.android.c2dm.permission.RECEIVE" />
<application
android:allowBackup="true"
android:theme="#style/AppTheme"
android:label="#string/app_name">
<activity
android:name="<My_package_name>.MasterActivity"
android:screenOrientation="portrait">
</activity>
<activity android:name="<My_package_name>.WebActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--
BroadcastReceiver that will receive intents from GCM
services and handle them to the custom IntentService.
The com.google.android.c2dm.permission.SEND permission is necessary
so only GCM services can send data messages for the app.
-->
<receiver
android:name="<My_package_name>.CustomGCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<!-- Receives the actual messages. -->
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<!-- Receives the registration id. -->
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="<My_package_name>" />
</intent-filter>
</receiver>
<!--
Application-specific subclass of GCMBaseIntentService that will
handle received messages.
By default, it must be named .GCMIntentService, unless the
application uses a custom BroadcastReceiver that redefines its name.
-->
<service android:name="<My_package_name>.GCMIntentService"
android:enabled="true"/>
</application>
Might be something I've forgotten to add. Let me know.
All ideas are welcomed.
-MrDresden
Well it seems to have fixed it self by only cleaning, and rebuilding and then deploying that to those other devices.
Why removing all traces from all phones, then running in debug mode on them didn't work, except on one phone I have no idea.
I have this code that works great:
Notification n = builder.build();
n.flags = Notification.FLAG_NO_CLEAR;
But when I restart the phone, the notification goes away. Is there any flag that make that happen?
If you want to print notification when the device boots up, you can create a receiver that is invoked when the system boot is completed, for this, first create a receiver,
public class MyReciever extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent)
{
Log.d("BOOT COMPLETE","SERVICE CALLED>>>>>>>>>>>>");
//use your code here to print notifications
}
}
This receiver is invoked when the system boot is completed. You can also call a service from the onReceive method of receiver to print the notification.
Also you must define the following regularities in your manifest file,
First define permission for getting BOOT_COMPLETION intent,
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
Then define your receiver also,
<receiver android:name=".MyReciever"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
No. I don't think that is possible.
You could have a service that runs at start-up to to bring up that notification again. Notifications otherwise do not persist across reboots.