I have a mobile app (kotlin/android studio) does not have an activity openned. This is a background service.
My app is connected by socket with my server. Via this server, I can ask to the mobile app to start an another app.
I found the code to do that and this works well. But I have a problem. I need to turn on my screen when I start a new app.
I have seen many solutions with different flags to setwith getWindow(). But getWidnow() works only on an activity class.
So can I turn on the screen in a class which does not inherit "Activity"?
If this is possible, can you explain me how?
Thank you.
var intent = contextTmp.packageManager.getLaunchIntentForPackage(packageName)
if (intent == null) {
// Bring user to the market or let them choose an app?
intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse("market://details?id=$packageName")
}
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
contextTmp.startActivity(intent)
Related
I am using react-native-notifications version 4.2.4 on React Native 0.64.1. I have also tried on react-native-notifications version 4.3.1 on React Native 0.67.
Steps
Hard close the app.
Open a notification. getInitialNotification() is
populated. The app will open the first screen, then navigate to a
screen with the notification details.
Press the hardware back button
twice (at this point the app has been exited)
Open the app from the app tray.
Expected Result
onNotificationOpened() event listener is not fired and the first screen of the app is shown
Actual Result
onNotificationOpened() event listener is fired and step 2 happens.
If I comment out the call to callOnOpenIfNeed() in onActivityStarted() in RNNotificationsPackage.java, this only happens the first time after the app is hard closed. I believe that this function is causing the issue to happen and notification.onOpened() is being called incorrectly as the Intent.getExtras() should not have the notification object.
See below for reference:
private void callOnOpenedIfNeed(Activity activity) {
Intent intent = activity.getIntent();
if (NotificationIntentAdapter.canHandleIntent(intent)) {
Context appContext = mApplication.getApplicationContext();
Bundle notificationData = NotificationIntentAdapter.cannotHandleTrampolineActivity(appContext) ?
NotificationIntentAdapter.extractPendingNotificationDataFromIntent(intent) : intent.getExtras();
final IPushNotification pushNotification = PushNotification.get(appContext, notificationData);
if (pushNotification != null) {
pushNotification.onOpened();
}
}
}
I have seen this on Android versions 9-12.
I am using Firebase (FCM) to show Push Notifications to the user and I am running into a weird problem.
The code I have works for the following scenarios (using FirebaseMessagingService):
App in foreground - Receiving data in onReceive() and showing a popup inside app.
App in background - Receiving data in onReceive() and showing a notification for the user. If this is clicked the app will be brought back to front. The intent from this is received in LauncherActivity followed by a finish() call which takes me to whatever activity I already had open.
App completely closed - same as background. App will be started and intent will be handled in LauncherActivity before calling finish() on that.
And here is where it gets interesting:
App completely closed -> open it through notification (intent received in LauncherActivity) -> put the app in background and send another notification -> when this notification is clicked the LauncherActivity is completely ignored (onCreate is no longer called) and I get taken straight to whatever activity I already had. The intent here has no extras or categories.
Why is LauncherActivity being bypassed in this specific case? Keep in mind that this works fine if the app was initially started normally (not by clicking on a notification)
Intent mainIntent = getPackageManager().getLaunchIntentForPackage(getPackageName());
if (mainIntent != null) {
mainIntent.addCategory(NOTIFICATION_CATEGORY);
mainIntent.putExtra(.........);
}
PendingIntent pendingMainIntent = PendingIntent.getActivity(this, SERVICE_NOTIFICATION_ID, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, context.getString(R.string.default_notification_channel_id));
notificationBuilder.setContentIntent(pendingMainIntent);
//.....icon, color, pririty, autoCancel, setDefaults, setWhen, setShowWhen, contentText, setStyle
NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
getString(R.string.default_notification_channel_id),
getString(R.string.default_notification_channel),
NotificationManager.IMPORTANCE_HIGH
);
notificationManager.createNotificationChannel(channel);
notificationBuilder.setChannelId(getString(R.string.default_notification_channel_id));
}
notificationManager.notify(SERVICE_NOTIFICATION_ID, notificationBuilder.build());
}
I'd appreciate any ideas. Thank you.
When you launch an app for the first time, Android remembers the Intent that was used to launch it. Normally, when you launch an app from the HOME screen, this is an Intent that contains ACTION=MAIN and CATEGORY=LAUNCHER. If your app then goes to the background (for whatever reason), and the user later taps the icon on the HOME screen, the same launch Intent is used. Android matches this against the Intent used to launch the app for the first time, and if these match, Android doesn't launch a new Activity, it just brings the task containing the app from the background to the foreground in whatever state it was in when it got moved to the background. Under normal circumstances, this is exactly the behaviour that you want (and that the user expects).
However, when the app is launched for the first time from a Notification, this can mess things up. In your case, this is what you are seeing. You launch the app from a Notification and Android remembers the Intent used (from the Notification), when you later launch the app (again from a Notification), android matches the Intent in the Notification with the Intent used to launch the app for the first time, and thinks you want to bring the existing app task from the background to the foreground.
There are several ways to deal with this, depending on the behaviour that you want to have. The best thing to do is probably not to launch your root Activity (the one with ACTION=MAIN and CATEGORY=LAUNCHER) from the Notification. Instead launch a different Activity and have that Activity determine what it should do next (ie: redirect to the root Activity or something else, depending on the state of your app). You should also set the NO_HISTORY and EXCLUDE_FROM_RECENTS flags on the Intent that you put in the Notification. This will ensure that Android won't remember this Intent as the one that launched the app.
https://developer.android.com/preview/privacy/background-activity-starts
From this, it results that my payment app, which shows an Activity when a NFC transaction is performed, will not be able anymore to show anything to the user.
Has anyone have a clue what would be the new approach ?
Thanks!
I currently use the NFC service and it starts an Activity intent.
Intent intent = new Intent(mApplicationContext, PaymentActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
mApplicationContext.startActivity(intent);
The Activity should be shown. It works now, but from Android Q, it won't
According to the link, if you are having a HostApduService, then your app should work the same in Android Q.
If that is not your case, the simplest work around is to get "Draw over other apps" permissions. You can open activities if the app has been granted the SYSTEM_ALERT_WINDOW permission by the user. I have tested this and working.
Technically, you are showing something on top of other apps without user's interaction, so this might be the right way to go.
I just recently added the capability of my app to check for updates on our local server (this app is not published in the Google Play store. It's going to be used internally and there is no internet connection where it will be used. Don't ask. That's how it is :) ). I keep track of updates by checking a certain table in SQL Server and if my app's version is lower than what is indicated in this table, I download the new APK from an internal website (LAN only) then install the APK. I also have another application in the device that listens for PACKAGE_ADDED broadcasts. I can capture the broadcast successfully.
The problem is, after installation, the broadcast receiver starts the app by calling the following.
public class PackageInstalledBroadcastReceiver extends BroadcastReceiver {
private final String MY_PACKAGE_NAME = "com.company.packagename";
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED)) {
String packageName = intent.getData().getSchemeSpecificPart();
if (packageName.equalsIgnoreCase(MY_PACKAGE_NAME)) {
Intent i = new Intent();
i.setClassName(MY_PACKAGE_NAME, MY_PACKAGE_NAME + ".LoginActivity");
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
}
}
But it takes a long time for the app to start. The user might think that nothing is happening, so he/she can start the app manually by clicking the app's icon. If the user clicks the app's icon, the app starts immediately. After a while, the activity that the broadcast receiver started is also opened. So now, I end up with two instances of my app in the same activity (LoginActivity). I can say that this is the case, because if I press the Back key on the device from the LoginActivity, I still end up in another LoginActivity and if I press the Back key again, I end up on the device's desktop.
You have two problem in your question:
The fist, why your BroadcastReceiver take a long time to start your activity.
It have not enough information for stoving this.
The second your want to make your activity have a single instance.
Android provide a way to do that:
Step one: Visit your application androidmanifest file
Step two: Find your activity declaration.
Step there: Add the following property android:launchMode = "singleInstance"
The reference here:
P/s: If you could provide my some more information of your fist problem. Please create a new question. Hope you resolve it.
Currently I have a button that when pushed calls the Intent below.
Intent sharingIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
sharingIntent.putExtra(Intent.EXTRA_EMAIL,
new String[] { toString });
sharingIntent.putExtra(Intent.EXTRA_SUBJECT,
"New Files from Safe Storage");
sharingIntent.setType("text/*");
startActivity(sharingIntent);
This intent then uses the default share activity to share the email with my attached file (which i took out for this example). When this code goes off it opens the gmail activity for me, but i still need to push the send button even though everything is filled in. Is there a way to make this instead just send automatically without showing the user the activity and having them forced to push "Send"?
Have a look on the following link, there is an answer for your question.
Sending Email in Android using JavaMail API without using the default android app(Builtin Email application)