Close an app from another app - android

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 ...

Related

Pasing data through app after install without launching

Refering to this post I need to ask something else.
I have an application "A" which download and install another app "B".
I want B to "transfer" data to A and then A will use this data to do work.
I know that we can transfer data with intent.
After installing B app with A, Android provide a choice with "Ok" or "Launch" ; my question is :
Is that possible to pass data from B to A when we click on "Ok"? (So we stay in A app without launching B)
If yes, how? Is that possible to "invisible" launch B? How should I code B to get this comportement?
I know that might be hard to understand, you can try to check my previous draw (here again).
EDIT:
I use this code to launch B installation from A.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri uri = Uri.fromFile(new File(Environment.getExternalStorageDirectory().toString() + "/downloadedfile.apk"));
Intent.setDataAndType(uri, "application/vnd.android.package-archive");
getApplicationContext().startActivity(intent);
There are many ways to handle this, here is one that (I believe) is quite simple to implement. Since your A app [presumably] knows what it is installing:
App A: Add a BroadcastReceiver to react to the installation, though by default it is off.
Android: BroadcastReceiver on application install / uninstall
App B: Add a Service for background communication.
Note: A Service must be exported to be accessible to other apps via explicit intent, but this creates a security concern, as it is open to all other apps.
When a user of App A clicks to install App B:
Start the BroadcastReceiver with a filter set to detect the install:
stackoverflow...android-broadcastreceiver-on-application-install-uninstall
App A starts the install.
When the BroadcastReceiver detects the package has been added (the package name will be in the received intent,) it can stop the BroadcastReceiver, and can send an explicit Intent naming the Service in AppB. You can pass whatever data you need in the intent.
When the AppB service receives the intent, it can act in any way you'd like.
Service is always created using a non-null Intent, though the 'action' of explicit Intents is null.
Service.onStartCommand() might receive a null Intent if the service was re-created.
I'd fill in more of the code, but I have a day job ;)
Note:
Intent.ACTION_PACKAGE_ADDED called when a package is installed.
Intent.ACTION_PACKAGE_INSTALL was never used, and was deprecated in API 14.
http://developer.android.com/reference/android/content/BroadcastReceiver.html
http://developer.android.com/reference/android/content/Intent.html

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

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.

PushNotifications and MVVMCross

I have a service which handles my push notification. When the app is running, everything is fine, but once the app is not running I am getting a null reference exception. I have traced it back to the following line :
newIntent = Mvx.Resolve<IMvxAndroidViewModelRequestTranslator> ().GetIntentFor (request);
This line is used to get the intent for the status bar notification so when the user clicked on it it will take him to the appropriate page inside the app. I am pretty sure that This is null because the application is not running and the MvvmCross framework did not have a chance to initialize and register the IMvxAndroidViewModelRequestTranslator.
My question is what should I use as an alternative?
UPDATE
So I dis some reading and I believe that a regular intent wont work and break my app. I was thinking about creating a dummy activity In my app which will get the regular intent I will send and move on to use the IMvxAndroidViewModelRequestTranslator (which should be not null since the app was started) and create an MvvmCross navigation request.
Any thoughts?
UPDATE 2
Tried the approach above with no luck... still failing on the same line...
So basically the question is how can I launch the app from the status bar while making the MvvmCross eco system start as well...
Thanks
Amit
So what I ended up doing is once the notification arrived and the Mvx.Resolve threw an exception I (meaning the app is not running), I saved the notification data to the app preferences and launched the app to its main activity and there I simpley checked for the notification data and if it existed I navigated to the appropriate activity.
When the Android UI starts, then MvvmCross runs Setup to initialise things like IoC, your application, etc
If you need to initialise your MvvmCross application within a non-UI setting, then try the answer from MvvmCross DataService in an Android Broadcast listener which shows how to access the same setup that the UI uses.

Android call method from another app without starting it

I have two android applications with different packages App1 and App2. Suppose I want to call a method Method1 written in App1, from App2. One solution I found in the following link, Android call method from another app, suggested that we should register a BroadcastReceiver in App1 and call sendBroadcast() from App2. But the problem is, I could call the Method1 only if App1 is running in the background. Otherwise, nothing is happening.
How to resolve this issue? Are there any other ways to call Method1 without having to start App1?
But the problem is, I could call the Method1 only if App1 is running in the background.
This is incorrect, if you register any component (BroadcastReceiver, Service, Activity, etc.) in the AndroidManifest.xml and it is exported, other applications can trigger it with an Intent regardless of the current state of the application process.
Perhaps the issue you are running into is that the example you linked to registers the BroadcastReceiver in Java code. If you instead publish the <receiver> in your manifest, it will be externally accessible always. This is explained in the SDK Documentation for BroadcastReceiver.

Android Activity Stack is not working as stated in the docs - last activity in task stack not shown

According to Android docs:
http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html
"When the user leaves a task by pressing the Home button, the current activity is stopped and its task goes into the background. The system retains the state of every activity in the task. If the user later resumes the task by selecting the launcher icon that began the task, the task comes to the foreground and resumes the activity at the top of the stack."
If I understand this correctly, this means:
Activity A as MAIN Activity.
Activity B that gets started in A, through "startActivity" - common, plain intent instance.
I open app for first time, A gets loaded.
I click on button in A and B is openend.
I press home button.
I open app again, for 2nd time, and B is expected to be shown
...right?
I suppose this is the correct behavior to expect...
However, I am not seeing this in my app.
If I hit "Home button" and then resume my app, by pressing the launcher icon, it will start with the main activity - not the one at the top or latest one.
I am coding on a Samsung Galaxy Tab Android 2.2.1 - I have the most common options in the Android manifest - thing is that I handle like 10 different activities with different intent extras - and a Dispatcher class approach - or save each activity state - sounds quite demanding.
I am using Eclipse IDE with ADT version 12; and I found something very interesting:
When I run the app from the Eclipse IDE, with my device connected, I don't see this behavior. The app behaves as stated in the docs.
In fact, I saw this only after I deployed my apk at the Google Play app repository; and downloaded it to test.
My question is, has anybody found the real reason why is this happening?
Is the documentation wrong? or missing something?
Is this a bug on Android?
Another research I have done is:
When I try my app, downloaded from the google play, as APK, if I enter my app for the 2nd time, I get the "main" activity instead of the last one openend. I press home.
After pressing home, I enter application management settings for android, locate my app and click on "force stop".
After doing this, the app behaves as stated in the docs.
Somebody help! :)
This is a bug in android's platform:
http://code.google.com/p/android/issues/detail?id=2373
The workaround is, to place this in the onCreate method of your main Activity:
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(LOG_TAG, "Main Activity is not the root. Finishing Main Activity instead of launching.");
finish();
return;
}
}
as extracted from:
How to prevent multiple instances of an activity when it is launched with different intents
...spent 3 days looking out for this.
I'm just going to explain why it fails, and how to reproduce this bug programmatically so you can incorporate this in your test suite:
When you launch an app through Eclipse or Market App, it launches with intent flags: FLAG_ACTIVITY_NEW_TASK.
When launching through the launcher (home), it uses flags: FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_BROUGHT_TO_FRONT | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED, and uses action "MAIN" and category "LAUNCHER".
If you would like to reproduce this in a test case, use these steps:
adb shell am start -f 0x10000000 -n com.testfairy.tests.regression.taskroot/.MainActivity
Then do whatever is needed to get to the other activity. For my purposes, I just placed a button that starts another activity. Then, go back to the launcher (home) with:
adb shell am start -W -c android.intent.category.HOME -a android.intent.action.MAIN
And simulate launching it via the launcher with this:
adb shell am start -a "android.intent.action.MAIN" -c "android.intent.category.LAUNCHER" -f 0x10600000 -n com.testfairy.tests.regression.taskroot/.MainActivity
If you haven't incorporated the isTaskRoot() workaround, this will reproduce the problem. We use this in our automatic testing to make sure this bug never occurs again.
Hope this helps!
The docs are right, the only possible problem I can think of that is causing this is the device you are testing on, if it works as expected on the emulator (which is stock Android) it should work on at least 90% of Androids, its the manufactures fault for this I believe not Android.

Categories

Resources