How to launch kiosk app from single app in Android - android

I have an Android device that is running a single application. This application starts on boot and is the only one the user shall be able to see.
But once this app is running, I would like to be able to launch another app by clicking a button on this "boot" app, in a way that this second app is launched in "kiosk" mode, so that the user cannot go back, cannot go home, cannot get any notification, and so on, until certain action is finished.
For this I am trying to follow the Google documentation for lock mode here.
But it is not clear for me, when it tells "DPC must allow apps..." this code should be placed in the initial app (the one on boot), or for the one I want to run in kiosk mode?.
Would appreciate a bit more detailed info on that.
The part when it tells:
// Set an option to turn on lock task mode when starting the activity.
val options = ActivityOptions.makeBasic()
options.setLockTaskEnabled(true)
// Start our kiosk app's main activity with our lock task mode option.
val packageManager = context.packageManager
val launchIntent = packageManager.getLaunchIntentForPackage(KIOSK_PACKAGE)
if (launchIntent != null) {
context.startActivity(launchIntent, options.toBundle())
}
I assume that is indeed to be placed on the "boot" app.

Yes, that part will reside in your boot app, which should work for you but you can also add the second apps packagename to the
DevicePolicyManager.setLockTaskPackages()
If you don't want to try that method as seen below:
private val YOUR_BOOT_APP_PACKAGE_NAME = "your.boot.app.packagename"
private val YOUR_SECOND_APP_PACKAGE_NAME = "your.second.app.packagename"
private val APP_PACKAGES = arrayOf(YOUR_BOOT_APP_PACKAGE_NAME, YOUR_SECOND_APP_PACKAGE_NAME)
mDevicePolicyManager.setLockTaskPackages(mAdminComponentName, APP_PACKAGES)

Related

Bring app back to foreground from code doesn't work on Android 12+

I made a Xamarin.Forms project to create and show local notifications, and it's supposed to be able to put the app back to the foreground when the notification is clicked.
The thing is, my code works on Android 11 and before, but on Android 12 & 13 the notification click is received by the app, if I have a callback for that notification it is called, but the app stays in background.
This is the part of the code that runs when I received a notification click and that I want to set the app in foreground (this is in the Xamarin Android project) :
var packageManager = Application.Context.PackageManager;
Intent launchIntent = packageManager.GetLaunchIntentForPackage(Constants.PackageName);
if (launchIntent != null)
{
launchIntent.AddCategory(Intent.CategoryLauncher);
Application.Context.StartActivity(launchIntent);
}
I have found a lot of posts on how to start/set to foreground an app, and the code I use is what's working for others, but all these posts where from 2020 and before, so no Android 12+ at the time and I can't find anything about a new way of doing this.
Does anyone have this functionality working on the newest Androids ?
I have found the solution so I'll post it here if someone needs it.
The code I use to put the application back to the foreground is correct, but I was missing the System_Alert_Window permission in my main application.
So to handle this permission I did :
Add it to my main application's manifest
Create a native method that checks if it is enabled
Create a native method that redirect the user to the overlay settings so they can allow the permission.
To check if the permission is enabled :
public bool HasOverlayPermission()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.M)
return true;
return Android.Provider.Settings.CanDrawOverlays(Application.Context);
}
To redirect the user to their phone settings for AppOverlay (this permission can only be allowed from the settings) :
public void AskForOverlayPermission()
{
if (Android.Provider.Settings.CanDrawOverlays(Application.Context))
return;
var uri = Android.Net.Uri.Parse("package:" +
Application.Context.PackageName);
Intent intent = new Intent(
Android.Provider.Settings.ActionManageOverlayPermission, uri);
_mainActivity.StartActivityForResult(intent, 101);
}
The StartActivityFromResult method is only accessible in Activity classes, so you can either write it in you MainActivity or give your MainActivity as constructor parameter of another class.
This code will directly redirect the user to the settings page, so it's better if you ask them if they want to allow this permission in a popup or something beforehand (so they can understand why they're redirected).
I have found the code in this post : How to enable screen overlay permission by default

Nativescript + Angular UI freezed after bring back from background on Android

My app have a background service (Android) which look periodicly for new data. If there are new data a notification is started. By tapping the notification a little native code piece is running and this will bring back to front the Nativescript app.
Snippet from the Kotlin class to bring back the Nativescript app:
val launchIntent: Intent? = packageManager.getLaunchIntentForPackage(applicationContext.packageName)
launchIntent?.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or Intent.FLAG_ACTIVITY_SINGLE_TOP)
launchIntent?.setAction(ACTION_NOTIFICATION_AVAILABLE)
startActivity(launchIntent)
In the AppComponent class my listener for a AndroidApplication.activityResumedEvent will listen:
export class AppComponent implements OnInit {
constructor(
private router: Router,
private ngZone: NgZone,
) {}
ngOnInit(): void {
android.on(AndroidApplication.activityResumedEvent, (args) => this.ngZone.run(() => {
let intent = args.activity.getIntent();
if (intent.getAction() === com.sample.app.NotificationTapReceiver.ACTION_NOTIFICATION_AVAILABLE) {
this.router.navigate(['/notificationList']);
}
}));
}
}
Most of the times this code works as aspected. But in my opinion we have three diffrent situations:
App is in foreground and running when a notification is incomming and the use tap on it. => all works fine
The app is not running only the background service. If the user tap the notification the app will fully start and move to the notification list. => all works fine
Problem: The App is running but not in the foreground. By tapping the notification the app resume (without restart) to the front and navigate to the notification list BUT the user interface are freezed. By tapping the elements on the screen, the inside code are running (consoloe.log(...)) but no action on the UI. Maybee the UI are not freezed only the routing/navigation don't work.
I find the question Nativescript - How to bring app to foreground when notification is pressed but in my case there are no difference between android emulator and (not connected) real android device.
Tests with the flags to start the activity will change the behavior but not in the right way
# FLAG_ACTIVITY_SINGLE_TOP might be the best solution but the described error above is very annoying
launchIntent?.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or Intent.FLAG_ACTIVITY_SINGLE_TOP)
# even the app is in foreground after a tap on the notification the app is fully restarts
launchIntent?.addFlags(FLAG_ACTIVITY_NEW_TASK)
Have anyone an idea where the problem is or which flags i have to set to prevent the current state and the fully working UI (with router/navigation)? Or do i have to modify the nativescript/angular code the better handle the resume event?
Not the best solution but when i was able to trim the flags to get the in the foreground running app still running and in the other two states (app dead or app in the background) a fully restart is initiated, at the moment this will be fine too.
Update: It look like, that the UI not freezed. I added a RadListView and i can scroll to the list, still the routing/navigate don't work. Even i use the this.routerExtensions.back() nor i use the this.router.navigate(['notificationDetail']).

How to open an app via Intent and clear the back stack to return to app

I would like that when i open an app via android intent, when the user presses the back button, it will return to my app. Currently, if using the bellow code, it opens the app but when pressing the back button it returns to app main page and only after a second press return to my app.
private void openApp(String packageName) {
Intent launchIntent = mContext.getPackageManager().getLaunchIntentForPackage(packageName);
if (launchIntent != null) {
mContext.startActivity(launchIntent);
}
}
Looking online i checked guides such as:
Understand Tasks and Back Stack
I also played and checked android source code for Intent flags and actions but could not figure our how to do that
Your app can't control the workflow/ navigation behavior of another app. Once you start the other app, you have no further control of the user's navigation options until the user returns to your app.
By the way, the behavior you describe is the appropriate behavior for e.g. an app which offers an implicit deep link:
This means that when a user presses the Back button from a deep link destination, they navigate back up the navigation stack just as though they entered your app from its entry point.

How make a Android application that can't be closed

I'm developing an Android app for a company where those who will use it are the employees, for this reason the company asked me to develop an application that the user can not close, because if he will not use the smartphone for other purposes, but for this I need the Android native buttons do not interfere with the application.
I've deactivated the button to go back and put the application as Home.
#Override
     public void onBackPressed () {
         super.onBackPressed ();
     }
...
<category android: name = "android.intent.category.HOME" />
However if the user clicks the button that displays open applications, it can exit the application.
I researched a lot before creating resolve this question and realized several attempts to solve this problem.
One. I tried to create the same behavior as the MX Player has, when you use the lock to see a video, the MX Player is always on top of everything, leaving the user to see and click others places. However using this behavior does not i cant see My Dialogs nor Popup and also can not apply a thema, as in my case is not simply an activity is the entire application.
Reference links of my attempt
How to disable Home and other system buttons in Android?
http://www.piwai.info/chatheads-basics/
If anyone knows how to use that behavior MX Player, or if anyone knows any more how to make the user can not close the application, please help me, I know it's not just me who have this problem.
Any help is welcome!
My API is 16 - Android-4.1
Are your target devices rooted? If so, this article goes through the steps to make this possible. What you specifically ask about can be done by modifying the build.prop file to include the following line: qemu.hw.mainkeys=1. This will stop the soft-key navigation bar from ever showing up.
If the device you're running isn't rooted, I don't think that it's possible to do what you're asking.
The best way i found to the user can't access others apps, was to make a service that check which is the top activity, if don't is my then reopen my app.
ActivityManager manager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> runningTasks = manager.getRunningTasks(1);
if (runningTasks != null && runningTasks.size() > 0) {
ComponentName topActivity = runningTasks.get(0).topActivity;
if (!topActivity.getPackageName().startsWith("com.mypackage.")) {
Log.i("Top Activity", topActivity.getPackageName());
if (LocalCache.getInstance().isForceHome()) {
Intent intent = new Intent(HomeService.this, AuthLoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
handler.postDelayed(this, 500);
}
Old question, but I'm facing exactly same situation:
In-house App
Can't be close
I'm going to set App as a Launcher, and block top-dowm swipe to prevent status bar appear.
I think it's good enough for an in-house App ~

Two instances of my android application are running....How to avoid this?

Here is my problem -
I copied my .apk file onto phone memory card and launch my application clicking on it and it allows me to install my application.I install my application.Finally,I got system installation pop up containing two options "Open" and "Done".When i click "Open" my application got launched.Up to this point everything is working without any problem.
Now in my application I click on a button and some download is taking place as a result(Showing progress dialog).Now I press a Home button,so my application goes to background.
Now I again launch my application by going inside Menu and clicking on my application icon.
Expected result - Still I Should see Progress Dialog for downloading.
Actual result - A new instance/session of my application is getting started.
So how to avoid this so that only one and one instance/session of my application should run.
#Palejandro, here you are. Put the code below into your main activity onCreate() method:
// Possible work around for market launches. See
// http://code.google.com/p/android/issues/detail?id=2373
// for more details. Essentially, the market launches the main activity
// on top of other activities.
// We never want this to happen. Instead, we check if we are the root
// and if not, we finish.
if (!isTaskRoot()) {
final Intent intent = getIntent();
final String intentAction = intent.getAction();
if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && intentAction != null && intentAction.equals(Intent.ACTION_MAIN)) {
Log.w(TAG, "Main Activity is not the root. Finishing Main Activity instead of launching.");
finish();
return;
}
}
I used this piece of code in my projects and it works fine!
I believe you need to put
<activity
android:launchMode="singleInstance"
</activity>
in the manifest file.
what do your OnPause, OnResume and OnCreate?
I will bet money you are not saving anything OnPause, and starting a new instance all the time via OnCreate.
You should read the notes on Activity Lifecycles.
If you haven't got this sorted yet, I would say your app is actually being killed when home is pressed, or perhaps you have a bug that doesn't latch onto whatever object is keeping state.
// put below code in your launcher activity before call super and setcontentview()
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
// get the info from the currently running task
List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(10);
boolean alreadyTask=false;
for(ActivityManager.RunningTaskInfo info : taskInfo){
ComponentName componentInfo = info.topActivity;
String value= componentInfo.getPackageName();
if(value.contains(getPackageName()) && !info.topActivity.getClassName().contains(getPackageName()+".LauncherActivity")){
alreadyTask=true;
Log.i(TAG, "second instance found!!!");
break;
}
}
if(alreadyTask){
finish();
}
I don't have a solution but the problem is that the intent used to start the app is different when you open it directly from install compared to opening it from your home screen. Since it will get started by two different intents it will open a new instance the second time round.
A quick work around is to avoid pressing "Open" when you have installed the application. Press "Done" and then find the application yourself.
See: http://code.google.com/p/android/issues/detail?id=2373

Categories

Resources