Multiple Instances of the same app are generated in stack - android

If there is an app has a login activity, and it launches by the icon click. this login activity can be launched by another intent too. the problem is when the activity is running, (launched by touching the app icon) and when it receives the different intent call it starts another login activity.
how can i launch the login activity again after closing the current running activity, when the different intent call is received to launch the login activity.
the different intent mentioned above is, when the user select an specific file with specific extension, my app must be started.
<activity
android:name=".login.Login"
android:configChanges="orientation|keyboardHidden"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:scheme="content"
android:mimeType="application/octet-stream"
android:pathPattern=".*\\.chat"
tools:ignore="AppLinkUrlError" />
</intent-filter>
</activity>
The second intent is called , my app downloads the selected file and stores it in internel storage.
this is the onCreate method in the Login Activity
public void onCreate(Bundle savedInstanceState) {
if (getResources().getBoolean(R.bool.portrait_only)) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
super.onCreate(savedInstanceState);
if (isTaskRoot()) {
Uri data = getIntent().getData();
if (data != null) {
getIntent().setData(null);
try {
importData(data);
} catch (Exception e) {
// warn user about bad data here
finish();
return;
}
}
}
...................................
}
when user selects a specified file, the app launches another activity. then there are two login activities in the stack. help me to get rid of this
singleinstance, singletask solutions were tried. but when the launchingmode is set to singleinstance or singletask and the second intent call is received it does not call the
importData()
method. so the file that i want to download is not downloaded..

Here I used "singleTask" as launchMode. Then I have to use onNewIntent() when the Activity is called again. below link gives some more Explanation.
“onCreate()” method is not called from another intent filter

Related

Why starting the Activity by an intent (Intent.ACTION_VIEW) doesn't always start a new activity and call onCreate()?

I have two Android applications.
The first application is the "browser". It gets an URL and displays it in a WebView. The corresponding activity is declared as:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http" />
<data android:scheme="https" />
</intent-filter>
</activity>
The second application has a few buttons. Tapping each button opens the first application and sends the URL to it using Intent.ACTION_VIEW:
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse(urlString);
intent.setData(uri);
intent.setComponent(new ComponentName("com.custom.browser", "com.custom.browser.MainActivity"));
startActivity(intent);
I expect this code to start a new activity as per https://developer.android.com/reference/android/app/Activity. So the browser application retrieves the URL in onCreate() by using the code:
#Override
protected void onCreate(Bundle savedInstanceState) {
...
Intent intent = getIntent();
if (intent != null && Intent.ACTION_VIEW.equals(intent.getAction())) {
displayUrl(intent.getDataString());
}
...
}
However I found that sometimes onCreate() is not called. After calling startActivity(intent), the browser application is just brought to the front, therefore displaying a previous URL.
I can override this behavior by moving the intent retrieval code in the onResume().
However I'd like to understand what am I doing wrong? Shouldn't the method startActivity(Intent) always start a new activity and always call onCreate(), as suggested by the Android documentation?
I expect this code to start a new activity
That is not necessarily what will happen.
However I found that sometimes onCreate() is not called. After calling startActivity(intent), the browser application is just brought to the front,
Yes, that will happen if the activity you are starting is already running at the front of a task. See the documentation for tasks.
I can override this behavior by moving the intent retrieval code in the onResume().
That will not work. Override onNewIntent() and get the new Intent there. Or, adjust the flags in your Intent, or adjust the manifest settings for the activity that you are starting, as is discussed in the documentation for tasks.

Links are opening in Android webview creating multiple instances

I am working on an Android webview app and opening www.xyz.com in it.
When the app is running in the background and if I try to open Whatsapp/SMS received message-www.xyz.com/example then it is opening in a new instance and not opening in the already running instance which is in background.
And when I tried using android:launchMode="singleTask" it resumes www.xyz.com only instead of opening www.xyz.com/example.
Below is my AndroidManifest.xml
<activity android:name=".MainActivity" android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="www.xyz.com"
android:scheme="https"
/>
</intent-filter>
</activity>
Below is the MainActivity.java code -
protected void onResume() {
super.onResume();
Uri data = getIntent().getData();
if (data != null && data.isHierarchical()) {
String uri = this.getIntent().getDataString();
myWebView.loadUrl(uri);
Log.i("MyApp", "Deep link clicked " + uri);
}
}
Please let me know what I am doing wrong? Thank You.
By using launchMode="singleTask" and according to Android docs (see https://developer.android.com/guide/components/activities/tasks-and-back-stack):
The system creates a new task and instantiates the activity at the
root of the new task. However, if an instance of the activity already
exists in a separate task, the system routes the intent to the
existing instance through a call to its onNewIntent() method, rather
than creating a new instance. Only one instance of the activity can
exist at a time.
Add to your main activity an onNewIntent handler where you should see the new URL being passed in newIntent:
#Override
protected void onNewIntent(Intent newIntent)
{
// reload WebView
}
Additionally, I'm not sure that using onResume to mywebView.loadUrl() is a good or necessary practice, as even simple pause/resume events would lead to the page being reloaded. I'd suggest loading it in onCreate(), and reloading it in onNewIntent().

Activate Splash Activity or Main Activity based on the status of app

I want to open a specific file from another app with my app to handle it. For example, open a attached file in a mail from Gmail app.
With the following intent-filter setting, it works fine. When I open a file, MainActivity shows up and handles it irrespective of whether it is opened through another app or directly from my app. But I want the flow starting from SplashScreen Activity, in the event that the file is opened from another app. On the other hand, if app has been activated, activate directly MainActivity.
Does anyone know how to fix it??
AndroidManifest.xml
<activity android:name=".SplashScreenActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:mimeType="*/*"
android:scheme="content" />
</intent-filter>
</activity>
You have to replace your activity from
to
<activity android:name=".SplashActivity">
And in SplashActivity get Action from Intent and then check if the Action is android.intent.action.VIEW Then Open your MainActivity and send your file from SplashActivity to MainActivity.
That's it
You can't change launcher activity from manifest file. You can set more than one <category android:name="android.intent.category.LAUNCHER"/> in intent-filter but You have to set a default activity.
But there is a way you can solve your problem...
Make a launcher activity with No UI and open the activity with condition in onCreate method.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent;
if (condition) {
intent = new Intent(this, ClassA.class);
} else {
intent = new Intent(this, ClassB.class);
}
startActivity(intent);
finish();
}
OR
In your splash activity write condition before setContentView method.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent;
if (condition) {
setContentView();
} else {
intent = new Intent(this, ClassB.class);
startActivity(intent);
finish();
}
}
Hope this will help you.

Choose an activity to load in startup - Android

I have an android application which needs to decide which activity to load first (from 2 activities) on startup. The application is a kind of an alarm. So, the thing is I have to launch one of those activities by checking whether there is already an alarm is set or no alarm is set.
Is there a way to check this on startup using AlarmManager class without conflicting with the default alarm application in my phone.
Or should I use a database of temporary data storing method to get the details.
How can I develop this.
Please help me.
Define an activity that takes care of this. Give it the intent filter so it is launched first
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
In this activity, perform the logic that decides which activity should be opened.
For example, my app has a SplashActivity that checks if a user is logged in. If there's none, it starts LoginActivity, if there is, it goes to content activity.
<activity
android:name=".SplashActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
and
public class SplashActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (userLoggedIn()) {
startActivity(new Intent(this, ContentActivity.class));
} else {
startActivity(new Intent(this, LoginActivity.class));
}
}
}
Have a common base Activity and in its onCreate method you can write logic to choose from your Activitys, and start the chosen Activity from there. The base Activity need not load any UI (i.e. need not call setContentView) and it can call finish() just after launching the Intent.

Dropbox Core API for Android: Not returning after Authentication

I am developing two android applications:
the first is a normal application with a launcher and so on
the other is a application only with a viewer activity (see the manifest):
<activity
android:name=".MyActivity"
android:icon="#drawable/icon"
android:label="#string/dropbox" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.dropbox.client2.android.AuthActivity"
android:configChanges="orientation|keyboard"
android:launchMode="singleTask" >
<intent-filter>
<data android:scheme="db-XXXXX" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
The plan is, that the first application does not need internet permissions and the second is some kind of add-on to the first.
The second application should sync a file with Dropbox (with the Core API, not with the Sync API).
From my first app, I start 'MyActivity' from the second app like this:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setComponent(new ComponentName("my.package","my.package.MyActivity"));
intent.putExtra("filePath", "/myFile.txt");
startActivityForResult(intent, SYNC_REQUEST);
That works. The Activity comes up and there, if not authorized yet, the user must press a button. Then the following code will be executed
AndroidAuthSession session = buildSession();
mApi = new DropboxAPI<AndroidAuthSession>(session);
mApi.getSession().startAuthentication(MyActivity.this);
If the user does not have dropbox installed, the browser will pop up.
Now my troubles begin:
As soon as the user presses 'Accept' or 'Decline', the browser does not disappear. It stays open and MyActivity does not get resumed (onResume is not called!).
I found out, that adding
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
before starting MyActivity from my first application will solve the problem, but then I can not listen/wait for the result of MyActivity.
I am frustrated. Can anyone help me or give me some advise?
Thanks!
When you are using startAuthentication method. It will automatically start the AuthActivity. you do not need to call startActivity() explicitly. Then in onResume method of your activity write this code :
#Override
protected void onResume()
{
super.onResume();
if (if dropBoxAPI!= null && dropboxAPI.getSession().authenticationSuccessful())
{
try {
dropboxAPI.getSession().finishAuthentication();
oAuth2Token = dropboxAPI.getSession().getOAuth2AccessToken();
}
catch (IllegalStateException ie)
{
ie.printStackTrace();
}
}
}

Categories

Resources