Execute a piece of code on certain Battery Level in Android - java

I'm looking for a way of executing a piece of code within my Android application when the phone reaches 10% battery life. Would anyone be able to point me in the right direction of how to do so?

Get battery level in percentage
Intent batteryIntent = registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
float levelPert;
int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
// Error checking that probably isn't needed but I added just in case.
if(level == -1 || scale == -1) {
levelPert = 50.0f;
}
levelPert = ((float)level / (float)scale) * 100.0f;
P.S. As mentioned in the documentation that BatteryManager is sticky intent, so there is no need to add manifest declaration.
You can read more about getting Battery details here

From developer.android.com :
You can't easily continually monitor the battery state, but you don't need to.
Generally speaking, the impact of constantly monitoring the battery level has a greater impact on the battery than your app's normal behavior, so it's good practice to only monitor significant changes in battery level—specifically when the device enters or exits a low battery state.
From this link

Write one receiver for getting the battery level like this:
public class BatteryReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
if (level < 10) {
// Write your code here
}
}
}
Write One Service:
public class BatteryService extends Service {
private BatteryReceiver receiver;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
receiver = new BatteryReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(receiver, filter);
}
#Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
}
Register this service in your Manifest file like this:
<service android:name="com.example.testandroid.BatteryService" >
</service>
then start the service in First Activity is Enough.

Related

LocationListener doesn't provide update after sometime in android service

I am writing an application where I need to get the location updates really fast from background.
Hence, I've written a service to achieve the required outcome.
I am starting the service from an activity's onCreate() method.
The problem I am facing is, the service is able to provide location update for about 20 to 30 seconds from the time of activation of service. Then I am not getting any updates.
Here is the code for the service:
public class MyLocService extends Service
implements
LocationListener{
private final LocationListener locationListener = this;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Handler handler = new Handler(Looper.getMainLooper());
Runnable runnable = new Runnable() {
#Override
public void run() {
if (checkPermission()) {
manager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
manager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
}
else{
//Request Permission
Intent permissionIntent = new Intent();
permissionIntent.setAction(LOCATION_PERMISSION_REQUIRED);
sendBroadcast(permissionIntent);
}
Looper.loop();
}
};
handler.post(runnable);
//Create notification nad run in foreground
startForeground(
NotificationCreator.getNotificationId(),
NotificationCreator.getNotification(context)
);
return Service.START_STICKY;
}
#Override
public void onLocationChanged(Location location) {
Log.d("LocUpdate", location.getLatitude() + " : " + location.getLongitude());
}
Every time I start the service from the activity like :
Intent intent = new Intent(this, MyLocService.class);
startService(intent);
I get updates in the onLocationChange() for 20 to 30 seconds.
Another observation is : if I keep the activity (from where I am starting the service open and visible) then I continue to get the location updates.
However when I close the activity or kill the app and allow the service (alone) to run in the background, I am not getting any location updates although the service is running as I can see the notification at the top of my screen.
What am I doing wrong?
I've solved the problem. Turn off the battery optimization in miui or add the app as exception. Code works perfectly.

Android Service to check whether the user screen on or off

Is there any way to create a service that runs forever on a background for Android user to check whether their screen on or off, etc?
I'm about to create an analytics, so I need to know when the user turn on or turn off their screen.
Thanks, I will appreciate all the input
You may use Android broadcast receiver to detect screen on and off.
Here is a good example of it
https://thinkandroid.wordpress.com/2010/01/24/handling-screen-off-and-screen-on-intents/
you may also follow this thread
https://stackoverflow.com/a/9478013/2784838
You need to create broadcast receiver and manage screen on or off status.
Declare receiver in manifest:
<receiver android:name=".DeviceWakeUpReceiver" />
public class DeviceWakeUpReceiver extends BroadcastReceiver {
private static final String TAG = "DeviceWakeUpService";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive() called");
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
//End service when user phone screen off
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
//Start service when user phone screen on
}
}
}
You cannot use a BroadcastReceiver for receiving screen off/on events.
Write a intent service which is started via boot complete listener and register for Intent.ACTION_SCREEN_OFF and Intent.ACTION_SCREEN_ON.
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
registerReceiver(new ScreenOffOnReceiver(), filter);
class ScreenOffOnReiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
// Screen OFF
else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
// Screen ON
}
}
}

calling BroadcastReceiver from Activity

I am newbie in android programming; sorry if my question is easy :)
I'm trying to write code that monitors the battery level on the phone and if it is, lower some level for example (%15), create a message that asks user to plug the charger. I know that I need to use BroadcastReceiverclass and I want to use it in my MainActivity class. Here is the code I have:
public class MainActivity extends Activity{
BroadcastReceiver br = new BroadcastReceiver() {
#Override
public void onReceive(final Context context, Intent intent) {
String intentAction = intent.getAction();
Log.d("receiver", intentAction);
int level = intent.getIntExtra("level", 0);
if (level < 15){
Log.d("receiver", "battery level low");
}
if (Intent.ACTION_BATTERY_OKAY.equalsIgnoreCase(intentAction)) {
Log.d("receiver", "battery level okay");
}
}
};
......
but it seems that the onReceivemethod is never called since I never see the Log.d("receiver", intentAction) message on Android Studio debug window.
I also have registered br in onResume and unregistered it in onPause:
public void onResume() {
super.onResume();
filter.addAction("receiver");
registerReceiver(br, filter);
}
public void onPause() {
super.onPause();
unregisterReceiver(br);
}
But still I am not getting any message.
Can anybody please help me? Should I also add something to AndroidManifest.xml?
If you dont want to use BroadcastReceiver simply dont use it. Battery intent is sticky intent so you can check it without need of BroadcastReceiver and i also dont think its good idea to put receiver in activity. You can check battery stuff in your activity like this and you dont need to edit your manifest
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent batteryStatus = context.registerReceiver(null, filter);
int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
float batteryPct = level / (float)scale;
if(batteryPct < 15){
//do your stuff
}
Your code in onResume() is wrong. You will have to update it as follows.
filter.addAction(Intent.ACTION_BATTERY_LOW);
filter.addAction(Intent.ACTION_BATTERY_OKAY);
registerReceiver(br, filter);
to include the ACTION_BATTERY_LOW and ACTION_BATTERY_OKAY filters as mentioned in the docs.

EventListener for Power Button press in a Service

I want to listen the power key event in the service.
How can in do that ?
Currently I am working with an app, where I need to listen the power button for some events, from a service which is running in a background, even when the app is killed or stopped.
Somehow I can manage to get it.
But when I kill/stop the app, the service is getting stopped.
How can i overcome this ?
Currently the code i am using this :
Service Class:
public class SampleService extends Service
{
SettingContentObserver mSettingsContentObserver;
AudioManager mAudioManager;
private ComponentName mRemoteControlResponder;
private Intent intent;
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.v("StartServiceAtBoot", "StartAtBootService -- onStartCommand()");
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
#Override
public void onStart(Intent intent, int startId) {
boolean screenOn = intent.getBooleanExtra("screen_state", false);
if (!screenOn) {
Toast.makeText(getApplicationContext(), "On", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "Off", Toast.LENGTH_SHORT).show();
}
}
public void onCreate()
{
mSettingsContentObserver = new SettingContentObserver(this,new Handler());
getApplicationContext().getContentResolver().registerContentObserver
(android.provider.Settings.System.CONTENT_URI, true, mSettingsContentObserver );
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
mRemoteControlResponder = new ComponentName(getPackageName(),
StartAtBootServiceReceiver.class.getName());
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
BroadcastReceiver mReceiver = new StartAtBootServiceReceiver();
registerReceiver(mReceiver, filter);
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
public void onDestroy()
{
getApplicationContext().getContentResolver().unregisterContentObserver(mSettingsContentObserver);
}
}
BroadcastReceiver Class:
public class StartAtBootServiceReceiver extends BroadcastReceiver
{
static boolean wasScreenOn;
private boolean screenOff;
public void onReceive(Context context, Intent intent)
{
if(intent.getAction().equals(Intent.ACTION_SCREEN_OFF))
{
wasScreenOn = false;
Toast.makeText(context, "Power Off", Toast.LENGTH_SHORT).show();
}
else if(intent.getAction().equals(Intent.ACTION_SCREEN_ON))
{
wasScreenOn = true;
}
Intent i = new Intent(context, SampleService.class);
i.putExtra("screen_state", screenOff);
i.setAction("com.example.antitheft.SampleService");
context.startService(i);
//
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Intent i1 = new Intent();
i1.setAction("com.example.sampleonkeylistener.MainActivity");
context.startService(i1);
}
}
}
given above is the sample code and i have created AndroidManifest.xml files also with user's permission but i cannot get the app continue service if it is killed or stopped.
Thanks in Advance.
#Override
public void onDestroy() {
super.onDestroy();
startService(new Intent(this, SampleService.class));
}
This is one way to ensure that service will never stop even user want to destroy it.
This is one Just ONE of ways to achieve what you are trying to achieve.
Secondly, you can try and run service in "foreground" by using startForeground().
Also, make sure that in you return "START_STICKY" (which you are doing in the sample code that you shared and I trust that you are also doing in App's code too :) ) in Services's onStartCommand().
This will ensure that If this service's process is killed while it is started (after returning from onStartCommand(Intent, int, int)), then leave it in the started state but don't retain this delivered intent. Later the system will try to re-create the service.
And you may find some additional pointers/hints to make sure your service is not stopped at below link.
How can we prevent a Service from being killed by OS?
Just pick and choose the approach that best suits YOUR Need/implementation.

Android Service needs to run always (Never pause or stop)

I created a service and want to run this service always until my phone restarts or force closed. The service should run in background.
Sample code of created service and start services:
Start the service:
Intent service = new Intent(getApplicationContext(), MyService.class);
getApplicationContext().startService(service);
The service:
public class MyService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO do something useful
HFLAG = true;
//smsHandler.sendEmptyMessageDelayed(DISPLAY_DATA, 1000);
return Service.START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// TODO for communication return IBinder implementation
return null;
}
}
Manifest declaration:
<service
android:name=".MyService"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
</service>
Is it possible to run this service always as when the application pauses and anything else.
After some time my application goes pause and the services also go pause or stop.
So how can I run this service in background and always.
"Is it possible to run this service always as when the application pause and anything else?"
Yes.
In the service onStartCommand method return START_STICKY.
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
Start the service in the background using startService(MyService) so that it always stays active regardless of the number of bound clients.
Intent intent = new Intent(this, PowerMeterService.class);
startService(intent);
Create the binder.
public class MyBinder extends Binder {
public MyService getService() {
return MyService.this;
}
}
Define a service connection.
private ServiceConnection m_serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
m_service = ((MyService.MyBinder)service).getService();
}
public void onServiceDisconnected(ComponentName className) {
m_service = null;
}
};
Bind to the service using bindService.
Intent intent = new Intent(this, MyService.class);
bindService(intent, m_serviceConnection, BIND_AUTO_CREATE);
For your service you may want a notification to launch the appropriate activity once it has been closed.
private void addNotification() {
// create the notification
Notification.Builder m_notificationBuilder = new Notification.Builder(this)
.setContentTitle(getText(R.string.service_name))
.setContentText(getResources().getText(R.string.service_status_monitor))
.setSmallIcon(R.drawable.notification_small_icon);
// create the pending intent and add to the notification
Intent intent = new Intent(this, MyService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
m_notificationBuilder.setContentIntent(pendingIntent);
// send the notification
m_notificationManager.notify(NOTIFICATION_ID, m_notificationBuilder.build());
}
You need to modify the manifest to launch the activity in single top mode.
android:launchMode="singleTop"
Note that if the system needs the resources and your service is not very active it may be killed. If this is unacceptable bring the service to the foreground using startForeground.
startForeground(NOTIFICATION_ID, m_notificationBuilder.build());
In order to start a service in its own process, you must specify the following in the xml declaration.
<service
android:name="WordService"
android:process=":my_process"
android:icon="#drawable/icon"
android:label="#string/service_name"
>
</service>
Here you can find a good tutorial that was really useful to me
http://www.vogella.com/articles/AndroidServices/article.html
Hope this helps
If you already have a service and want it to work all the time, you need to add 2 things:
in the service itself:
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
In the manifest:
android:launchMode="singleTop"
No need to add bind unless you need it in the service.
A simple solution is to restart the service when the system stops it.
I found this very simple implementation of this method:
How to make android service unstoppable
You can implement startForeground for the service and even if it dies you can restart it by using START_STICKY on startCommand(). Not sure though this is the right implementation.
I found a simple and clear way of keeping the Service running always.
This guy has explained it so clearly and have used a good algorithm. His approach is to send a Broadcast when the service is about to get killed and then use it to restart the service.
You should check it out: http://fabcirablog.weebly.com/blog/creating-a-never-ending-background-service-in-android
You don't require broadcast receiver. If one would take some pain copy one of the api(serviceconnection) from above example by Stephen Donecker and paste it in google you would get this, https://www.concretepage.com/android/android-local-bound-service-example-with-binder-and-serviceconnection
Add this in manifest.
<service
android:name=".YourServiceName"
android:enabled="true"
android:exported="false" />
Add a service class.
public class YourServiceName extends Service {
#Override
public void onCreate() {
super.onCreate();
// Timer task makes your service will repeat after every 20 Sec.
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
// Add your code here.
}
});
}
};
//Starts after 20 sec and will repeat on every 20 sec of time interval.
timer.schedule(doAsynchronousTask, 20000,20000); // 20 sec timer
(enter your own time)
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO do something useful
return START_STICKY;
}
}
I had overcome this issue, and my sample code is as follows.
Add the below line in your Main Activity, here BackGroundClass is the service class.You can create this class in New -> JavaClass (In this class, add the process (tasks) in which you needs to occur at background). For Convenience, first denote them with notification ringtone as background process.
startService(new Intent(this, BackGroundClass .class));
In the BackGroundClass, just include my codings and you may see the result.
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.provider.Settings;
import android.support.annotation.Nullable;
import android.widget.Toast;
public class BackgroundService extends Service {
private MediaPlayer player;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
player = MediaPlayer.create(this,Settings.System.DEFAULT_RINGTONE_URI);
player.setLooping(true);
player.start();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
player.stop();
}
}
And in AndroidManifest.xml, try to add this.
<service android:name=".BackgroundService"/>
Run the program, just open the application, you may find the notification alert at the background. Even, you may exit the application but still you might have hear the ringtone alert unless and until if you switched off the application or Uninstall the application. This denotes that the notification alert is at the background process. Like this you may add some process for background.
Kind Attention: Please, Don't verify with TOAST as it will run only once even though it was at background process.
Hope it will helps...!!

Categories