Battery broadcast receiver doesn't work - java

I don't know why, but my battery broadcast receiver doesn't work.
AndroidManifest.xml
<receiver android:name=".BatteryReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BATTERY_CHANGED" />
<action android:name="android.intent.action.BATTERY_LOW" />
</intent-filter>
</receiver>
BatteryReceiver.java
public class BatteryReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
int level = intent.getIntExtra( "level", 0 );
Log.d("Battery", "level: "+level);
Toast.makeText(context, "Battery low!", Toast.LENGTH_LONG).show();
}
}
What is wrong with my code?
I'm using console (telnet) to change battery level (power capacity X).

There are several issues; I've ordered them roughly by decreasing severity:
You can't register for ACTION_BATTERY_CHANGED from your Manifest; you must register for it programmatically.
Don't use the BATTERY_STATS permission; it's completely unrelated.
If you're receiving more than one Broadcast in the same BroadcastReceiver (and it's generally a good idea even if you're not) you should check to see which Broadcast you've just received. ACTION_BATTERY_LOW should not be treated in the same way as ACTION_BATTERY_CHANGED. (For one thing, it doesn't have the BatteryManager.EXTRA_LEVEL Extra attached to it, so trying to read it will give you your default value, 0.)
You should use -1 as your default value, not a valid value like 0.
You should check to see if you've received the default value and handle it appropriately.
You should use BatteryManager.EXTRA_LEVEL rather than hard-coding "level".

Related

Android detecting incoming and outgoing calls is not working with Redmi and Oppo mobiles

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.

How to pause onCreate until boot completed?

I host widgets in my app and it seems, that if i start my app before booting of the device is completed, widgets cannot be created properly. Widgets then seem to be not loaded completely or not initialized/updated correctly. For instance: BatteryBotIndicator-Widget, which shows the battery status in percentage, shows a value of "XX" instead of some number like "70%". If i then restart my app and try to recreate the widget with:
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
it gives me null for appWidgetInfo (i fetch appWidgetId from SQLite database). And widget cannot be recreated.
It is kind of difficult to debug the real cause in this situation to find out what is exactly causing this (Starting Debugger at the right time). I assume the AppWidgetManager is not ready yet or something.
What i can say for sure: If i wait until i receive the broadcast-event BOOT_COMPLETED all widgets are created properly.
So how can i pause the execution of onCreate until booting is completed?
I can think of putting the thread to sleep in a while loop until the BroadcastReceiver (BOOT_COMPLETED) is setting a bool-variable in application-data to true. But i dont want to wait for this event always at starting of my app, as you can imagine ;)
if i start my app before booting of the device is completed, widgets cannot be created properly.
please explain more what exactly do you mean when you say - "not properly" . this might be relevant to understand if you're widget really depends on something related to the boot.
I can think of putting the thread to sleep in a while loop until the BroadcastReceiver (BOOT_COMPLETED) is setting a bool-variable in application-data to true
very bad idea.. also from performances and design reasons
instead, why not simply register to boot complete broadcast from the manifest, and when you recevice it - simply send the relevant broadcast to update your widget? AppWidgetProvider is already extends BroadcastReceiver, so you can simply add it intent filter for boot complete broadcast.
this is how to add intent filter to boot complete:
<receiver android:name="MyWidgetProvider" >
<intent-filter >
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
<meta-data
...
</receiver>
and this is how to react to it from the widget provider implementation:
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("android.intent.action.BOOT_COMPLETED")){
doTheUpdateHereExactlyLikeHowYouUpdateItFromAnywhereElse();
} else {
super.onReceive(context,intent);
}
}
for more information - follow this tutorial :https://laaptu.wordpress.com/2013/08/12/android-update-app-widget-with-listview-after-phone-reboot/

Android - Set notification to never go away

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.

Android: How to Detect "Turn on USB storage" Broadcast?

I am trying to detect the Turn on USB storage using BroadcastReceiver though i am able to detect the USB connected using android.intent.action.UMS_CONNECTED action
and
disconnected using android.intent.action.UMS_DISCONNECTED action.
How can i detect the USB storage ?
Below is how I check if storage card is mounted/unmounted. You can change it to check removed/insterted. I do this by register a BroadcastReceiver to get the "mount events" then check what state the storage card is in. If it is not mounted and is not while it is checking (the state during it mounts the card again) it is unmounted or the card has been removed.
public class MemCardReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
onMemcardMounted();
}
else if (!Environment.getExternalStorageState().equals(Environment.MEDIA_CHECKING)){
onMemorycardUnMounted();
}
}
private void onMemorycardUnMounted() {}
private void onMemcardMounted() {}
}
And in ManifestFile
<receiver android:enabled="true" android:exported="true" android:name="the.name">
<intent-filter>
<action android:name="android.intent.action.MEDIA_MOUNTED" />
<action android:name="android.intent.action.MEDIA_UNMOUNTED" />
<data android:scheme="file" />
</intent-filter>
</receiver>
There are several different states checkout this if there are any other stated like. removed
I think android.Intent.action.ACTION_MEDIA_EJECT is broadcast when user takes the USB storage in use and ACTION_MEDIA_MOUNTED when it's turned off.

Having trouble receiving ACTION_PASSWORD_SUCCEEDED and ACTION_PASSWORD_FAILED intents

I am using Android's Administration API and have a DeviceAdminReceiver, and override the following functions:
#Override
public void onEnabled(Context context, Intent intent)
{
System.out.println("Admin On======================");
}
#Override
public void onDisabled(Context context, Intent intent)
{
System.out.println("Admin Off======================");
}
#Override
public void onPasswordFailed(Context context, Intent intent)
{
System.out.println("PW Bad============================");
}
#Override
public void onPasswordSucceeded(Context context, Intent intent)
{
System.out.println("PW Good===========================");
}
#Override
public void onPasswordChanged(Context context, Intent intent)
{
System.out.println("Changed PW=======================");
}
On enabled, Disabled, and PW changed work, however password failed and succeeded do not. Strangely, they randomly work once in a while and then stop working. Is there anything wrong with my code, or could this be an API problem?
The receiver in AndroidMaifest
<receiver android:name="AdminReciever"
android:label="Administration"
android:permission="android.permission.BIND_DEVICE_ADMIN" android:enabled="true">
<meta-data android:name="android.app.device_admin"
android:resource="#xml/adminpolicies" />
<intent-filter>
<action android:name="android.app.action.ACTION_PASSWORD_SUCCEEDED"/>
<action android:name="android.app.action.ACTION_PASSWORD_FAILED"></action>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED"></action>
<action android:name="android.app.action.ACTION_PASSWORD_CHANGED"></action>
</intent-filter>
</receiver>
FIXED
Found out the problem, it seems this wasn't documented. I had set a minimum password length with dpm.setPasswordMinimumLength(). The password entry activity does not fire a PASSWORD_FAILED intent if the password entered is less then the minimum length. Also PASSWORD_SUCCEEDED only fires if a bad password (PASSWORD_FAILED fired) was entered before the successful one. So two successful passwords in a row will not fire the second intent.
Very late answer here but I was having the same issue and your 'Fixed' edit helped me work out why.
As you say, this isn't very well documented at all so can be quite misleading. The documentation suggests that any password failure will result in onPasswordFailed being called.
ACTION_PASSWORD_FAILED
Action sent to a device administrator when the user has entered an incorrect device or profile challenge password. You can at this point check the number of failed password attempts there have been with DevicePolicyManager.getCurrentFailedPasswordAttempts(). You will generally handle this in onPasswordFailed(Context, Intent, UserHandle).
However, that's not true. onPasswordFailed only appears to be called when the password/PIN/Pattern satisfies the Default Policy. This is different from your minimum password length.
Although I can't find any documentation stating the default policies, it appears to be 4 numbers (PIN), 4 characters (Password) or 4 points (Pattern). Anything less than these will not trigger the call.
For an example, set minimum length to 6 and set your password to 123ABC. Now try to login using the following :-
123 - onPasswordFailed is not called
123A - onPasswordFailed is called
Nice little tester project here you can try this with.
Even though you've probably well and truly moved on from this issue, someone else may gain some clarity.
Cheers.
You can make use of the android.intent.action.USER_PRESENT. This intent will be fired whenever the user unlocks the device. You can register a broadcast receiver which will capture the android.intent.action.USER_PRESENT to detect the device unlock events.

Categories