in my Android project i've created an custom clock widget with a service which contains an instance of Broadcast Reciever and an intent filter. The Broadcast Reciever provides the update of the widget every time arrives the ACTION_TIME_TICK. This is working perfectly when set targetSdkVersion to 25, in gradle. But if i target to sdk 27, the service stops after few minutes. I've read the documentation about background executions limit in Android O, but i can't find any approach that is useful for my project. Do you have any suggestion?
There are a couple of things you can try which, when used in concert, should be able to cut through all of the idle/standby/doze modes (irrespective of OS version).
Use a WakefulBroadcastReceiver instead of an ordinary BroadcastReceiver. Make sure you include the WAKE_LOCK permission to use it correctly.
Use the setExactAndAllowWhileIdle() method (on API 23 & above) to schedule the Intent for the receiver:
if (Build.VERSION.SDK_INT < 23) {
if (Build.VERSION.SDK_INT >= 19) {
setExact(...);
}
else {
set(...);
}
}
else {
setExactAndAllowWhileIdle(...);
}
Related
The problem seems to be known, but I could not find the right solution.
I will describe the scenario:
There is an application making requests to the API. In some FirstActivity, a request is made to the API, upon positive result of which startActivity () is called in SecondActivity. The problem is that if, while sending the request, the application is minimized to the background (that is, startActivity () will be called in the background), then:
If android version> = 29 then startActivity () basically won't work. The one following startActivity () finish () will work and upon restarting the application will restart (which is logical)
If the android version is < 29, then startActivity () will fire and bring this SecondActivity to the foreground.
Based on this, the question is. How can I force the application, regardless of version, to transition between activities and not bring them to the front?
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
finish();
As per documentation
Android 10 (API level 29) and higher place restrictions on when apps
can start activities when the app is running in the background.
Workaround : In specific situations, your app might need to get the user's attention urgently, such as an ongoing alarm or incoming call. You might have previously configured your app for this purpose by launching an activity while your app was in the background.
To provide similar behavior on a device running Android 10 (API level 29) or higher, complete the steps described in this guide.
you can show a high-priority notification with a full-screen intent.
More Details
Updated answer for new requirement: For your comment
(Well, please tell me how to make startActivity () in the background start the activity also in the background, and not raise the application from the background)
you can add a LifecycleObserver that will be notified when the LifecycleOwner changes state.
Inside your activity api response callback use the following condition
if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
// Activity is in resumed state, Open new activity immediately
} else {
// else add a LifecycleObserver that will be notified when the LifecycleOwner changes state
lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
super.onStart(owner)
// remove observer immediately so that it will not get triggered all the time
lifecycle.removeObserver(this)
// Activity is in start state again, Open new activity here
}
})
}
So I am making an app that has to check for some information, but I need to be able to do that while the app is killed/not actively running. So basically like Youtube's notifications or something. I am a beginner and watched some tutorials on FCM, which can send a notification while the app is killed, which is fine. However, I need to be able to periodically make API calls, check if a certain condition is true and send the notification if so (all of that while app is not running). I tried googling that and found nothing that can help me. So... any ideas? (No code included since I don't think it's relevant.)
If this condition only affects the display of notifications, you can simply check the condition when you receive a notification through FCM. Here's an example :
class FCMService : FirebaseMessagingService()
{
override fun onMessageReceived(message: RemoteMessage)
{
val myCondition = getConditionFromAPI()
if (myCondition) {
showNotification(message)
}
}
}
Use AlarmManager to request periodic runs of your code. It may be set up to broadcast a message time to time to your receiver (declared in AndroidManifest.xml or in your code).
It will work while device is on. To continue after reboot, you have to set up a receiver for Intent.ACTION_BOOT_COMPLETED and register it in your code (not in AndroidManifest.xml, as it no longer works in latest versions of Android).
I have the following code:
https://github.com/lucas-kejan/React-Widget/blob/master/android/app/src/main/java/com/androidwidgetpoc/BackgroundTaskBridge.java#L26
That should add the widget to the android home screen, when the method is called, but it does not work.
It gives me the following error:
lenght = 0; index = 0.
BackgroundTaskBridge.java:31
Well, let's take a look on things that you want to do - let user to pick widget and take a place in launcher. If you want to make it pre Oreo devices, where is no api for following action. So to run PICK_APPWIDGET intent you need appWidgetId. The only way to get appWidgetId by yourself is to bind id to appWidgetInfo, but this thing requires BIND_APPWIDGET permission, which is only available to system. So on pre Oreo device it's impossible to make a thing that you want (of course if you're not a system app).
On Oreo devices we have a new pinning widget api.
AppWidgetManager mAppWidgetManager =
context.getSystemService(AppWidgetManager.class);
AppWidgetProviderInfo myWidgetProviderInfo = new AppWidgetProviderInfo();
ComponentName myProvider = myWidgetProviderInfo.provider;
if (mAppWidgetManager.isRequestPinAppWidgetSupported()) {
// Create the PendingIntent object only if your app needs to be notified
// that the user allowed the widget to be pinned. Note that, if the pinning
// operation fails, your app isn't notified.
Intent pinnedWidgetCallbackIntent = new Intent( ... );
// Configure the intent so that your app's broadcast receiver gets
// the callback successfully. This callback receives the ID of the
// newly-pinned widget (EXTRA_APPWIDGET_ID).
PendingIntent successCallback = PendingIntent.createBroadcast(context, 0,
pinnedWidgetCallbackIntent);
mAppWidgetManager.requestPinAppWidget(myProvider, null,
successCallback.getIntentSender());
}
Don't forget that it requires api version 26+. You can check documentation of following api here
How to continue background service in android Oreo without showing notification dot? i continues my background service using notification but i don't want to show notification for running service.
If you would have read the Android Oreo 8.0 Documentation properly somewhere in here, you might not have posted this question here.
Step 1: Make sure you start a service as a foreground Service as given in below code
ContextCompat.startForegroundService(mainActivity, new Intent(getContext(), GpsServices.class));
ContextCompat.startForegroundService(mainActivity, new Intent(getContext(), BluetoothService.class));
ContextCompat.startForegroundService(mainActivity, new Intent(getContext(), BackgroundApiService.class));
Step 2: Use notification to show that your service is running. Add below line of code in onCreate method of Service.
#Override
public void onCreate() {
...
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForeground(NOTIFICATION_ID, notification);
}
...
}
Step 3: Remove the notification when the service is stopped or destroyed.
#Override
public void onDestroy() {
...
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
stopForeground(true); //true will remove notification
}
...
}
One problem with this solution is that it will keep showing the notification until your Service is running on all devices running on Android Oreo 8.0.
I'm sure that this solution will work even when the app is in the background or in kill state.
IMPORTANT NOTE: SHOWING A NOTIFICATION FOR RUNNING A SERVICE IN BACKGROUND (APP IN BACKGROUND OR KILLED STATE) IS MANDATORY IN ANDROID OREO 8.0. YOU CANNOT RUN AWAY WITH IT. SO IT IS RECOMMENDED THAT YOU MAKE NECESSARY CHANGES IN YOUR APP TO MAKE IT WORK PROPERLY AS PER THE BEST PRACTICES FOLLOWED OR ASKED BY ANDROID.
I hope this might help to solve your problem.
This isn't possible in this API version (26) and higher. Android OS automatically close your service if you run it without showing a notification to the user.
If you are targeting API >= 26 the system will impose a restriction on your service to run in background unless your activity in foreground. As soon as your activity goes to background, the service will be terminates when system finds it running in background (See Background service limitations).
By using startForegroundService() method you grant that permission to run the service in background even when the activity isn't running.
Must also once the service has been created, the service must call its startForeground() method within five seconds.
This code worked for me. First you make sure :
1- Define the service in Manifest
2- Define the permission in Manifest
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
3- Make sure you have started the service before.
Your service should have a notification. You should be careful that
your notification must have a ChannelID !
this page can help you:
How to create a Custom Notification Layout in android?
Android how to show notification on screen
Now paste the following code into your service
#Override
public void onCreate() {
super.onCreate();
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForeground(" your Notification ID ", notification);
}
} catch (Exception e) {
Log.e(" Error --->> ", e.getMessage());
}
}
after that add this code:
#Override
public ComponentName startForegroundService(Intent service) {
return super.startForegroundService(service);
}
and this:
#Override
public void onDestroy() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
stopForeground(true);
}
}
I'm learning how to make apps for android and I have started by creating one which makes my phone scream when its dropped.
I got it working to where the phone screams when dropped, but now I need to make it so that the phone screams when dropped even when the app is closed, and to show a notification in the notification bar saying that its running
What should I use to do this? Should I use intentService? Ive been looking all over and I'm not sure where to look. Any guides would be appreciated
You need to make your service run in the foreground. You can achieve this by showing a notification when your service is running.
This is how you need to make your service run as foreground
private void showNotification(String title)
{
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(title);
startForeground(1000,mBuilder.build()); // 1000 - is Id for the notification
}
You can also set your custom RemoteViews in notification using setContent
You can remove the service from foreground state using stopForeground
check Service Training.
For your use case it's important that it's an foreground service:
Documentation Service