How to remove multiple instances of the app - android

I made an app that create and listen custom url. My problem is the multiple instances of the app. For example I create a url and send it to my friend through sms. After that I open that sms (that contains url) in my app. This create a new instance of my app that open this url. I want that there must be only one instance at a time. How will I achieve this.
Thanks,

Set android:launchMode="singleTop" to your Activity in AndroidManifest.xml which opens URL. For example:
<activity android:name="com.abc.MainActivity" android:label="app_name"
android:launchMode="singleTop">
Moreover, if you like to catch new Intent then override the following method in your activity code:
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent); //set new intent as current intent
}

Use android:launchMode="singleTask" to your Activity in AndroidManifest.xml. For more information, please check this document on LaunchMode of an Activity.

Related

How to fix invalid branch referring params(clicked_branch_link) from banch links when clicked from withing the app

We are generating branch links according to the described documentation, The links work awesome when clicked from other platfomr like whatsapp, sms, browser etc, but when we share the same link within the app and click on it , we receive
{"+clicked_branch_link":false,"+is_first_session":false}
We have crosschecked all the documentation from branch io and we are following all the mentioned steps.
we are initializing Branch and handling deep linking in your Splash activity
if (BranchIOUtils.isBranchIntent(getIntent())) {
Branch.getInstance().initSession(this, this.getIntent().getData(), this);
}
Splash activity have the launchMode set to singleTask
<activity
android:name=".activities.Splash"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="#style/AppThemeNoActionbar">
overriding onNewIntent() in your Main/Splash activity
#Override
protected void onNewIntent(Intent intent) {
this.setIntent(intent);
handleIntent(getIntent());
}
Made sure we are initializing Branch with Branch.getAutoInstance(this)
Branch.setPlayStoreReferrerCheckTimeout(10000);
// Branch object initialization
Branch.getAutoInstance(this);
Not able to get as to what is missing, any pointers would be of greate help .
To deep link from within your own app, you'll have to launch a chrome intent as follows:
Intent intent = new Intent(this, ActivityToLaunch.class);
intent.putExtra("branch","http://xxxx.app.link/testlink");
intent.putExtra("branch_force_new_session",true);
startActivity(intent);
https://docs.branch.io/apps/android/#handle-links-in-your-own-app
If you have additional questions, please write into support#branch.io. Thanks.

i am Trying more Flags to prevent the Activity to be opened more than one time at the Same time

i tried Flags like
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |Intent.FLAG_ACTIVITY_CLEAR_TASK);
i Login to my application and open the home page > when i receive a notification and preessed on it to see details at home page it opened well But the previous
You can achieve this with the help of launch mode
go to manifest where your activity is declared.
And add following attribute to your activity declaration.
android:launchMode="singleTask"
And in your activity class ovveride following method
public void onNewIntent(Intent intent) {
setIntent(intent);
//do other stuff with new intent
}
I will also suggest you to read more about activity launch mode https://developer.android.com/guide/topics/manifest/activity-element.html

onNewIntent is not called

I have very strange situation.
Having one app, I decided to create another one from the code of first one.
I copied .xml files, copied .java files so that everything is OK.
But there's one HUGE problem: my onNewIntent(Intent intent) method is called in first project, but it's not called in the second project (the code is the same!)
Method, which could trigger then, but can't trigger now
public void onClick(View arg0) {
Intent browserInt = new Intent (Intent.ACTION_VIEW,
Uri.parse("https://oauth.yandex.ru/authorize?response_type=token&client_id=zzzzz"));
browserInt.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(browserInt);
}
Here's onNewIntent() method:
#Override
protected void onNewIntent(Intent intent){
System.out.println(" I WORKED!");
Uri uri = intent.getData();
if (uri!=null) {
String m = uri.toString().split("#")[1];
String[] args = m.split("&");
String arg = args[0];
String token = arg.split("=")[1];
System.out.println(token);
}
}
I don't see "I WORKED" in my logs, unfortunately.
I've read lots of similar questions both on SO and over the Internet, tried setting Intent flags SINGLE_TOP, SINGLE_TASK and so on.
Here's the Android Manifest of WORKING project:
<application
android:name="yyy"
android:icon="#drawable/yaru_icon"
android:allowBackup="false"
android:label="xxx"
android:theme="#style/LightTheme">
<activity
android:name=".Main"
android:label="xxx"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
I'm quite desperate, why the similar code is not working anymore?
EDIT: I've tried everything: SINGLE_TOP, SINGLE_INSTANCE, SINGLE_TASK..
but then I occasionally did this on another activity:
Main m = new Main();
m.onNewIntent(this.getIntent());
And it finally worked!
I don't know, whether it's a dirty workaround or a bug, if anyone can explain it, please, comment.
PREAMBLE:
Allright, I'm a little late to this one, but as I stumbled over the same issue and no answer here or for any of the other four stackoverflow questions, I found for this issue, solved the problem for me, here's what I figured out.
ANSWER:
There are several possible reasons, why onNewIntent isn't called and I'm gonna list them all - well all of which I know.
As mentioned in many answers before and in the doc for the onNewIntent function (link in Yaroslavs answer), you either need the android:launchMode="singleTop" manifest entry for the activity, where you want onNewIntent to be called, or the Intent used for starting the activity must have the flag FLAG_ACTIVITY_SINGLE_TOP. You don't need both (it's a | aka. logical or not a & aka. logical and )! onNewIntent should also be called for android:launchMode="singleTask", but before you use that, you better check out the android:launchMode documentation, because it has much more consequences, than just one function call.
In older versions of Android there was a bug, which basically prevented android:launchMode="singleTop" from working as specified and thus onNewIntent from being called. The bug was never officially solved, but I couldn't reproduce it in version 4.4.2 (Samsung S4 Mini). So it seems to have been fixed at some point between 4.0.x and 4.4.2.
Not every time the preconditions as mentioned before are fulfilled, onNewIntent will be called. As the documentation of the function states:
...when the activity is re-launched while at the top of the activity stack instead of a new instance of the activity being started, onNewIntent() will be called on the existing instance with the Intent that was used to re-launch it."
That means, if the activity is newly created, onNewIntent won't be called, no matter what launchMode or Intent flags you did set!
To my understanding, either onCreate or onNewIntent is called, but never both.
So, if you wanna pass data to the activity through the Intent and it should always work (as in my case), no matter if the activity is relaunched or the activity is freshly created, you can do as described in this very useful blog post.
As a variation of the solution described in the above blog post, you could also take advantage of the fact, that no matter if onNewIntent or onCreate was called, onResume will always be called afterwards, and do something like this:
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
#Override
protected void onResume() {
super.onResume();
Intent intent = getIntent();
// ... do what you wanna do with the intent
}
For this example getIntent will always get you the Intent you used for the startActivity call or the Notification, as the new Intent will also be set for the Activity, if the Activity is freshly created (and thus onCreate was called).
POSTAMBLE:
Sorry for the long post. I hope you found something useful in it.
The Activity you want to receive onNewIntent() in should have
android:launchMode="singleTop"
Or add the flag tn intent
browserInt.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
Intent.FLAG_ACTIVITY_SINGLE_TOP);
As documented in onNewIntent(Intent)
Here's one situation that might bite you, along with a bit more information: onNewIntent is called as expected with this code:
Intent intent = new Intent...
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
finish();
startActivity(intent);
but not with this code
Intent intent = new Intent...
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
finish();
The reason for that is that, in the second code block, the new activity is added on top before calling finish for the current activity, so to get the second code block to work you must add the FLAG_ACTIVITY_CLEAR_TOP flag as suggested by some of the other answers, like this:
Intent intent = new Intent...
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
Note that finish is not called at all here, because it is called for you. From the documentation for the FLAG_ACTIVITY_CLEAR_TOP flag:
If set, and the activity being launched is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent.
I was using onNewIntent for search implementation in Android. I came across the problem that onNewIntent wasn't being called when I used the Go button on the keyboard in the emulator. I solved the issue by placing my code for handling the intent in the onCreate method also. This needs to be done to make sure that the intent action is handled when a fresh instance of the activity is started.
This posed a problem as onCreate is called whenever the activity is restored from a previous state too. So, the intent handling method gets called even when an orientation change occurs.
Solution : Use if (savedInstanceState==null) to determine if activity is being restored from a previous state, or is it a fresh search.
The best way to handle onNewIntent with singleTop is simply this:
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
Then do all of your logic on getIntent inside onResume.
for me I didn't add search action to the activity in the manifest:
<activity android:name=".SearchResultsActivity" ... >
...
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
...
</activity>
Check your steps here:
https://developer.android.com/training/search/setup
In my case, I just add launchMode="singleInstance" in the activity tag in the AndroidManifest file.
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Note: I was using kotlin.
To enter to the onNewIntent method, you need in your AndroidManifest.xml file, put after set you main activity a launch mode, in this launch mode you have to put singleInstance e.g:
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:launchMode="singleInstance"
android:windowSoftInputMode="adjustPan" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Now you will able to enter to you onNewIntent method.

"Private" intent filter for self app use only

I have created a file explorer and register
<action android:name="android.intent.action.GET_CONTENT" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.OPENABLE" />
But I don't want my internal file explorer is begin shown for user to choose when another app send implicit intent with "Openable" category. How can I do so? Should I just create my own action name?
I don't have the explicit one because I want user to choose other file explorer within my app.
If it's important that only your own app is able to start one of your components, set the exported attribute to "false" for that component in the manifest.
if you asking me - I think that for your situation the best thing is to create your own intent filter (as you sugested in your question), because if you declare your activity to receive a system built in broadcast - it have a meaning. so what's the point using this built in broadcast, if you kind of "breaking his contract" from a system point of view, and want to ignore it in some cases?
if you'll decide to use this built in filter anyway although what I've suggested, the way to achieve what you want is:
register your receiver not in the manifest, but in the onCreate() method of your first launch activity, and unregister him in the onDestroy().
that way your activity won't be registered when none of your activities are foreground - that is close to state which application is close from users point of view.
in case you are not sure how it's done, that's the way:
private BroadcastReceiver mMyCustomReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerReceiver(mMyCustomReceiver, IntentFilter.create(YOUR_FILTER_ACTION_COMMAND, YOUR_FILTER_DATA_TYPE));
}
#Override
protected void onDestroy() {
unregisterReceiver(mMyCustomReceiver);
super.onDestroy();
}
I agree with Chris Stratton and Tal Kanel.But instead you can use specific "Data" in your intent filter.Documentation says:
An Intent object that contains neither a URI nor a data type passes
the test only if the filter likewise does not specify any URIs or data
types.
So if an intent has "Openable" category and has not data part that matches your intent filter specific data part,your internal file explorer will be not shown for user.
You could use an 'activity-alias' to make a 'copy' of the activity with android:exported="false" and the private intents?
If you are willing to invoke your activity via an explicit intent (ie, giving the target component name) then you can omit having an intent filter for that activity.

android Intent received to onCreate multiple times

hi
I have added an app to the Gallery share menu.
Selecting and sharing one image works fine and this code:
if (Intent.ACTION_SEND.equals(action)) {
in my onCreate is executed.
The problem is when i press back(destroy) and open the app again
The same Intent is received in the onCreate.
I use the :
android:launchMode="singleTop">
and the
protected void onNewIntent(Intent intent)
The onNewIntent is not firing.
I suspect i must clear out the Intent somehow.
and been trying to find and answer but im stuck
The problem is in your launchmode. It should be standard so each time it will initiate a new instance of activity.
As you are using a singleton so if you get back to your current activity again, it will not relaunched.
See this link for ref how launchmode works: http://developer.android.com/guide/topics/manifest/activity-element.html#lmode
found the solution so i answer my question for anyones delight
Added this to manifest:
<activity android:name=".ServicesDemo"
android:label="#string/app_name"
android:configChanges="keyboardHidden|orientation">
Added this to my ServicesDemo:
public void onConfigurationChanged(Configuration newConfig)
{
Toast.makeText(this, "onConfigurationChanged",Toast.LENGTH_LONG).show();
super.onConfigurationChanged(newConfig);
}
Orientation changes of the phone will trigger this method instead of onCreate

Categories

Resources