Application button to open current/new instance of another app - android

I have two applications, A and B. In app A I've added a button which opens app B.
When the button is clicked I want to open App B if it's not already running, otherwise I want to bring the app to the front.
This is the code I use:
Intent intent = getPackageManager()
.getLaunchIntentForPackage(
"com.myapp.something");
if (intent != null) {
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
The code seems to work, but the problem is that if I open app B from app A (using this code) and then click directly the icon of App B, I get two instances of the app, which is undesired.
How can I open the app, as the code does, but also get the same instance even if the app's icon is clicked?

Add Intent.FLAG_ACTIVITY_CLEAR_TOP

Related

Android start activity of second app having no icon from first app

I am having two apps. First app has an activity from which I want to launch an activity from the second app. I am using the following code:
Intent launchIntent = m_context.getPackageManager().getLaunchIntentForPackage(m_packageName);
if (launchIntent != null) {
m_context.startActivity(launchIntent);
}
This code is working very fine to launch the activity from the second app but I want to have the second application without any icon. I am using following code in MainActivity of the second application to remove icon:
PackageManager p = getPackageManager();
//Removing app icon
ComponentName componentName = new ComponentName(this, com.tools.html2pdf.MainActivity.class);
p.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
This code successfully removes the launcher icon but then activity from my first application is unable to launch the activity from second app.
Can any one help me in this regard? I want to launch activity of an app having no icon from activity of another application.
When you disable the component like you have done, that component can't be launched in any way. However, interesting thing is that other components (non-disabled activities) of your second application are still launchable.
So, you can create an alias of your MainActivity in the second application which will be used for your purpose. Let's call alias as MainActivityAlias.
From your first application, call the intent on MainActivity. The code for disabling the component will be executed and nothing will open. However, the icon will be gone because this component is disabled and everything related to this component (i.e icon) is gone too.
Now, call the intent on MainActivityAlias just after above intent in the first application. This is just a copy of MainActivity but it does not have any code for disabling and thus, it is enabled and launchable.
Some Side Notes :
1) Both activities should have an <intent-filter> with android.intent.action.MAIN.
2) Your MainActivity should be the launcher activity and thus should have android.intent.category.LAUNCHER in the manifest.
3) Inside MainActivity, you have to check where the call is coming from. If the call is from the first application, then execute the code to disable icon which you mentioned in the question. If the call is coming from launcher icon, then open MainActivityAlias using intent. You can know where the call is coming from like this.
Note - This is just an idea. I have not tested it.
If you don't want the second app to have an app icon, just remove the <intent-filter> with ACTION=MAIN and CATEGORY=LAUNCHER for the root Activity in the second app. When the app is installed, if there is no <intent-filter> with ACTION=MAIN and CATEGORY=LAUNCHER, there will be no app icon shown.
Your app can still launch the second app, but not with the method you've described, since Android doesn't know which is the "launch" Activity. Assuming you know the package and class name of the Activity you want to launch in the second app, you can launch it like this:
Intent launchIntent = new Intent();
launchIntent.setClassName("second.package.name", "fully.qualified.class.name.of.MainActivity");
// add and Intent flags if necessary here
launchIntent.addFlags(Intent.FLAG_ACTIVITY_...);
startActivity(launchIntent);

How to resume an application from another application?

Actually, I know how to launch an application from another application.
The problem is that the application always restarts instead of resuming when I launch it from another application after launching it from home screen. (I mean the application is running first by pressing the shortcut from home screen)
For example,
There are two applications : A, B
Launch two applications from home screen first.
Launch A application again from B application.
A application restarts instead of resuming.
How could I resume it?
Now I am doing it as below.
Intent intent = getPackageManager().getLaunchIntentForPackage(PACKAGE);
intent.setAction(ACTION);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
ACTION is custom action.
Please help.
You can check for the Intent.CATEGORY_LAUNCHER category and Intent.ACTION_MAIN action in the intent that starts the initial Activity.
If those two flags are present and the Activity is not at the root of the task (ie.. app was already running), then I call finish() on the initial Activity. That exact solution may not work for you, but something similar should.
Here is what I do in onCreate() of the initial/launch Activity:
if (!isTaskRoot()
&& getIntent().hasCategory(Intent.CATEGORY_LAUNCHER)
&& getIntent().getAction() != null
&& getIntent().getAction().equals(Intent.ACTION_MAIN)) {
finish();
return;
}
You need to set the ACTIVITY_REORDER_TO_FRONT flag on your Intent when you call Context.startActivity().

How to keep a single Android instance of app in current running apps

I have an android application which has two activities let's say A and B where A is the launcher activity. For activity A I registered an intent-filter which opens application for a specific URL. I want to have always a single task for my application in current running apps. To solve this problem I tried different combinations for launchMode attributes:
A singleTop, B standard but when I access app via intent URL I have two applications in current running apps
A singleTask B standard but every time when I open the app, it starts with activity A even the apps was already opened with activity B (in this case I want to resume the app)
A singleTask B singleTask the behavior is like A singleTask B standard
I want that my app to have the same behavior like for example gmail, always to have maximum one instance in current running apps, when I open it and there is already an instance in background, to resume it and if I open the app via intent filter I want to process the intent and provide content accordingly (for example gmail is in background and I receive a new mail notification after I click it, the android keep one instance for gmail and displays the new mail).
I use Samsung Galaxy Note 4 with Android 6.0
Problem solved
I found a solution for my problem, maybe it is not the best but it works. Firstly I added a new Activity to catch the intent filter which has launchMode = "SingleTask" and in its onCreate method I posted an event to kill all existing activities.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if ("android.intent.action.VIEW".equals(getIntent().getAction())) {
// This Activity is started using an external app (eg: Gmail)
// So start the app from the beginning
// (redirecting to Activity A)
Intent mainIntent = getIntent(); // Copy the Intent used to launch me
// Launch the real root Activity (launch Intent)
mainIntent.setClass(this, StartActivity.class);
// Post an event to kill all existing activities
// To do this i use Guava
PubSub.getInstance().post(new KillActivityEvent());
startActivity(mainIntent);
finish();
} else {
// The activity wasn't started by an external app
finish();
}
}

App Restarts on bringing it to foreground from different launch sources

Hi I am stuck with this issue.
I have my app which has 3 activities:
SplashScreenActivity, LoginScreenActivity, ViewPagerActivity(which houses 3 fragments).
When I put the apk in the mobile sdcard and install and open using the packagemanager. My App starts up just fine.
Issue - But, now if I press the Home Button and again launch the app from the Apps drawer/Homescreen. The App seems to relaunch and I have to go through the entire flow of Splash and LoginScreen.
This issue does not occur if I launch the App the first time itself from the Apps drawer itself./If I long press the Home Button and select the App from recent apps list the app is resumed properly as well.
For Reference I launch activities using these flags
Splash->Login
Intent intent=new Intent(SplashScreen.this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
LoginActivity->ViewPagerActivity
Intent intent = new Intent(context, ViewPagerActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
Home screen icon launches whatever activity you have declared as the MAIN ... LAUNCHER activity in your manifest. Generally, the launch activity in manifest should be the main activity of your app. From there you can invoke splash screens and login activities when needed.
remove these flags or the complete line of code
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
This seems to be an issue when launching with package manager.
https://code.google.com/p/android/issues/detail?id=2373
if (!isTaskRoot()) {
Intent intent = getIntent();
String action = intent.getAction();
if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && action != null && action.equals(Intent.ACTION_MAIN)) {
finish();
return;
}
}

Prevent SingleTask app from closing when returning to the calling app

I have two apps, which I will refer to as app A and app B. App B is a single task app and normally, if you start this app from the Home screen and use the Back button, you will not be allowed to return to the Home screen. Now suppose app A needs to call app B using an Intent. If the user then uses the Back button in app B, I really do want them to return to app A. But since I am overriding the Back button, it is not possible to return to app A using the Back button.
How can I return to app A but make sure app B remains running if it was running when app A called it? If app B was not running when app A called it, app B should shutdown (get destroyed) when the Back button is pressed.
I am using Android 2.2
UPDATE:
I tried the following:
#Override
public void onBackPressed()
{
try
{
if (this.returnToClient)
moveTaskToBack (true);
this.returnToClient = false;
}
catch (Exception ex)
{
}
}
I set returnToClient to true if the activity is launched by a calling app by checking some bundle data that gets passed in.
Now if I press the Back button, app B will move to the background and app A comes to the foreground. Looks good. Now if I press the Home button and then launch app B, app B just picks up where it left off. Also good. Now the bad part. If I do a long press on the Home button to bring up the history list and then tap on the icon for app B, the onNewIntent method gets called exactly the same with and with the same data being passed in as though app A had initiated the activity. So what I am guessing is that Android treats launching an app from the Home screen different than it does from the History list. Why? I have no idea. It seems that the history has to do with whoever launched the activity last and persists the bundle data as part of that history. That is weird and it results in unwanted behavior making app B look like it just got called from app A.
Have AppA launch AppB using an Intent with an EXTRA that indicates that it was launched from AppA, something like this:
Intent intent = new Intent(this, AppB.class);
intent.putExtra("returnToAppA", "true");
startActivity(intent);
Then, when AppB traps the "back" key, it can check if it was launched from AppA and if so, it can return to appA like this:
Intent intent = new Intent(this, AppA.class); // Use the starting
// (root) Activity of AppA here
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Setting FLAG_ACTIVITY_NEW_TASK will ensure that a new instance of AppA will not be created, but it will just return to the existing task containing AppA.

Categories

Resources