I have a simple React Native app, with a single activity MainActivity. The app is meant to be used for an online orders system, so it's meant to be "on" all the time. When the app receives a notification I want to open the app if killed, and bring to the foreground if in background. I have made this work in the past with the example code below but it doesn't work anymore, I don't know if it's an Android API change or what. Please also note I'm not an Android developer so bear that in mind.
I'm using OneSignal and here is my notification received handler:
public class SignalReceiver implements OneSignal.OSRemoteNotificationReceivedHandler {
#Override
public void remoteNotificationReceived(Context context, OSNotificationReceivedEvent notification) {
Intent intent = new Intent(context, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
context.startActivity(intent);
Log.d("ONESIGNAL", "OPENED??");
}
}
and this is my AndroidManifest.xml excerpt. The only relevant part should be the <meta-data> tag as that was added as per OneSignal documentation, but pasting other parts in case relevant:
<application
android:name=".MainApplication"
android:label="#string/app_name"
android:icon="#mipmap/ic_launcher"
android:roundIcon="#mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="com.onesignal.NotificationServiceExtension"
android:value="com.packagename.SignalReceiver"
/>
</application>
The log message display in Logcat in Android Studio so the code is running all fine. I also get a notification 30 seconds after the log shows, so that is also very odd!
I have noticed com.onesignal.NotificationServiceExtension doesn't actually exist if I try to import in code, but I don't know if it's meant to.
Can someone see any problem with my code, and if yes how can I get it to bring the app to foreground?
Edit
I've tried this code in Android versions 11 and 12 on Samsung devices. Standard devices, not kiosk or managed.
I also just noticed if the app has been closed for a few minutes (over 5 minutes) then the app does indeed open up. But not if it's been used recently.
Related
class AlarmReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Toast.makeText(context,"Ready to wake up?", Toast.LENGTH_LONG).show()
val myIntent = Intent(context,AlarmActivity::class.java)
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(myIntent)
}
}
Manifest:
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.QuickNap">
<activity android:name=".AlarmActivity"
android:screenOrientation="portrait"
android:theme="#style/Theme.NoActioBar"
android:windowSoftInputMode="adjustResize"></activity>
<!-- <receiver-->
<!-- android:name=".AlarmReceiver"-->
<!-- android:process=":remote" />-->
<receiver android:name=".AlarmReceiver"
android:enabled="true"
android:exported="true"
android:process=":remote">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="android.intent.action.REBOOT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity
android:name=".MainActivity"
android:screenOrientation="portrait"
android:theme="#style/Theme.NoActioBar"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
MainActivity:
onTimer = true;
moonImage.setColorFilter(null)
val mIntent = Intent(this, AlarmReceiver::class.java)
val mPendingIntent = PendingIntent.getBroadcast(this, 0, mIntent, PendingIntent.FLAG_UPDATE_CURRENT)
val calendar = Calendar.getInstance()
calendar.add(Calendar.SECOND, minuteSet)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,calendar.timeInMillis,mPendingIntent)
}
else
{
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.timeInMillis, mPendingIntent)
}
hi, i am trying to create a alarm android app using kotlin .
so i created a Reciever, in that reciever i am switching on a activity and in that activity i am playing Sound.
this code works fine as intended on emulator. but on device (Redmi Note 7 pro, MIUI OS). it only works when screen is on and if the app is open.
any idea on how to make sure it switches the screen on when this receiver is invoked?
also i am new to android development, so ELI5. ty
There are plenty of reasons why you cannot bring the app to the foreground. Let's break it down and solve it accordingly:
1- Stock OS Restrictions: : Android is known for the increasing restriction on background tasks. MIUI even surpassed that with more restriction due to their "Battery Optimization" algorithm. First of all, make sure you inform the user that the app CANNOT run in the background or be brought to the foreground if the MIUI Battery Optimization is enabled. Therefore, give the user the ability to go to the Battery Saver option in app's options by giving him a one-click intent. Sadly, there is no programmatic work-around. You can see here a list of manufacturers that enforce their battery saving policies: Don't kill my app!
Xiaomi is not the only manufacturer you have to worry about.
2- Android 10 (API 29) Restrictions: Starting from this particular API, apps can NO LONGER jump to the foreground from the background. Google started putting a lot of restrictions on a lot of permissions and features. Please read more here about which conditions have to be met in order to be able to launch the app that is running in the background: Restrictions on starting activities - API 29
What can you do: You can mess around with different flags and categories as well as parameters to add to the manifest. For example, if you haven't added this permission, make sure you do now:
QUOTED FROM THE LINK ABOVE:
...
The app should be granted the SYSTEM_ALERT_WINDOW permission by the user.
...
You can also try to add different flags and categories, this MAY WELL NOT work, but you can still try and fiddle especially with these two lines:
intent.addCategory(Intent.CATEGORY_LAUNCHER) //You can always add and remove categories
intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
Your best solution yet: You can always inspect an open-source project and see how they dealt with this particular issue. One of my favorites has to be this one: AlarmClock FOSS on GitHub by yuriykulikov
Best of luck.
Go to Settings/Apps/manage apps and select your application then select battery saver and make sure it is on "No restrictions" so your app can run in the background without any restrictions.
If it worked, you should teach the user to do that. write an intent to open the settings and so on.
I'm building an android application, which has a service, the service keeps running even if the app is killed by the user, I use this service to do some calculations, and send and receive data to the server, sometimes I use this service to relaunch the application, my application uses only landscape orientation. I used this code in AndroidManifest.xml:
<activity
android:name="com.myapp.MainActivity"
android:configChanges="orientation|screenSize"
android:label="#string/app_name"
android:screenOrientation="landscape"
android:theme="#android:style/Theme.Black.NoTitleBar.Fullscreen"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
However, when the app is killed by the user, and the user locked the mobile, it works, but it runs in portrait orientation.
I use this piece of code to run the app in the service:
bringToForegroundIntent = new Intent(AppContext.getContext(), MainActivity.class);
bringToForegroundIntent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED |
Intent.FLAG_ACTIVITY_NEW_TASK);
locSaveService.startActivity(bringToForegroundIntent);
I tried to solve this issue by deleting portrait XML layout from the app, but it throws an exception. Any Ideas?
Thanks
When i download my app from store.
its installed on main screen, and on apps menu ( when i click the circle with 6 dots on it )
when i click from main screen it opens an app, and when i click from the other place..it opens a second app as well.
i need one app running only..
how can this be fixed?
my manifest
<application
android:name="dfsfsdp"
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".StartupActivity"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
I think you aren't running multiples instances (if you are running multiple instances if fail of the mobile), or you see two applications open in the menu what you use to close the running apps (the recent applications menu)?
If you only see one maybe your are restarting the same instance. Look at your StartupActivity or post here to try help you.
If this don't help you, take a look at to read about the lifecycle of an Activity:
http://developer.android.com/training/basics/activity-lifecycle/index.html
Best regards.
I bet it's repeated question but I need to ask it again. Service cannot start even I've put following code
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name=".MyBroadcastreceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<activity
android:name="com.im.HomeActivity"
android:clearTaskOnLaunch="true"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.im.ListActivity"
android:label="#string/title_activity_list" >
</activity>
<service
android:name="com.im.SyncService"
android:process=":remote" >
</service>
</application>
and
public class MyBroadcastreceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent arg1) {
Intent intent = new Intent(context, SyncService.class);
context.startService(intent);
Log.i("Autostart", "started");
}
}
Help me, please.
Is your BraodcastReciever getting invoked?
if not then the reason could be following:
Starting with 3.1 when applications are installed they are in a
“stopped” state so they will not be able to run until the user
explicitly launches them. Pressing Force Stop will return them to this
state.
once the user runs the app for the first time (and does not Force Stop
it), everything behaves as before — a reboot will cause BOOT_COMPLETED
broadcasts to be received and so on. However, if the user installs the
app, until and unless they run the app manually, no broadcasts will be
received.
So in your case you will have to create launcher activity and make sure you start that launcher activity at least once then you will start receive boot event broadcast.
Source
Starting from Android 3.1, a user must start the application at least once before your application can receive android.intent.action.BOOT_COMPLETED events.
Also android:allowBackup="true" is set in your manifest file, make sure the App is not installed on the SD card. If you are saving to external storage, you will need to setandroid.intent.action.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE instead.
On some phones(like HTC) there is a Fast Boot option, If it is activated, The BOOT_COMPLETE will not be invoked.
Another approach would be to use Intent.ACTION_SCREEN_ON and check if service is running, if it isn't, then start the service. More info available here
I have a basic Android application that is supposed to reboot the phone continuously a set number of times. In order to do this, I need the application to be started upon phone startup. In order to that, I essentially followed the instructions found here, adding the permissions to the manifest and creating a BroadcastReceiver class that starts the activity. Here is some of my relevant code:
public class StartMyServiceAtBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
System.out.println("StartMyServiceAtBootReceiver called.");
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
// Intent activityIntent = new Intent("com.example.rebooter.MainActivity");
Intent activityIntent = new Intent(context,MainActivity.class);
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(activityIntent);
}
}
}
From the manifest file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rebooter"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</activity>
<service
android:name=".RebootManager"
android:label="Reboot Manager" >
<action android:name="com.example.rebooter.RebootManager" />
</service>
<receiver android:name=".StartMyServiceAtBootReceiver"
android:enabled="true"
android:exported="true"
android:label="StartMyServiceAtBootReceiver" >
<action android:name="android.intent.action.BOOT_COMPLETED" />
</receiver>
</application>
In the Eclipse emulator, the application appears to be working properly. That is, though my emulator isn't rooted and the phone doesn't execute the reboot commands correctly, I do see that, upon startup, the correct activity is started.
Now, when I'm trying it on a particular system running Android 4.0.4, everything in the application is working properly EXCEPT boot upon startup. Any ideas?
I tried to eliminate the possibility of any hardware problems (since I'm not using a commercially-released phone) by installing another application that boots upon startup and confirming that it does indeed boot upon startup, and it does indeed show up under running apps as a cached process after startup.
I would appreciate any help. Let me know if you need any additional information.
There are a number of issues here.
First, you neglected to post StartMyServiceAtBootReceiver, the component you are expecting to get control at boot time, so we cannot comment on whether there are any particular problems with it.
Second, unless something has explicitly executed one of your components (e.g., the user launched MainActivity from the home screen), StartMyServiceAtBootReceiver will never be invoked, on Android 3.1+. Make sure you run your activity before trying a reboot, and see if that helps.
Third, you implemented a constructor on StartupManager, which is a bad idea. Please move this logic to onCreate().
Fourth, your code will likely crash in that constructor, as getApplication() will not return a valid value at this point in the code, particularly since you failed to chain to the superclass' constructor. Again, moving this code to onCreate() will help here.
Fifth, starting an activity from onCreate() of a service (let alone its constructor) is very unusual and may not be appreciated by the user. Moreover, if that service is not doing anything else, you could just as easily start that activity from StartMyServiceAtBootReceiver and skip StartupManager entirely.
Sixth, you have <intent-filter> elements on your services, as if you are expecting third party developers to invoke those services. If that is the case, fine. If not, please remove the <intent-filter> elements and use explicit Intents within the rest of your app code to refer to them (e.g., new Intent(this, StartupManager.class)), for better security. Or, add android:exported="false" to those services, though that is automatic if you remove the <intent-filter> elements.