I have a class called ShowBoardList where I check if user has logged in. If user hasn't logged in, then I want to return to the MainActivity which provides the user with buttons to login into different services.
My AndroidManifests.xml looks like this:
<application
<activity android:name="im.chaitanya.TaskTimer.MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="im.chaitanya.TaskTimer.WebViewActivity" >
</activity>
<activity android:name="im.chaitanya.TaskTimer.ShowBoardList"
android:label="Your Tasks">
</activity>
</application>
ShowBoardList.java looks like this:
...
Intent mainActivityIntent = new Intent(ShowBoardList.this, im.chaitanya.TaskTimer.MainActivity.class);
Intent intent = getIntent();
String url = intent.getStringExtra(WebViewActivity.EXTRA_MESSAGE); //url can be null here
Keys keys = new Keys(); //this gets an API key
SharedPreferences settings = getSharedPreferences("mySettings", 0);
String savedToken = settings.getString("token", "Empty");
if (MyUtils.equalsWithNulls(url,"tasktimer://oauthresponse#token=")) {
Log.d("From ME:", "I've reached inside url check");
mainActivityIntent.putExtra(caller, "ShowBoardList");
//caller is a String. I'm storing the name of the current activity (ShowBoardList) in it.
//So that the main activity (which I'm trying to call) will know where the call came from.
startActivity(mainActivityIntent);
}
if(savedToken.equals("Empty") || savedToken.equals("")) {
String searchString = "#token=";
int tokenIndex = url.indexOf(searchString) + searchString.length(); //Since url can be null there can be an error here
String token = url.substring(tokenIndex);
savedToken = token;
SharedPreferences.Editor editor = settings.edit();
editor.putString("token", token);
editor.apply();
}
...
Condtion equalsWithNulls checks if url is null OR equal to the string in the argument. I have log statements there to check whether control reaches inside the if statement. The main activity however doesn't start.
Edit: onCreate() of MainActivity.java looks like this:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences settings = getSharedPreferences("mySettings", 0);
String token = settings.getString("token", "Empty");
Intent intent = new Intent(this, ShowBoardList.class);
if(token != "Empty") {
startActivity(intent);
}
intent = getIntent();
String callerActivity = intent.getStringExtra(ShowBoardList.caller);
View coordinatorLayoutView = findViewById(R.id.snackbarPosition);
if (callerActivity!=null && callerActivity == "ShowBoardList") {
Snackbar
.make(coordinatorLayoutView, "Permission Denied", Snackbar.LENGTH_LONG)
.show();
}
setContentView(R.layout.activity_main);
}
Try to define your new Intent wherever you required.
Intent newIntent = new Intent(ShowBoardList.this, im.chaitanya.TaskTimer.MainActivity.class);
newIntent .putExtra(caller, "ShowBoardList");
startActivity(newIntent );
My solution is based on Sourabh's comment on the question. I realised from my logs that the activity was indeed being started.
What I didn't realise was that when startActivity() is called, the calling activity (in this case ShowBoardList) is paused and when ShowBoardList was being called again, it would resume from after startActivity().
Therefore the solution here was to call finish() and then return immediately after the startActivity() which ensures that onCreate is called the next time. I hope that makes sense if anyone is in the same situation.
These questions helped me understand more about finish():
about finish() in android
onCreate flow continues after finish()
Related
I am building an app in which when the user first installs it, In the MainActivity(Launcher Activity) the app asks what type of user he is(Let's say Driver or Rider)? Based on the user selection he is directed to the corresponding login screen. After the user is logged in he directed to HomeActivity. If he closes the app without logging out, next time he opens the app he should directly see the HomeActivity(based on what usertype he selected). For one user the code in the MainActivity would be like:
#Override
protected void onStart() {
super.onStart();
// Check if user is signed in (non-null) and update UI accordingly.
FirebaseAuth mAuth = FirebaseAuth.getInstance();
FirebaseUser currentUser = mAuth.getCurrentUser();
if (currentUser != null) {
sendToStart();
}
}
private void sendToStart() {
Intent startIntent = new Intent(MainActivity.this,DriverHomeActivity.class);
startActivity(startIntent);
finish();
}
I am new to Android and Firebase. I don't how this should be done for two types users.
Create one login screen, in that screen the user can choose work type(two buttons or radio buttons).
If he chooses Driver, then create a Driver node in the database with the information he wrote and direct him to the home activity:
FirebaseUser user=FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference ref=FirebaseDatabase.getInstance().getReference().child("Drivers").child(user.getUid());
ref.child("name").setValue(name);
Intent startIntent = new Intent(MainActivity.this,DriverHomeActivity.class);
startActivity(startIntent);
finish();
Also do the same for Rider.
If the user, closes the app without logging out. In the first activity that should open (ex: splash activity), check if there is a current user and check type of user:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference driver = FirebaseDatabase.getInstance().getReference().child("Drivers");
DatabaseReference rider = FirebaseDatabase.getInstance().getReference().child("Riders");
if (user != null) {
driver.child(user.getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
Intent i = new Intent(SplashActivity.this, DriverHomeActivity.class);
startActivity(i);
finish();
} else {
Intent intent = new Intent(SplashActivity.this, RiderHomeActivity.class);
startActivity(intent);
finish();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Here in the splash activity, it will check if there is a current user(if user is logged in) user.getUid() will return the current userid and then it will check if this userid is under the Drivers node, and then it directs him to the driver's home activity.
Your issue can be solved by the usage of SharedPreference mechanism.
Here you can keep the login status in SharedPreference like below:-.
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences();
prefs.edit().putBoolean("login", true).commit();
when the user won't logged out and coming back, you should check the login status in splash screen using the SharedPreference variable and moved the user to corresponding activity.
Boolean loginStatus = prefs.getBoolean("login", false);
if (loginStatus) {
// Move to Home activity
} else {
//Move to login screen
}
Little bit documentation here
You might consider keeping a LauncherActivity in your android application which will decide which activity to launch further. A sample LauncherActivity might look like the following.
public class LauncherActivity extends AppCompatActivity {
private boolean loggedIn = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
boolean isLoggedInAsDriver = getSharedPreferences.getBoolean("is_driver", false);
startApplication(isLoggedInAsDriver);
finish();
}
private void startApplication(boolean isLoggedInAsDriver) {
Intent intent;
if (isLoggedInAsDriver) {
intent = new Intent(LauncherActivity.this, DriverActivity.class);
startActivity(intent);
finish();
} else {
intent = new Intent(LauncherActivity.this, RiderActivity.class);
startActivity(intent);
finish();
}
}
}
Your application can have only one launcher, so mark the LauncherActivity as the launcher of your android application in the AndroidManifest.xml like the following.
<activity
android:name=".LauncherActivity"
android:label="Your app name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Now you may have noticed that I have used a flag (i.e. isLoggedInAsDriver) to start the desired activity from the LauncherActivity. This is a preference data that you need to store in your SharedPreferences when you can determine if the user is a driver or rider. Then each time your application launches via your LauncherActivity, check the stored value and get the user type. Based on the user type, launch the second activity.
use this code in manifest
and also
you should save user type with user ID in database and at start app check this first and then show home page.
<activity android:name=".MainActivity/>
<activity android:name=".DriverHomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
I want to open login_activity on first time entering app, and then on the second entering to app open main_activity.
I create something but it wont work. so I wonder what I'm doing wrong?
this is my LoginActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
userName = (EditText) findViewById(R.id.username);
userPhone = (EditText) findViewById(R.id.userPhone);
loginBtn = (Button) findViewById(R.id.buttonLogin);
dbHandler = new LogsDBHandler(this);
loginBtn.setOnClickListener(this);
setTitle("AMS - biomasa | prijava");
SharedPreferences pref = getSharedPreferences("ActivityPREF", Context.MODE_PRIVATE);
if (pref.getBoolean("activity_executed", false)) {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();
} else {
SharedPreferences.Editor edt = pref.edit();
edt.putBoolean("activity_executed", true);
edt.commit();
}
}
public void insert() {
User user = new User (
userName.getText().toString(),
userPhone.getText().toString());
dbHandler.addUser(user);
Toast.makeText(getBaseContext(), "Prijavljeni ste!", Toast.LENGTH_SHORT).show();
}
#Override
public void onClick(View v) {
if (v == loginBtn && validateUser()) {
insert();
}
}
In main activity i have only image and two buttons.
And in manifest I add launcher to main and login activity.
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"></action>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".LoginActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"></action>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
What am I doing wrong here?
Create one start-up activity call it as SplashActivity
public class SplashActivity extends Activity{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
// decide here whether to navigate to Login or Main Activity
SharedPreferences pref = getSharedPreferences("ActivityPREF", Context.MODE_PRIVATE);
if (pref.getBoolean("activity_executed", false)) {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();
} else {
Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
finish();
}
}
}
In your LoginActivity simply set activity_executed to true
public void insert() {
User user = new User (
userName.getText().toString(),
userPhone.getText().toString());
dbHandler.addUser(user);
Toast.makeText(getBaseContext(), "Prijavljeni ste!", Toast.LENGTH_SHORT).show();
//set activity_executed inside insert() method.
SharedPreferences pref = getSharedPreferences("ActivityPREF", Context.MODE_PRIVATE);
SharedPreferences.Editor edt = pref.edit();
edt.putBoolean("activity_executed", true);
edt.commit();
}
change manifest as below-
<activity android:name=".MainActivity"/>
<activity android:name=".LoginActivity" />
<activity android:name=".SplashActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
you can change launcher activity as main activity.so that when you open the application it is starting from main activity there you can check whether he is logged in or not.if he is not logged in you must navigate him to login activity or else you just do it as it is.Following is manifest file..
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"></action>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".LoginActivity"></activity>
You should add another empty activity (with no UI) that loads before anything.
Then use SharedPreferences to store some value. Thus if the user has already opened your app once, the value is stored. And then use a condition to check this value. If its the value you saved skip login_activity and direct to main_activity else direct to login_activity.
Problem about the line
if (pref.getBoolean("activity_executed", false)) {
You can Implement this method to call inside if(appIsLoggedIn)
public boolean appIsLoggedIn(){
return pref.getBoolean("activity_executed", false);
}
I'm sure this is a failure in my understanding of intents but I have an ExpandableListView of items and when I click on an item it launches the first one OK but for each time after that it only launches the first one again no matter which on I click on. The request debugs as OK but the received intent always debugs as if the first one was sent. After a half a day stuck on it and Google failing me, I need some help.
Activity #1 Mainfest
<activity
android:name="com.h17.gpm.ActivityToDoList"
android:launchMode="singleInstance"
android:label="#string/app_name" >
<intent-filter>
<action android:name="com.h17.gpm.TODO" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Activity #1 Code
Intent launch = new Intent(ActivityToDoList.this, ActivityToDoEdit.class);
launch.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
launch.putExtra("Action._ID", a.get_ID());
Log.d("ACTIVITYLAUNCHTEST", "Launch["+a.get_ID()+"]");
startActivity(launch);
Activity #2 Mainfest
<activity
android:name="com.h17.gpm.ActivityToDoEdit"
android:label="#string/app_name" >
<intent-filter>
<action android:name="com.h17.gpm.TODO.EDIT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Activity Code #2
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_todo_edit);
Intent i = getIntent();
Bundle extras = null;
if(i != null)
extras = i.getExtras();
if (extras != null){
action_id = extras.getLong("Action._ID");
Log.d("ACTIVITYLAUNCHTEST", "Receive["+action_id+"]");
}
}
I've read from other posts that getIntent returns the first Intent so also tried
#Override
protected void onNewIntent(Intent intent){
Bundle extras = null;
if(intent != null)
extras = intent.getExtras();
if (extras != null){
action_id = extras.getLong("Action._ID");
Log.d("ACTIVITYLAUNCHTEST", "Receive New Intent["+action_id+"]");
}
setIntent(intent);
}
I've also tried a lot of combinations of Intent Flags and Launch Modes in the Manifest but for the life of me the first time always comes up as
Launch[1]
Receive[1]
and the second time
Launch[2]
Receive[1]
and from then on no matter what value I send the activity launches with the first value, 1 and the onNewIntent never seems to fire.
The complete function that generates the intent
private void loadLists(){
ExpandableListView expandableList = (ExpandableListView) findViewById(R.id.expandableListViewToDoLists);
expandableList.setClickable(true);
adapter = new ActionListsExpandableAdapter(getApplicationContext());
expandableList.setAdapter(adapter);
expandableList.setOnChildClickListener(new OnChildClickListener() {
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
Action a = (Action) parent.getExpandableListAdapter().getChild(groupPosition, childPosition);
if (startedForResult){
Intent data = new Intent();
data.putExtra("Action._ID", a.get_ID());
data.putExtra("Action.SUBJECT", a.getSUBJECT());
setResult(RESULT_OK, data);
finish();
}else{
ActionList al = (ActionList) parent.getExpandableListAdapter().getGroup(groupPosition);
Intent launch = new Intent(ActivityToDoList.this, ActivityToDoEdit.class);
launch.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
launch.putExtra("Action._ID", a.get_ID());
Log.d("ACTIVITYLAUNCHTEST", "Launching activity with intent for Action ID ["+a.get_ID()+"]");
launch.putExtra("ActionList._ID", al.get_ID());
launch.putExtra("ActionList.position", childPosition);
startActivity(launch);
}
return false;
}
});
}
May be this is a good reference for you.
To me it seems like onNewIntent (with FLAG_ACTIVITY_SINGLE_TOP) like onCreate will be called if app is not destroyed. Hope is helpful to you. It works for me in my case.
For further reference see
Android: get most recent intent
I get an ActivityNotFoundException when I use this code:
public void addListenerOnButton3(){
button3 = (Button) findViewById(R.id.btnSettings);
button3.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
Intent intentSettings = new Intent("net.stuffilike.kanaflash.Settings");
showToast("Settings clicked,");
try{
startActivity(intentSettings);
}
catch(Exception e){
showToastL("Exception" + e);
}
return;
}
});
}
Fair enough, except I can't tell how it wants me to tell it where the Activity is. Here is the relevant section of the Manifest:
<activity
android:name="net.stuffilike.kanaflash.Settings"
android:label="#string/settings" >
<intent-filter>
<action android:name="android.intent.action.SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
How can I be sure the compiler finds my Settings.java file?
Oh, my package is named
package net.stuffilike.kanaflash;
try this
#Override
public void onClick(View arg0) {
Intent intentSettings = new Intent(X.this,Settings.class);
showToast("Settings clicked,");
try{
startActivity(intentSettings);
}
catch(Exception e){
showToastL("Exception" + e);
}
return;
}
});
replace X with your current activity name ..
The constructor for new Intent(String action) takes action as paramter.
As per your manifest, the action you are using is android.intent.action.SETTINGS,
1.So your Intent should be as below
Intent intentSettings = new Intent("android.intent.action.SETTINGS");
or
2.You can directly invoke the activity by using the Activity name,
Intent intentSettings = new Intent(this, Settings.class);
or
3.You can also define a custom action like net.stuffilike.intent.action.SETTINGS and then use this to create your Intent like
Intent intentSettings = new Intent("net.stuffilike.intent.action.SETTINGS");
There's 2 ways you can do this.
Use the action String to let the system see what Activitys can resolve the action on the Intent. If there is more than one Activity that can resolve the action, the user will get an option to pick which one they want.
Intent intentSettings = new Intent("android.intent.action.SETTINGS");
Open the Activity using its class directly (can only be done if both Activitys are in the same app).
Intent intentSettings = new Intent(this, Settings.class);
Right now I am getting a force close on my android emulator.
Upon finishing this app, I will want to put a custom field in instead of just test, but for now I just want test to show up from the http activity.
Any help would be great!
MainActivity:
public class MainActivity extends Activity {
public final static String EXTRA_MESSAGE = "com.example.main.MESSAGE";
/*#SuppressLint("ParserError")
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}*/
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
private Button searchBtn;
#Override
protected void onCreate(Bundle savedInstance){
super.onCreate(savedInstance);
setContentView(R.layout.activity_main);
searchBtn = (Button) findViewById(R.id.button1);
searchBtn.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
Intent intent = new Intent(null, http.class);
startActivity(intent);
}
});
}
}
Http:
public class http extends Activity {
public http(){
httpMethod();
}
public void httpMethod(){
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://api.site.com/api/");
try {
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
;
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
String test = "hello";
TextView myTextView = (TextView) findViewById(R.id.myTextView);
myTextView.setText(test);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
} catch (IOException e) {
// TODO Auto-generated catch block
}
}
}
Manifest:
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.example.main.DisplayMessageActivity"/>
<activity android:name="com.example.main.http"/>
</application>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
</manifest>
There are whole lot of issues in the code:
1) Intent intent = new Intent(null, http.class);
Use first parameter as MainActivity.class instead of null
2) httpActivity should have onCreate (or) onResume life cycle activity methods to create activity for startActivity
Not but the least, please spend some time on reading documentation and doing example programs instead of just type-in something and post on SO. By going through all your questions it is something like SO community did your app for you.
You have to initialize Intent like this
Intent intent = new Intent(MainActivity.this, http.class);
You need to pass Context as first parameter not null.
start as:
searchBtn.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
Intent intent = new Intent(MainActivity.this, http.class);
startActivity(intent);
}
});
instead of passing null as First parameter in Intent Constructor
for more information see here
http://developer.android.com/reference/android/content/Intent.html
I trully advice you to read some Android basics beacause you have some issues in the code:
You have a null context when you're initializing the intent at the button's listener. You should have: Intent intent = new Intent(getApplicationContext(), http.class); or Intent intent = new Intent(MainActivity.this, http.class);
You need to create your ativity and set it's content. You must override at least the onCreate method.
It's not so important, but its a good practice to write code that anyone might understand instead of write code for the machine! I'm telling this because you have *activity_main* sml file where you define your main activity layout and menu. I suggest you to refractor these file names to something like main.xml, for the layout, and *main_mnu.xml*.