Android usb permissions. How to handle attach, detach and already plugged in - android

I'm developing an android app that must communicate with a usb device. I read the docs at http://developer.android.com/guide/topics/connectivity/usb/host.html, and added an intent filter and a device list. After that my app detects the device when I plug it in and offers to start the app automatically. If the app is already running when the device is plugged, or if the device is already plugged when I start the app, there are problems.
If the app is already running I get a new blank window. I suspected it started another instance and added android:launchMode="singleTask" to my manifest, but the behavior did not change. I think I get an error message: E/Qt JAVA ( 6433): Surface 1 not found!
If the device is already plugged when I start the app, I get a permission error when I try to open the device.
The behavior I would like is:
- If dev attached when app not running, start the app
- If dev attached when app running, detect it and enumerate devices
- If dev detached when app running, detect and handle it in my code
Should all this be doable just with the intent filter if I do it correctly?
I'm developing the app with Qt, and using JNI to interface java code handling the usb stuff, if that is relevant info.

You need to set the android:launchMode to singleInstance, not singleTask.
From the documentation:
singleTask:
The system creates the activity at the root of a new task and routes the intent to it. However, if an instance of the activity already exists, the system routes the intent to existing instance through a call to its onNewIntent() method, rather than creating a new one.
singleInstance:
Same as "singleTask", except that the system doesn't launch any other activities into the task holding the instance. The activity is always the single and only member of its task.

Related

How to prevent Android from creating a new activity when USB device is connected?

I want my Android app work like this:
When a new USB device is connected, and my app is already active, my app asks for permission to use the USB device.
When the same (type of) USB device is connected again, and my app is active, then my app can use it without having to ask for permission again.
If my app is active, the current activity continues running (rather than
a new Activity being started) when a known USB device is connected.
I can't get #3 to work: Android 9 insists on starting a new Activity, because my app is registered as a default handler for this USB device. I don't care about default handlers: I don't need an app to be started when the device is connected. (However, I do need #2.)
I tried this:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0) {
finish();
return;
}
...
}
Unfortunately this didn't work: it removed both copies of my activity from the stack, navigating back to the Android home screen. I only want to remove or prevent the Activity automatically created by Android when a known USB device is connected.
What I want is possible, the app Serial USB Terminal seems to work like this.
How can I accomplish it?
the 'Serial USB Terminal' app uses
android:launchMode="singleTask"`
As you can see in https://github.com/kai-morich/SimpleUsbTerminal, launchMode=singleTask and singleTop have same effect for most apps. Only if you would start another activity in the app, e.g. Android Settings then you should use singleTask, else a new MainActivity would be started when the settings activity is currently shown.
This (singleTop) seems to have fixed it in the manifest:
<activity android:name=".MainActivity" android:launchMode="singleTop">
I'm not sure if this is the right way to solve it though.

Restart native app after crash

In android 4.4 and below, who loads a native application (/system/bin/*) at startup, I think that the file init.rc is responsible, it is correct?
Then if a native application crashes (for example /system/bin/mediaserver) it restart automatically, then the question is: who is responsible for the application restart? there is a file?
ActivityManagerService restarts the native apps.
There's usually some chatter in logcat when an app is restarted by the activity manager service, in the normal log and/or event log
(logcat -b events).
More Info:
If you see the code of ActivityManagerService.finishForceStopPackageLocked() method, this method fires an Intent with action Intent.ACTION_PACKAGE_RESTARTED.
And it is called from various methods like:
ActivityManagerService.forceStopPackage()
IPackageDataObserveronRemoveCompleted.onRemoveCompleted()
So internally there's an PackageDataObserver implemented in ActivityManagerService, which observes if any package is removed, and if it's need to be restarted, an intent is fired with the action Intent.ACTION_PACKAGE_RESTARTED
And every package is forced closed using ActivityManagerService.forceStopPackage(), it knows which package to restart.
Hope it clears the doubt.

How to startActivity from service that has android:singleUser and permission INTERACT_ACROSS_USERS

I'm looking to expand my app to handle Guest Mode, introduced in Android L. I found that if I create a service with android:singleUser in AndroidManifest, with permission INTERACT_ACROSS_USERS, and I'm a system app by installing it in /system/priv-app, then my service is running even as I switch user. But my app needs to interact with the user, by being able to launch an activity, show a toast or notification. All of those things seems to not be possible. Is there a particular flag I need to set when I call startActivity so that it will launch a new activity from my service?
I found a way to do it. Basically have a singleton Service, which is a service with the android:singleUser="true" and with INTERACT_ACROSS_USERS and have the APK installed in /system/priv-app. Then have it broadcastAsUser to all users. You'll need to use reflection to access methods in UserManager. Then have a receiver instance which will receive the broadcast in the guest user's space, and then have the receiver startActivity.
There are several internal apis (comments as #hide) like Context.startActivityAsUser, NotificationManager.notifyAsUser to support it, but it needs build from source also with platform signature.

Android : can native code get broadcast intent from android system? [duplicate]

This question already has answers here:
Listen to own application uninstall event on Android
(3 answers)
Closed 7 years ago.
Recently i've seen a funny app - Photo Wonder.
When this app is uninstalled, it shows a web survey page asking for the reason of app uninstall. Now, here is the problem.
As far as I know, after an app has been removed, the system broadcasts ACTION_PAKAGE_REMOVED intent.
But this funny app was able to show my the web page although the official doc says
"The package that is being installed does not receive this Intent."
Anyhow, I could find a process checking some kind of status of the app.
Now here is the question. Can the native app catch the broadcasted intent from android system?
If it is possible, please let me know how! :-(
I believe I've got the main idea of how they did it. Here is the pieces of the puzzle.
Any Android application can start a process by calling Runtime.exec() function.
Runtime.getRuntime().exec("chmod 755 '/data/data/my.app/files'/native_code");
After this line of code gets executed there is another process spawned. This process runs under the same linux user as the application itself.
When a user opens Settings -> Apps -> My App and presses "Force stop" button, main application process gets killed, but the process hosting native program (see above) still runs. I personally believe this is a security issue and I am going to report it back to AOSP.
Such native program can run infinitely and do nothing - just sleeping. But before going to sleep, it registers a termination signal handler which will be called when process is about to be terminated by the system.
int main(void) {
signal(SIGTERM, termination_handler);
while(1) {
sleep(10);
}
}
void termination_handler(int sig) {
// handle termination signal here
}
Now you should already know what the last piece is, right? My native termination_handler should be able to launch a browser. I didn't try this in code, but I assume this is possible, because I can do it using adb shell as following
adb shell am start -a android.intent.action.VIEW -d http://www.google.com
Now back to the question about how Dolphin Browser does it. Install the app and launch it at least once. Once started, it registers a native uninstall watcher using the principles described above. To see it, connect to the device and open adb shell. Then call ps to see list of processes. You will see two processes similar to following
u0_a109 315 ... mobi.mgeek.TunnyBrowser
u0_a109 371 ... /data/data/mobi.mgeek.TunnyBrowser/files/watch_server
As you can see it starts a watch_server native program, which is a part of its apk-file. Now open App info page of Dolphin Browser and press "Force Stop". Switch back to terminal and call ps again. You will see there is no mobi.mgeek.TunnyBrowser process anymore, but watch_server still runs.
By the way this approach will only work, if watcher server runs all the time. To
make sure it is always up, both apps require "run at startup"
permission, where they start their watchers.
Now, when you uninstall the app, Android stops all processes belonging to this application. Watcher receives termination signal and opens browser with predefined URL and then shuts down.
I might look a bit different in some details, but the main concept behind this hack must be as described.
There could be a tricky thing like that application is also having watcher service.
You can check the permission used by that app may contain INSTALL and UNINSTALL permissions.
HOW IT WORKS:
instead of single app that may have 2 app bundle.
as and when you install it, this app is also installing some service that is watching your app status
When you try to uninstall that app the system broadcast is called which is handled by that service and will check that if your package is exist in installed application or not.
as soon as this service finds that your package is not in the list it calls an intent with action view with the web url to open the brawser.

Close an app from another app

I have application A and application B.
I launch B with an intent from A in this way:
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName("com.applicationB", "com.applicationB.MainActivity");
intent.putExtra(EXTRA_NAME,"name");
startActivity(intent);
When the user closes application A I want application B to close too. App B has JNI and uses exec() command.
I've tried android:sharedUserId but I got this error when app A tries to launch B with the code above:
Error running exec(). Command: [....] Working Directory: null Environment: (not null, it shows all the environment.
Any ideas?
you must use android IPC mechanisms like broadcast receiver
when application A closes it should send a broadcast and application B should register for a broadcast receiver to capture broadcasts from application A
see the documents for more info http://developer.android.com/reference/android/content/BroadcastReceiver.html
If both applications are programmed by yourself, you could consider to add a BroadcastReceiver in app B, that takes care, that all activities get closed. Before app A closes, call that receiver and it's done.
If you are not sure which activity is shown, you could extend the Activity class with a BroadcastReceiver, so that all activities get notified.
If app B is not programmed by you, you could use killbackgroundProcesses(), e.g.
ActivityManager activityManager = (ActivityManager)this.getSystemService(ACTIVITY_SERVICE);
activityManager.killBackgroundProcesses(myProcessId);
... however, this works only if app B is in fact in background. Additionally this is not the best option to close an app 'cause you do not know what the app is currently doing.
Edit: found my favorite example on that topic :-) check http://www.hrupin.com/2011/10/how-to-finish-all-activities-in-your-android-application-through-simple-call - it shows how to close all activities from within the app. However, it's not a big step doing this from another one ...

Categories

Resources