How to choose starting Activity based on condition in Android - android

How can I dynamically select the starting Activity of my application?
Take for example this scenario: the first time the user opens the app, he will see the AuthenticationActivity, after that, he will see the MainActivity. If he logs out, he will see the AuthenticationActivity again.
I don't want to use a splash screen or something similar and I'm wondering if there is any way of doing this.
I was thinking of checking if there are any accounts in the onCreate method of the MainActivity, before calling setContentView, and display the AuthenticationActivity if not, but it doesn't feel ok to me.

You could do something like this:
public class NavigatorActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent;
if (isAuthenticated) {
intent = new Intent(NavigatorActivity.this, MainActivity.class);
} else {
intent = new Intent(NavigatorActivity.this,
AuthenticationActivity.class);
}
startActivity(intent);
finish();
}
}
And launch your app with this NavigatorActivity.

You could also set MainActivity the parent of LoginActivity, set LoginActivity as Main/Launcher and call finish() if already logged in.
<application ... >
...
<!-- The main/home activity (it has no parent activity) -->
<activity
android:name="com.example.myfirstapp.MainActivity" ...>
...
</activity>
<!-- A child of the main activity -->
<activity
android:name="com.example.myfirstapp.LoginActivity"
android:label="#string/title_activity_login"
android:parentActivityName="com.example.myfirstapp.MainActivity" >
<!-- Parent activity meta-data to support 4.0 and lower -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.example.myfirstapp.MainActivity" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
Instead of getting back to the last activity, it launch the parent one.

Related

How do I make an activity the first activity launched but only on the first run of the application

I need my app to have one activity(Register) be the first activity launched when an app is first installed but then after the initial run it will have a different activity(LogInActivity) be the first activity launched... I have put code in that makes the Register activity only run once but I can't figure out how to alter my manifest to get the desired results. I have tried moving the MAIN action to the Register activity but that causes it to be launched everytime I run my app. When the MAIN action is in the LogInActivity then Register doesn't run at all. I also tried to add a DEFAULT action in my manifest under the opposite activity of where I had the MAIN action but that didn't work either and upon further research of what DEFAULT does I don't believe this is what I need. So is there some other intent I need to add to my XML?
Manifest:
<application
android:allowBackup="true"
android:icon="#drawable/skey"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
///////////FIND INFO ACTIVITY
<activity
android:name=".FindInfoActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.LogInActivity" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
//////////LOG IN ACTIVITY
<activity
android:name=".LogInActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.LogInActivity" />
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
//////////REGISTER ACTIVITY
<activity
android:name=".Register"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.LogInActivity" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Don't have three separate LAUNCHER activities unless you want the user to be able to launch the app from the homescreen from three separate items (there are valid use-cases for this, but this isn't it).
Have one activity that handles launching the application. It checks the boolean in your SharePreferences, then starts the appropriate activity from there. Then just finish the Activity so the user won't re-open it when the user presses "Back".
public class LauncherActivity extends Activity {
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
if (firstTimeRunning()) {
// start register activity.
} else {
// start login activity.
}
finish();
}
}
In the Manifest just have this Activity as:
<activity android:name=".LauncherActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
You don't need any IntentFilters for your register activity or login activity because these are never opened through implicit intents, nor do they have any special permissions (from what I can see).
Use SharedPreference. When you open the app the first time do this:
SharedPreferences shared;
shared=getSharedPreferences("com.example", Context.MODE_PRIVATE);
shared.edit().putBoolean("first_time",true).apply();
in your onCreate() of first Activity do this:
SharedPreferences shared;
shared=getSharedPreferences("com.example", Context.MODE_PRIVATE);
if(shared.getBoolean("first_time",false)){
startActivity(new Intent(FirstActivity.this, NewFirstActivity.class));
finish();
}
Is the easiest way to "storage" data and states. SharedPreference also works with Strings, Int values, etc (if you don't want boolean value)
In your Manifest you should have only one launcher class, in the same class's onCreate method check for already logged in condition (SharedPreference). If yes, then using Intent launch HomeActivity otherwise launch LoginActivity if the user has registered and logged out. When user logs in, save account id / session details / user details in SharedPreference which you can validate in your launcher class for starting specific activity.
As Mariano said, you can use SharedPreferences. If you don't want to open your settings at startup you can use a Dialog to let the user decide to go to your settings or do nothing.
By the way, I think that use SharedPreferences to store login information (username and password) is best practice than be asking these values every time you start an app.

Up navigation goes to main activity

I have the following Androidmanifest file
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".First"
android:label="#string/title_activity_first"
android:parentActivityName=".MainActivity" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="android.anoop.com.myapplication.MainActivity" />
</activity>
<activity
android:name=".Second"
android:label="#string/title_activity_second"
android:parentActivityName=".First" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="android.anoop.com.myapplication.First" />
</activity>
</application>
In main activity's onCreate method i have the following code to launch Second activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent1=new Intent(this,Second.class);
startActivity(intent1);
}
Other than that every other activities code is what android studio provide as default. But when i press up button from the Second activity it goes directly to main activity and not to the First activity. I know there are alternate solutions for this problem but i just want to know why the up navigation is behaving like this.I am new to android so i may not be understanding something really simple. Any help will be appreciated. Thank you.
If you are using calling SecondActivity in onCreate of FirstActivity, then it goes to SecondActivity. But think about it, when do an Activity actually starts?
It starts after you call onCreate, then onStart , then onResume and then your Actiivity finally starts running. In your case, you are not allowing to go further onCreate, and hence FirstActivity has never even started. And thats why when you go back in navigation it jumps to the previously opened Activity, i.e., MainActivity.
I hope this clears your answer! For reference see the Lificycle of an Activity in this link.
Because FirstActivity is not started or Created. You are calling Second directly from Main Activity. As there is no any First Activity available in application's stack how Second Activity goes to parent Activity First? It will goes to Main Activity as Its the only Activity remain in stack.

Acitivity SingleTask behaviour with SplashScreen

In my App I have:
-SplashScreen (SSc) preparing the application (starting services and so on)
-MainActivity (MA) the most relevant part of the app handling most actions
-and some other activities which are not that relevant
For my App I'd like to have the behavior like launchMode singleTask, so that my App is always started as a new Task, even when opened through a link click in SMS/EMail app. The best would be to have only one Instance of my Activities as they are all serially navigable.
However when I start SSc as singleTask it is the root of the stack and navigating to the MainActivity, pressing home, click on the Launcher icon again the app is fully restarted. So SSc is shown again and so on. In this Situation, I would like the MainActivty to be brought to the front instead.
my wish would be:
launcherclick -> SSc ->MA ->HOME -> launcherclick -> bring MA to front -> HOME-> relaunch from recents -> bring MA to front
Click on link ->SSc/MA (whether it is first start) with the same instances
In my App it does not make sense to have multiple instances, as the background service only handles one MainActivity at a time because it polls data frequently just for the seen "Thing".
Do you have any recommendations to achieve this goal?
my first idea was a LauncherActivity with launchMode singletask without layout to route the intents to the other activities (which most likely will be singleTop !?, because its only in one task then) like:
public class LauncherActivity extends Activity {
private boolean firstStart = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
super.onResume();
if(firstStart){
startActivity(new Intent(this, SplashScreen.class));
firstStart = false;
} else {
Intent i = new Intent(this, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(i);
}
}
}
Manifest xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="x.startintenttest">
<application
android:allowBackup="true"
android:allowTaskReparenting="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name">
<activity
android:name="x.startintenttest.MainActivity"
android:label="#string/app_name"
android:launchMode="singleTop"></activity>
<activity
android:name="x.startintenttest.MainActivity2"
android:label="#string/title_activity_main_activity2"></activity>
<activity
android:name="x.startintenttest.SplashScreen"
android:label="#string/title_activity_splash_screen"
android:launchMode="singleTask">
<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="*.xyz.de"
android:pathPattern="/...-........."
android:scheme="https" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Its simple, I also did the same. I was using singleTask for my splash and the main activity. So that I faced the same issue(Splash was showing at every wakeup). But I solved this by removing the singleTask from the splash and kept it for the MA alone(I used to finish the splashActivity when the MA starts). Try this trick.
The solution provided Sripathi fixes the issue, but you end up with the link-opening-app having the splash screen layout in its preview. My solution to this is to have a LinkEntryPointActivity with no layout that then delegates the received intent to the splash screen.
class LinkEntryPointActivity : MyBaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val intentClone = intent.clone() as Intent
val componentName = intentClone.component
val newComponentName = ComponentName(componentName.packageName, SplashActivity::class.java.name)
intentClone.component = newComponentName
startActivity(intentClone)
finish()
}
}
And declare it in AndroidManifest.xml as
<activity android:name=".ui.LinkEntryPointActivity"
android:launchMode="singleTask" <-- This forces to open the link in a new task
android:screenOrientation="portrait">
<!-- Intent filters here -->
</activity>
The original splash screen activity should still be handling the MAIN action in the LAUNCHER category as usual.

Android library project custom redirect

I’ve an android app and checked as library let it be Mainapp. Now I have created two separate app using that library viz. subapp1 and subapp2. Individual apps are running fine. I’ve login activity in the library package. On successful login user will be redirected to dashboard activity.
Written simply in loginactivity page of the library pack
Intent i = new Intent();
i.setClass(getApplicationContext(), UserhomeActivity.class);
startActivity(i);
Now I need to specify to which activity the user will be redirected based on the sub app. So how I can manage this without replicating the pages. Thanks.
you could provide the class and package name as an argument and start a new intent:
Intent sccuess = new Intent();
sccuess.setClassName(packageName, className);
startActivity(sccuess);
I am not sure I understand you correctly but If I understand you correct, you need to derive your activities from SecureActivity which user is supposed to be logged in to access there.
After you extend your classes from SecureActivity, you can check it in onResume() method.
Here is an example:
public class SecureActivity extends Activity
{
#Override
public void onResume()
{
// Check if user logged in or not.
}
}
public class YourActivity extends SecureActivity
{
// ...
}
In the Mainifest of your Library, your should define like that
<activity
android:name="com.gmail.app.activities.A_Activity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:theme="#style/NoActionBar" >
<intent-filter>
<action android:name="com.gmail.app.A.Fire_Activity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.gmail.app.activities.B_Activity"
android:label="#string/app_name"
android:screenOrientation="portrait"
android:theme="#style/NoActionBar" >
<intent-filter>
<action android:name="com.gmail.app.B.Fire_Activity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
In library code where to fire the intent:
Intent i = new Intent(_context.getPackageName() + ".Fire_Activity");
//Action will be like com.gmail.app.A.Fire_Activity or com.gmail.app.B.Fire_Activity
startActivity(i);
PS:
Your Sub-Apps have package-names:
com.gmail.app.A
com.gmail.app.B

Android App - disappearance of app GUI

I'm trying to create a simple app, whose main task is to open the browser on defined URL.
I've created first Activity:
public class MyActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
Intent myIntent = new Intent(Intent.ACTION_VIEW,
Uri.parse("http://my.url.tld"));
startActivity(myIntent);
}
Here's my AndroidManifest.xml:
<manifest ...>
<application ...>
<activity android:name=".MyActivity" ...>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
This code is fully functional, but before it opens the browser, it displays a black background - blank app GUI. I didn't figured out, how to go directly do the browser (without displaying the GUI).
Anyone knows?
Add this theme declaration to your activity definition in you manifest
<activity android:name=".MyActivity"
android:theme="#android:style/Theme.Translucent.NoTitleBar"
>
Be careful with this, you must call finish(); from your activity after you are done with it otherwise users could get stuck with an invisible activity that prevents them from interacting the phonetop.

Categories

Resources