I have a MainActivity which has a navigation drawer and a framelayout container to show different fragments. On my navigation drawer there is an option which launches another activity(lockpattern activity) to show a lockpattern (had to use activity cause the library doesn't support fragments yet. Link to Library).Once the user has set up his pattern or canceled the procedure,i want the lockpattern activity to get destroyed and show the previous mainActivity and the same fragment what was there in the container before the lockpattern activity was launched.The problem im facing is that once the backbutton is pressed or even if i call the finish() function,it doesn't show the previous activity(ie Main activity) but instead relaunches the lockpattern activity.i have even tried super.onBackPressed(); and it doesn't seem to work.Any help or ideas to get around this is gratefully accepted.
Code of Lockpattern
public class Create_Pattern extends Activity {
private static final int REQ_CREATE_PATTERN = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
// This is your preferred flag
LockPatternView.MATRIX_WIDTH = 4;
Intent intent = new Intent(LockPatternActivity.ACTION_CREATE_PATTERN,
null, getBaseContext(), LockPatternActivity.class);
startActivityForResult(intent, REQ_CREATE_PATTERN);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQ_CREATE_PATTERN: {
if (resultCode == RESULT_OK) {
char[] pattern = data
.getCharArrayExtra(LockPatternActivity.EXTRA_PATTERN);
DataBaseHandler handler = new DataBaseHandler(this);
handler.open();
String PatternToWrite = new String(pattern);
handler.createPattern(PatternToWrite);
handler.close();
Log.d("DEBUG", new String(pattern));
Toast.makeText(getApplicationContext(), "Pattern Recorded",
Toast.LENGTH_LONG).show();
finish();
}
if (resultCode == RESULT_CANCELED) {
finish();
}
break;
}// REQ_CREATE_PATTERN
}
}
}
You should create a new Intent that points to the Activity you want to navigate to next, start that activity by calling startActivity(intent). Then you can call finish() to destroy the current Activity.
Another approach, (which I have not tried yet) is to create an 'up button' hierarchy and manually call NavUtils.navigateUpFromSameTask(this);
Documentation:
http://developer.android.com/training/implementing-navigation/ancestral.html
http://developer.android.com/reference/android/support/v4/app/NavUtils.html
Related
I am trying to make a simple text app in order to learn app dev with Java.
I have 2 classes/activities: DisplayActivity and EditActivity.
The goal/plan is to have a screen in EditActivity where you can edit a few edittext fields, it saves it and quits the EditActivity when you press ok, you press the button to access DisplayActivity and it shows everything previously entered.
In the EditActivity, I referenced my textfields and my button, and I convert the input to strings each string variable has its own getter.
From DisplayActivity, I made an EditActivity object that calls the getters on the textview fields, which are also referenced correctly
class EditActivity{
Button mButton;
EditText mName;
DispActivity obj = new DispActivity();
void onCreate(){
mButton = (Button)findViewById(R.id.whatever);
mName = (EditText)findViewById(R.id.whateveralso);
mButton.setOnClickListener(new View.onClickListener(){
#Override
public void onClick(View v){
//does the intent thing where it changes the activity to DispActivity
String name = mName.getText().toString();
}
});
}
in DisplayActivity, there is simply the name textview referenced.
I dont have error codes/messages or warnings: everything compiles, builds, and runs nicely, until I run the app... the DisplayActivity works fine, though it displays nothing. But when I try to run the EditActivity, it crashes...
One way to do this would be with Intent and it's result. It's a simple way to share data between activities.
In your DisplayActivity, where you start the edit activity:
Intent i = new Intent(DisplayActivity.this, EditActivity.class);
startActivityForResult(i); //start edit activity
In your EditActivity, you must set the result before you finish the activity:
Intent returnIntent = new Intent();
returnIntent.putExtra("result",resultString); //put your result string here
setResult(Activity.RESULT_OK,returnIntent);
finish(); //close edit activity
Now in your DisplayActivity you get the result by implementing the following method:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
if(resultCode == Activity.RESULT_OK){
String result=data.getStringExtra("result");
//display your string here
}
if (resultCode == Activity.RESULT_CANCELED) {
//user canceled the edit activity
}
}
}
I created an image gallery app.
My requirment:When I click on buttoncut in a activity(PhotosActivity.java), buttonpaste should become visible and it should remain visible when I go back to another activity(ImageGallery.java) so that I can use it for moving pictures to another folder.
What is happening: When I click on buttoncut(PhotosActivity.java), buttonpaste becomes visible but when I go back to any other activity(ImageGallery.java), it disappears.
I tried some code but its not working. How can I fix it ?
PhotosActivity.java
Intent intent = new Intent(PhotosActivity.this, ImageGallery.class);
intent.putExtra(EXTRA_IS_CORRECT, true);
startActivity(intent);
ImageGallery.java
Intent startingIntent = getIntent();
boolean isCorrect = startingIntent.getBooleanExtra(PhotosActivity.EXTRA_IS_CORRECT, false);
if(isCorrect) {
final ImageButton buttonpaste = (ImageButton) findViewById(R.id.buttonpaste);
buttonpaste.setVisibility(View.VISIBLE);
}
but when I go back to any other activity(ImageGallery.java), it disappears
Because you have a different Intent when you "go back". If you want to persist the visibility, you should probably be using SharedPreferences.
For example
ImageButton buttonpaste = (ImageButton) findViewById(R.id.buttonpaste);
SharedPreferences prefs = getSharedPreferences("prefs" Context.MODE_PRIVATE);
boolean isCorrect = getIntent().getBooleanExtra(PhotosActivity.EXTRA_IS_CORRECT, false);
SharedPreferences.Editor e = prefs.edit();
if(isCorrect || prefs.getBoolean(PhotosActivity.EXTRA_IS_CORRECT,false)) {
buttonpaste.setVisibility(View.VISIBLE);
e.putBoolean(PhotosActivity.EXTRA_IS_CORRECT, true);
e.apply();
}
In your main Activity use startActivityForResult instead of startActivity. This allows you to return a value from the new Activity to the Main Activity. For example:
In PhotosActivity
startActivityForResult(new Intent(PhotosActivity.this, ImageGallery.class), 3);
Here, number 3 is a number you define that allows you to identify the result later.
setResult(RESULT_OK); // or any result you want
The result is sent to the MainActivity, and you must override onActivityResult() to get the result.
protected void onActivityResult (int requestCode, int resultCode, Intent data)
{
if (requestCode == 3) // here you match the number you sent in startActivityForResult
if (resultcode == RESULT_OK)
// do something
}
I have implemented a 3rd party camera scanning app within a project of mine
I have an adaptor that extends a viewholder so i can have a custom layout
Within a view i have a button
When i create the view i add an OnclickListener to the image which i want to make clickable
i want this OnclickListener to call the camera but i need to call an startActivityForResult
i am confused about the placement of the onActivityResult when calling in this way.
my current attempts have been to create a seperate class(scan_activity) which extends activity but i couldnt get the onclicklistener to start the class
i have then attempted to declare it within the setOnClickListener, which as you can guess also failed.
Im guessing the call to the class is the way forward.im sure its an easy fix, but im not seeing it
please help
thanks in advance
imgCamera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context, ScanActivity.class);
intent.putExtra(ScanConstants.OPEN_INTENT_PREFERENCE, 1);
((Activity) context).startActivityForResult(intent,99);
}
}
);
and the class
imgCamera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new ScanActivity
}
}
);
The first option should work. You create an Intent object and you specify activity component as a parameter. Android will create an Activity object for you, so, never do that manually. Android should manage the lifecycle of activity.
By starting activity for result you tell Android that it should call onActivityResult callback with request code 99 on your first activity when ScanActivity will be closed.
Handling onActivityResult in your Activity:
#Override
public void onActivityResult (int requestCode, int resultCode, Intent data) {
if (requestCode == 99) {
// handle your result here
}
}
I am working on a To Do List Android application (it happens to be for a class assignment, but that's not what I'm asking about--I've tried to leave out as much code as I could). The main screen displays a list of ToDo items with a button at the bottom to open the Add New ToDo Item screen.
On the Add New ToDo Item screen, there is a Cancel button.
Relevant ToDoManagerActivity.java snippet:
public void onCreate(Bundle savedInstanceState) {
// Init and setup adapter, etc.
footerView.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(ToDoManagerActivity.this, AddToDoActivity.class);
startActivityForResult(intent, ADD_TODO_ITEM_REQUEST);
}
});
// Attach the adapter to this ListActivity's ListView
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
log("Entered onActivityResult()");
// Check result code and request code.
// If user submitted a new ToDoItem
// Create a new ToDoItem from the data Intent
// and then add it to the adapter
}
Relevant AddToDoActivity.java snippet:
protected void onCreate(Bundle savedInstanceState) {
// Initialize default view, handle other events, etc.
final Button cancelButton = (Button) findViewById(R.id.cancelButton);
cancelButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
setResult(RESULT_CANCELED, new Intent());
finish();
}
});
}
The above code works. Previously, I was trying this in the onClick handler for cancelButton:
public void onClick(View v) {
finishActivity(RESULT_CANCELED);
}
When I clicked the Cancel button, I could see that the onActivityResult was being reached in the logs, but the screen was not reverting back to the main ToDo list screen.
Why does the above code not return me to the previous screen, but the following code does return me to the previous screen? What am I misunderstanding about the task backstack/activities?
public void onClick(View v) {
setResult(RESULT_CANCELED, new Intent());
finish();
}
According to the documentation:
public void finish ()
Call this when your activity is done and should be closed. The ActivityResult is propagated back to whoever launched you via
onActivityResult().
and
public void finishActivity (int requestCode)
Force finish another activity that you had previously started with startActivityForResult(Intent, int).
You should call finish() to close the current activity and finishActivity() to close another activity you started using startActivityForResult(Intent intent, int requestCode). Calling finishActivity() on the current activity will not close it.
Also, there's no point in creating a new Intent for setResult() as you are not passing back any data. Doing this would be sufficient:
setResult(RESULT_CANCELED);
finish();
From Android Docs:
public void finishActivity (int requestCode)
Force finish another activity that you had previously started with startActivityForResult(Intent, int).
finishActivity does not finish the current activity but calls finish for an activity called with requestCode
If you look at the documentation for finishActivity() it says that it will force finish an activity started with startActivityForResult(), but you have to pass in the request code that you used to start the other activity. In your case it would be ADD_TODO_ITEM_REQUEST.
This is probably not the API you want to use. Your 2nd method is cleaner in that you don't need to force close the child activity, but let it finish in the normal way.
Say I'm on my main activity and I start a new activity
MainActivity > NewActivity
And from NewActivity I press the back key
MainActivity < NewActivity
I want MainActivity to do something if it's being displayed after NewActivity is closed, but not when MainActivity is run normally, such as when first running the application. Does anyone know if this is possible?
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK)) {
Log.d(this.getClass().getName(), "back button pressed");
}
return super.onKeyDown(keyCode, event);
}
#Update. If you want to be notified when NewActivity is finished, you have to start it by startActivityForResult(Intent, requestCode). Then, you must override onActivityResult() on MainActivity. Check the requestcode parameter here, if the return code equals the submit code (when you start childActivity), put some code to do your business.
int MYCODE=1000;
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Result OK.d.
if (requestCode == MYCODE) {
// do something good
}
}
I try the below method to detect the back button pressed on the action bar in activity by the first method and the second one is used to detecting the mobile hardware button back or kill activity button.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onBackPressed() {
setResult(RESULT_CANCELED);
super.onBackPressed();
}
You can override onBackPressed() method in NewActivity which will detect when back button is pressed. And then to inform the MainActivity about it, you can send a boolean flag in a bundle so that MainActivity detects that its opening after NewActivity.
In NewActivity:
#Override
public void onBackPressed() {
boolean fromNewActivity=true;
Intent mainIntent = new Intent(view.getContext(), MainActivity.class);
Bundle bundleObj = new Bundle();
bundleObj.putString("fromNewActivity", Boolean.toString(fromNewActivity));
mainIntent.putExtras(bundleObj);
startActivityForResult(mainIntent, 0);
}
In MainActivity in onCreate() method :
Bundle extras = getIntent().getExtras();
boolean fromNewActivity =Boolean.parseBoolean( extras.getString("fromNewActivity"));
Now you can check if the MainActivity is opened after NewActivity or not.
A couple of ideas:
You can just set a flag in MainActivity when it fires up NewActivity.
You can call startActivityForResult from MainActivity and arrange for NewActivity to set a result, which you will receive in MainActivity.onActivityResult() when NewActivity finishes.
When you start NewActivity you need to use startActivityForResult and use a valid requestId. Such requestId will be passed back to you to onActivityResult once NewActivity finishes.