How to keep the device sensor awake? - java

Using sensors I am detecting motion for some calculations for which I register sensors on a Service.
sensorManager.registerListener(sensorListener, sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION), SensorManager.SENSOR_DELAY_NORMAL);
For this, I am already using a foreground service with notifications to keep the sensor active.
Below is the code I used on the Service class (with higher priority for notification which returns sticky).
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
registerSensor();
Notification notification = new NotificationCompat.Builder(this, ServiceNotification.CHANNEL_1_ID)
.setSmallIcon(R.drawable.ic_stat_name)
.setPriority(NotificationCompat.PRIORITY_HIGH)
//.setCategory(NotificationCompat.CATEGORY_SERVICE)
//.setOngoing(true)
//.setAutoCancel(true)
//.setOnlyAlertOnce(true)
.setColor(getResources().getColor(R.color.colorPrimaryDark))
.setContentIntent(pendingIntent)
.build();
startForeground(13, notification);
return START_STICKY;
}
Android System doesn't kill my app, it runs whole night. But sensor doesn't response until I turn on the screen.
Tried acquiring Wakelock which solves my issue.
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MService: WakeLock");
mWakeLock.acquire();
But I don't want to use WakeLock for such long time.
Is there a way by which I can keep the phone's sensors alive for the long run, or am I doing something wrong with my foreground service/notification?
However, I researched a lot on foreground service with higher priorities.

Related

Android: Can I move a Service between foreground and background? [duplicate]

From the stackoverflow and many blogs, i surely understand that foreground service never run without notification in API>25. But still i confuse that Is notification mandory while app is running on screen or visible.
For eg. no need of notification when user stand within app. So is this possible to remove notification while app running ?
In service class
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
......
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Notification.Builder builder = new Notification.Builder(this, ANDROID_CHANNEL_ID)
.setContentTitle(getString(R.string.app_name))
.setContentText(text)
.setAutoCancel(true);
Notification notification = builder.build();
startForeground(1, notification);
}
return START_NOT_STICKY;
}
In activity
Intent myService = new Intent(this, MyService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(myService);
} else {
startService(myService);
}
It's not possible to remove the notification while the foreground service is running, but it is possible to change your foreground service back into a "regular" service. This removes the need for a notification. In fact, the function to use,
stopForeground(boolean removeNotification)
...includes a removeNotification parameter just for that purpose. You service can switch from being "foreground" to "regular" on demand, by alternating calls to startForeground() and stopForeground().
In case it's not clear, you'd probably want to call stopForeground() whenever you have at least one Activity in a "started" state. This is something you'd have to track manually. Then, when the number of "started" activities reaches 0, you'd call startForeground().
EDIT
One approach is to use a bound service. Then, it's easy to call stopForeground() on it when you want.
Assume you have a single Activity. You can bind it to the service (see this doc or use one of these examples). Then your onServiceConnected() function could look like this (adapted from the Google example):
//MyActivity.java:
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mService.stopForeground(true); //This makes the notification go away
bound = true;
}
...
#Override
protected void onStart() {
super.onStart();
// Bind to the service
bindService(new Intent(this, MyService.class), this, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (bound) {
Notification.Builder builder = new Notification.Builder(this, ANDROID_CHANNEL_ID)
.setContentTitle(getString(R.string.app_name))
.setContentText(text)
.setAutoCancel(true);
Notification notification = builder.build();
mService.startForeground(1, notification); //This brings the notification back! Service is already running, and continues to run.
unbindService(this);
bound = false;
}
}
No, it is mandatory even your app is running in foreground your foreground service need a notification.
You won't able to hide it.
Why :
You can use any other background task handler like intent service, job sclr but things is designed defferent for foreground service your user understand that event i will close this one of it's progress is going to keep running but things is defferent with background service your know it will do something in background but when system decide it's best time to do it not when your app want (as like in foreground service).
One more case ex :
Suppose your app in foreground battery level is lower than expected by user or system your foreground service will execute instantly no matter what so it's important for your user to know this it's running and take my resources (battery, data, etc)
Hopefully you got my mean 🙂

How to open activity (incoming voip call) in Android 10

In Android 10 there apply new restrictions for apps.
We can no longer start an activity from background. While this may be fine for the majority of apps, it's a killing blow for voip-apps that need to show an incoming call after a push notification arrived.
According to this https://developer.android.com/guide/components/activities/background-starts there is a list of conditions that can be met to still allow opening an activity, but tbh I do not understand that fully (non-english-native here).
What I definitely know, is:
I do not have any running activity, task, backstack and the like
The app is NOT EVEN RUNNING
What I need to achieve:
The FCM service of the app receives a push from our server and shall present the incoming call screen (over lock screen and all - just as it did with android 9 and below)
What can I do to open an activity for an incoming voip call in android 10?
Over the lockscreen and all, just as a normal user would expect from a PHONE app.
Thanks in advance for any hints.
To open Activity over lock screen. you can use a high-notification with "full-screen intent" as CommonsWare's answer. But for more detail, you can try my solution as below code:
Create a foreground service then call buildNotification in onStartCommand method, the buildNotification method will return a notification which put into startForeground method parameter.
public class IncomingCallService extends Service {
public int onStartCommand(Intent intent, int flags, int startId) {
Notification notification = buildNotification();
startForeground(1, notification);
return START_NOT_STICKY;
}
}
In buildNotification method, we will create notification with high priority, call category and a full screen intent.
private Notification buildNotification() {
Intent fullScreenIntent = new Intent(this, IncomingCallActivity.class);
PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(this, 0, fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_notification_icon)
.setContentTitle("Incoming call")
.setContentText("(919) 555-1234")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_CALL)
// Use a full-screen intent only for the highest-priority alerts where you
// have an associated activity that you would like to launch after the user
// interacts with the notification. Also, if your app targets Android 10
// or higher, you need to request the USE_FULL_SCREEN_INTENT permission in
// order for the platform to invoke this notification.
.setFullScreenIntent(fullScreenPendingIntent, true);
notificationBuilder.setAutoCancel(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationManager.createNotificationChannel(new NotificationChannel("123", "123", NotificationManager.IMPORTANCE_HIGH));
notificationBuilder.setChannelId("123");
}
Notification incomingCallNotification = notificationBuilder.build();
return incomingCallNotification;
}
In onStartCommand, add a line of code to send ACTION_CLOSE_SYSTEM_DIALOGS broadcast action. This verify IMPORTANT to kick off full screen pending intent.
public int onStartCommand(Intent intent, int flags, int startId) {
Notification notification = buildNotification();
startForeground(1, notification);
sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
return START_NOT_STICKY;
}
Create full screen activity which you want to display over lock screen then you need to add setShowWhenLocked and setTurnScreenOn for display over lock screen. If not, your activity will be displayed behind lock screen. Below is my sample.
public class IncomingCallActivity extends AppCompatActivity {
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_explore);
setShowWhenLocked(true);
setTurnScreenOn(true);
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);
}
}
Now you must start IncomingCallService when you receive a call from your logic.
public void startCallService() {
Intent intent = new Intent(context, IncomingCallService.class);
startForegroundService(intent);
}
You must declare activity, service and some permission in your manifest as below:
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
...>
<activity android:name=".IncomingCallActivity" />
<service
android:name=".IncomingCallService"
android:enabled="true"
android:exported="true" />
</application>
I tested on google, samsung, vsmart phone. It work well. But for xaomi device. you need to enable some permission by flow below steps:
Long click to you app icon
Open app info
Click to "Other permission" item
Allow show on Lock screen
Now your app will work on xaomi device. If you face any problems with my solution, please leave a comment here. I will help you If I could.
Use a high-priority notification with a "full-screen intent". That will:
Invoke your "full-screen intent" if the device is locked
Otherwise, display a "heads-up" notification
Please go through my blog on how to open activity for OS 10 and also how to display heads up notification and handle clicks on the action buttons.
https://medium.com/#dcostalloyd90/show-incoming-voip-call-notification-and-open-activity-for-android-os-10-5aada2d4c1e4
Check this link this will help you
here
or
You need to ask for a permission "draw over other app" then you can make this as previous versions
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
if (!Settings.canDrawOverlays(this)) {
RequestPermission();
}
}
private void RequestPermission() {
// Check if Android P or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Show alert dialog to the user saying a separate permission is needed
// Launch the settings activity if the user prefers
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + BuildConfig.APPLICATION_ID));
startActivityForResult(intent,
ACTION_MANAGE_OVERLAY_PERMISSION_REQUEST_CODE);
}
}
or You can use my this answer
https://stackoverflow.com/a/63699960/7108113

service stops unexpectedly under android 8 (oreo)

I have written and published an app ("Sensor Recording") in the Google Play Store. It's about reading sensor data (such as position, accelerometer, gyroscopes, etc.), displaying them numerically or graphically and storing them into kml and csv files for further processing, e.g with Google Earth or MS Excel. I have established a service to read and process the data in the background even when the screen is switched OFF.
Everything was working fine until Android 8. But in Oreo, the service is stopped automatically by the operating system, approx. 5 minutes after the screen is switched OFF. This has been introduced by Google intentionally to save battery lifetime. I have found some measures in the internet which should avoid that, but nothing worked so far.
What I have done:
1.) in the calling activity I have replaced startService() with startForegroundService()
2.) in the service itself I have made some modifications in onStartCommand() according to the hints I have found.
Tests with wakeLock also led to nothing. Any further ideas are appreciated.
private NotificationManager notMan;
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
// show notification + startForeground
int id = 42;
String channelId = "42";
String text = "Sensors active";
Intent notificationIntent = new Intent(this, SensorService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O)
{
NotificationChannel channel = new NotificationChannel(channelId,
getString(R.string.app_name),
NotificationManager.IMPORTANCE_DEFAULT);
notMan = getSystemService(NotificationManager.class);
notMan.createNotificationChannel(channel);
Notification.Builder builder = new Notification.Builder(this, channelId);
builder.setSmallIcon(R.drawable.vector3d_bg_transp)
.setContentTitle("Sensor Service")
.setContentText(text)
.setTicker(text)
.setSubText("Start Service")
.setShowWhen(true);
notification = builder.build();
}
else
{
notMan = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.vector3d_bg_transp)
.setContentTitle("Sensor Service")
.setContentText(text)
.setTicker(text)
.setSubText("Start Service")
.setPriority(PRIORITY_DEFAULT)
.setShowWhen(true).build();
}
startForeground(id, notification);
return super.onStartCommand(intent, flags, startId); // = 1, same as START_STICKY
} // onStartCommand
Recently, I found the solution – after an essential hint by Thomas Künneth (author of various Android books). The remedy is not in the source code, but in the settings of the smartphone. There is an option to enable background processing. On my Huawei P10 Lite with Android 8.0 it is located in the following menu tree (probably other devices or android versions have similar options):
Settings
Battery
Launch
Select the app in question.
Set the switch from “Manage automatically” to “Manage manually”.
In the pop-up menu set the switch “Run in background”.
That’s it, quite easy – if you know how.
It is remarkable, that Google offers this option, but does not highlight it in lectures about Android 8. Of course, this is consistent with the new policy “Battery first”.

Android background task issue

I am having a background task issue with Service class from Android, Whenever I am starting service from application and return to main menu on my device till then service running properly, but When I will clear all the background application from the recent application list then the service also stops. So how can I manage to avoid such a thing.
The onStartCommand method on your sub IntentService class should return Service.START_STICKY
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//some code...
return Service.START_STICKY;
}
Then the service will keep running in background.
When I will clear all the background application from the recent application list then the service also stops
You can use startForeground() to declare it to be a foreground service. A foreground service must provide a notification for the status bar, which is placed under the "Ongoing" heading, which means that the notification cannot be dismissed unless the service is either stopped or removed from the foreground.
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);

Android is killing my foreground service after Force stop my package

I've been struggling with this for 2 weeks now.
I'm developing an app that controls call duration.
I receive a braodcast where I start a foreground service to hang up the call.
but after five minutes or more android force stop my package then kills my process which cause the service to crash -I think - (don't know why) with no crash message or any kind of error.
it just disappear.
And it Schedules restart but it never start the service again.
here is the logcat
12-29 00:28:52.857 619-619/? I/ActivityManager: Force stopping package club.androidy.callcontrolfree appid=10006 user=0
12-29 00:28:52.858 619-619/? I/ActivityManager: Killing proc 433:club.androidy.callcontrolfree/u0a10006: force stop club.androidy.callcontrolfree
12-29 00:28:52.894 619-619/? W/ActivityManager: Scheduling restart of crashed service club.androidy.callcontrolfree/.PhoneCallService in 5000ms
12-29 00:28:52.919 619-619/? I/ActivityManager: Force stopping service ServiceRecord{422b1b18 u0 club.androidy.callcontrolfree/.PhoneCallService}
using adb shell dumpsys I got this which insures that my service is a foreground service with the right priority
*APP* UID 10088 ProcessRecord{41aefb98 27922:club.androidy.callcontrolfree/u0a10088}
user #0 uid=10088
class=club.androidy.callcontrolfree.AnalyticsApplication
dir=/data/app/club.androidy.callcontrolfree-1.apk publicDir=/data/app/club.androidy.callcontrolfree-1.apk data=/data/data/club.androidy.callcontrolfree
packageList=[club.androidy.callcontrolfree]
compat={240dpi}
thread=android.app.ApplicationThreadProxy#41cef800
pid=27922 starting=false lastPss=0
lastActivityTime=-11s768ms lruWeight=14097791 serviceb=false keeping=true hidden=false empty=true
oom: max=15 hidden=9 client=9 empty=15 curRaw=2 setRaw=2 nonStopping=2 cur=2 set=2
curSchedGroup=-1 setSchedGroup=-1 systemNoUi=false trimMemoryLevel=0
adjSeq=63108 lruSeq=10968
setIsForeground=false foregroundServices=true forcingToForeground=null
lastRequestedGc=-12s74ms lastLowMemory=-12s74ms reportLowMemory=false
Services:
- ServiceRecord{41fb2578 u0 club.androidy.callcontrolfree/.PhoneCallService}
and in Process LRU list (sorted by oom_adj): section
Proc #24: adj=prcp /FS trm= 0 27922:club.androidy.callcontrolfree/u0a10088 (fg-service)
I'm not binding my service to any activities
I start my service like this:
Intent srvIntent = new Intent(context, PhoneCallService.class);
context.stopService(srvIntent);
PhoneCallService.stopService = false;
context.startService(srvIntent);
and this is my onStartCommand :
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Context context = getApplicationContext();
String txtNotificationTicker = context.getString(R.string.strNotificationTicker);
String txtNotificationTitle = context.getString(R.string.strNotificationContexTitle);
String txtNotificationText = context.getString(R.string.strNotificationContexText);
String ns = Context.NOTIFICATION_SERVICE;
Intent cancelIntent = new Intent(this, StopServiceReceiver.class);
PendingIntent pendingIntentCancel = PendingIntent.getBroadcast(this, 0, cancelIntent
, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action action =
new NotificationCompat.Action
.Builder(R.drawable.ic_cancel
, context.getString(R.string.stop_service), pendingIntentCancel)
.build();
Intent mIntent = new Intent(this,MainActivity.class);
int HELLO_ID = 1;
PendingIntent pendingIntent = PendingIntent.getActivity(this, HELLO_ID, mIntent , 0);
this.mNotificationManager = (NotificationManager) getSystemService(ns);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
Notification notification = builder
.setContentIntent(pendingIntent)
.setContentTitle(new StringBuilder(String.valueOf(txtNotificationTitle)))
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(getBitmap(context, R.drawable.ic_launcher))
.setContentText(new StringBuilder(String.valueOf(txtNotificationText))
.append(": ").append(PHONE_NUMBER).toString())
.setWhen(System.currentTimeMillis())
.setPriority(NotificationCompat.PRIORITY_MAX)
.addAction(action)
.build();
notification.flags |= Notification.FLAG_NO_CLEAR;
startForeground(1, notification);
this.pt = new PhoneThread();
this.pt.start();
return Service.START_STICKY;
}
I'm acquiring wake lock like this
if (PhoneCallService.sCpuWakeLock == null) {
PhoneCallService.sCpuWakeLock = ((PowerManager)
context.getSystemService(Context.POWER_SERVICE))
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"CCF");
PhoneCallService.sCpuWakeLock.acquire();
Log.e("androidy","wacklock acquired");
}
I have already tried many solutions from SO and google issues but nothing works for me.
I saw and tried all these :
Foreground service killed by OS
Foreground service gets killed every time
Android foreground service being killed under certain conditions
Foreground Service being killed on Notification click
Foreground service being killed by Android
Users who keep the app are only 30% from total installs.
What I'm doing wrong?
Edit:
If you have the same issue please check Power Saving Options in your phone settings if your phone has this feature it will kill your app after the screen is off and will not allow it to work in background.
Original answer:
After a lot of search I solved it myself
it turned out that my app was power-intensive as shown in the picture below
Hence, android was force stopping it after 5 minutes when there is no activity on the screen to save power.
I solved power consumption issues and everything became OK.

Categories

Resources