I'm venturing into startActivityForResult for the first time and I'm running into a problem.
Activity A (ActivityMyList) launches Activity B (ActivityQuickList) waiting for a result:
Intent intentLaunchQuickList = new Intent(ActivityMyList.this, ActivityQuickList.class);
startActivityForResult(intentLaunchQuickList, REQUEST_QUICKLIST);
When a user clicks on a list item of Activity B, it returns "ql_id" to Activity A:
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
QuickListItem qlItem = m_Adapter.getItem(position);
if (qlItem != null && qlItem.getQLId() != -1) {
Intent data = new Intent();
data.putExtra("ql_id", Integer.toString(qlItem.getQLId()));
if (getParent() == null) {
setResult(Activity.RESULT_OK, data);
}
else {
getParent().setResult(Activity.RESULT_OK, data);
}
finish();
}
finish();
}
Integer.toString(qlItem.getQLId()) evaluates to "1". This is important because I am not receiving "1"...
I have overridden the onActivityResult handler in Activity A with this:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_QUICKLIST) {
if (resultCode == Activity.RESULT_OK) {
Bundle extras = data.getExtras();
if (extras != null) {
int id = extras.getInt("ql_id");
}
}
}
}
Unfortunately, extras.getInt("ql_id") evaluates to "0". Why is this? It should be "1". I am clearly doing something incorrectly.
Thank you for your help
Ah, nevermind. I'm putting a String into the bundle and pulling an int out.
Related
I have created two Activities.
Main Activity.java(This is the activity that application launches with, user click on a button called "Show timer" which takes the user to the next activity)
displayTimer.java(This is the second activity which has a ListView, with data in each row. on item click users comes back to the main activity)
I'm trying to pass the string stored in that row to the main activity.
This is the main code from display timer activity
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.user_list_view);
listView = (ListView) findViewById(R.id.customtimer_listview);
customTimerAdapter = new CustomTimerAdapter(this, R.layout.row);
BackGroundTask backGroundTask = new BackGroundTask(this);
backGroundTask.execute("Get_info");
registerForContextMenu(listView);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView textView = (TextView) view.findViewById(R.id.time_entered);
String timeRetrevied = textView.getText().toString();
//System.out.println(timeRetrevied);
Intent intentExtras = new Intent(displayTimer.this,MainActivity.class);
intentExtras.putExtra("TIME_DATA",timeRetrevied);
setResult(RESULT_OK, intentExtras);
//startActivityForResult(intentExtras,SECOND_ACTIVITY_REQUEST_CODE,null);
finish();
}
});
}
This is the code from the Main activity where i'm calling the method onActivityResult to get the data through intent from displaytimer. But i'm not able to get the data. Dont know what i'm doing wrong. Any input with be fine.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == SECOND_ACTIVITY_REQUEST_CODE){
if (resultCode == RESULT_OK) {
int setTimer = Integer.parseInt(data.getDataString());
System.out.println(setTimer);
seekbar.setProgress(setTimer * 60);
updateTimer(setTimer);
}
else{
System.out.println("Not Ok");
}
}
System.out.println("RequestCode failed");
}
}
Instead of
data.getDataString()
use
data.getStringExtra("TIME_DATA")
getDataString returns the URI in the encoded String format, which is not what you require as you are not passing in the data.
As you are passing in the Sting text with ID=TIME_DATA, use the same ID to get the string back using the getStringExtra("TIME_DATA");
I have implemented FragmentStatePagerSupport. I have 142 pages. I have also an activity that is MyListActivity and has ListView. When I click ListView item, it returns a page number. I want to use this page number for viewPager current page. viewPager.setCurrentItem() doesn't work in onActivityResult.
Here is how I call startActivityForResult:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu1:
Intent intent = new Intent(this, MyListActivity.class);
startActivityForResult(icindekiler, 0);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
And here is the listView of MyListActivity:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ListViewContent selectedItem = (ListViewContent) parent.getItemAtPosition(position);
int pageNo = book.getSpine().getResourceIndex(selectedItem.getResource().getHref());
Intent data = new Intent();
data.putExtra("PageNo", pageNo); // pageNo: 0 or 1 or 2 or ... or 142
setResult(0, data);
finish();
}
});
onActivityResult method in FragmentPageStateSupport activity:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 0 && resultCode == 0) {
if (data.hasExtra("PageNo")) {
pageNo = data.getExtras().getInt("PageNo");
Toast.makeText(getBaseContext(), "pageNo is " + pageNo, Toast.LENGTH_SHORT).show();
viewPager.setCurrentItem(pageNo);
}
}
}
For example pageNo is 11, Toast says "pageNo is 11" but viewPager doesn't change. When I use debugging in Android Studio, application runs Looper.java. I try viewPager.setCurrentItem(11) on different method (for example button click), this time it is working.
I am confused and have no idea on how to use the startActivityResults and setResults to get data from previous activity. I have a view class and a activity class.
Basically in my view class i have this dialog and it will actually start the activity class called the colorActivity class. When user selects yes also it will pass the name of the selected circle to the colorActivity class. At the colorActivity class, users are allowed to enter color code for a particular circle and i would like to pass the color code back to the view class. I have problems passing values from activity back to view using the startActivityForResult and setResult method. Adding on, how to make use of the fetched data afterthat?
my code are as follows
Ontouchevent code from my view class:
#Override
public boolean onTouchEvent(MotionEvent event) {
x = event.getX();
y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
for (int i = 0; i < circles.size(); i++) {
if (circles.get(i).contains(x, y)) {
circleID = i;
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
AlertDialog.Builder builder = new Builder(
getContext());
final EditText text = new EditText(getContext());
builder.setTitle("Adding colors to circles").setMessage(
"Proceed to Enter color");
builder.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface di,
int i) {
Intent intent = new Intent(
getContext(),
colorActivity.class);
intent.putExtra("circlename", circleNameList.get(circleID));
startActivityForResults(intent, 1); // error incurred here : The method startActivityForResult(Intent, int) is undefined for the type new DialogInterface.OnClickListener(){}
}
});
builder.setNegativeButton("No",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface di,
int i) {
}
});
builder.create().show();
}
}, 3000);
break;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) { // Please, use a final int instead of hardcoded
// int value
if (resultCode == RESULT_OK) {
ccode = (String) data.getExtras().getString("colorcode");
}
}
}
public static String getColorCode() {
return ccode;
}
In the colorActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_ecolor);
circlenametextview = (TextView)findViewById(R.id.circlenametextview);
String circlename = super.getIntent().getStringExtra("circlename");
circlenametextview.setText(circlename);//get the circle name
savebutton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent = new Intent(colorActivity.this, ?????);//how to return back to the view class?
colorcode = colorEditText.getText().toString();// I am able to get value right up till this point
Intent resultIntent = new Intent();
resultIntent.putExtra("colorcode", colorcode );
setResult(Activity.RESULT_OK, resultIntent);
finish();
}// onclick
});
}
After correcting the other code so that you can run the program, you can retrieve parameters back from your activity colorActivity in this way:
Step1: return some value from colorActivity
Intent resultIntent = new Intent();
resultIntent.putExtra("NAME OF THE PARAMETER", valueOfParameter);
...
setResult(Activity.RESULT_OK, resultIntent);
finish();
Step 2: collect data from the Main Activity
Overriding #onActivityResult(...).
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) { // Please, use a final int instead of hardcoded int value
if (resultCode == RESULT_OK) {
String value = (String) data.getExtras().getString("NAME OF THE PARAMETER");
References
http://developer.android.com/training/basics/intents/result.html
How to manage `startActivityForResult` on Android?
http://steveliles.github.io/returning_a_result_from_an_android_activity.html
STARTACTIVITYFORRESULT IS NOW DEPRECATED
Alternative to it and recommended solution is to use Activity Result API
You can use this code, written in Kotlin language:
Create ResultLauncher:
private var resultLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val data: Intent? = result.data
if (null != data && data.getBooleanExtra("REFRESH_PAGE", false)) {
//do your code here
}
}
}
start Activity by using above result launcher:
val intent = Intent(this, XYZActivity::class.java)
resultLauncher.launch(intent)
Return result from XYZActivity by
val resultIntent = Intent()
resultIntent.putExtra("REFRESH_PAGE", true)
setResult(Activity.RESULT_OK, resultIntent)
finish()
try using
ActivityName.this.startActivityForResult(intent,int)
Oh, and 1 small thing, in your code you have used
startActivityForResults(intent,int) ..replace that with
startActivityForResult(intent,int)
I have an app that has a few tabs. These tabs are all fragments. On the first tab fragment, I have a text view and a button, which I press on to call an activity.
This activity displays a list of items, car names.
I want to be able to click on a car in the list and return back to the calling fragment and update the text view with the car name I selected.
Can anyone help me out with this?
startActivityForResult() is probably what you're looking for. So a quick example (making super-basic assumptions about your data structure -- substitute as required) would be to make your fragment override onActivityResult(), define a request code, and then start the activity using that request code:
// Arbitrary value
private static final int REQUEST_CODE_GET_CAR = 1;
private void startCarActivity() {
Intent i = new Intent(getActivity(), CarActivity.class);
startActivityForResult(i, REQUEST_CODE_GET_CAR);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// If the activity result was received from the "Get Car" request
if (REQUEST_CODE_GET_CAR == requestCode) {
// If the activity confirmed a selection
if (Activity.RESULT_OK == resultCode) {
// Grab whatever data identifies that car that was sent in
// setResult(int, Intent)
final int carId = data.getIntExtra(CarActivity.EXTRA_CAR_ID, -1);
} else {
// You can handle a case where no selection was made if you want
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
Then, in the CarActivity, wherever you set a click listener for your list, set the result and pass back whatever data you need in an Intent:
public static final String EXTRA_CAR_ID = "com.my.application.CarActivity.EXTRA_CAR_ID";
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Assuming you have an adapter that returns a Car object
Car car = (Car) parent.getItemAtPosition(position);
Intent i = new Intent();
// Throw in some identifier
i.putExtra(EXTRA_CAR_ID, car.getId());
// Set the result with this data, and finish the activity
setResult(RESULT_OK, i);
finish();
}
call startActivityForResult(theIntent, 1);
In the activity started, once the user selects a car, make sure to put the car in an intent and set the result of the activity to that intent
Intent returnIntent = new Intent();
returnIntent.putExtra("result", theCar);
setResult(RESULT_OK, returnIntent);
finish();
Then, in your fragment, implement onActivityResult
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
if(resultCode == RESULT_OK){
String result = data.getStringExtra("result");
}
if (resultCode == RESULT_CANCELED) {
//Write your code if there's no result
}
}
} //onActivityResult
Make Sure to override onActivityResult() in the fragment's hosting activity too, and call the super
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
This is because the parent activity hijacks the onActivityResult method, and if you don't call super() then it wont get passed to the fragment to handle it
I've ran into an infuriating issue with my Android development- whenever I call startActivityForResult(this, Notepadv3.class);, my app skipps directly over it, not launching the new activity nor returning any result from it. It's as if the code wasn't there!
When I change this to mContext (I have defined mContext as Context mContext; in the beginning of the class), the app crashes with a NullPointerException.
I have used the exact same code layout in a different class, and it runs flawlessly.
I've verified that I'm properly declaring the activities in the Manifest.
I've spent hours searching stackoverflow for answers, as well as looking up countless examples of how to do this particular activity, to no avail. I'm in the process of learning how to write Android apps, and as such have used Google's Notepad tutorial to base my app on. Thanks for the much appreciated assistance in advance!
Code and stack trace is as follows:
NoteEdit.java: (I've skimmed some irrelevant code for readability's sake)
public class NoteEdit extends Activity implements OnClickListener {
Context mContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDbHelper = new NotesDbAdapter(this);
mDbHelper.open();
setContentView(R.layout.note_edit);
setTitle(R.string.edit_item);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == REQUEST_BARCODE) {
if (resultCode == RESULT_OK) {
barcode = (intent.getStringExtra("SCAN_RESULT"));
new updateBarcodeField().execute("");
} else if (resultCode == RESULT_CANCELED) {
}
}else if (requestCode == REQUEST_NEW) {
System.out.println("REQUEST_NEW onActivityResult().");
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
saveState();
outState.putSerializable(NotesDbAdapter.KEY_ROWID, mRowId);
}
#Override
protected void onPause() {
super.onPause();
saveState();
}
private void saveState(){
System.out.println("saveState()");
doorCall();
mDbHelper.open();
String title = mTitleText.getText().toString();
String barcode = mBarcodeText.getText().toString();
String price = mPriceText.getText().toString();
Intent requestNew = new Intent(mContext, Notepadv3.class);
if (returnCode == 1){
System.out.println("returnCode is 1. Calling validateFields()...");
String errors = validateFields(title);
if (errors.length() > 0) {
Toast.makeText(this, "Oops! Need a title!", duration).show();
System.out.println("Calling Notepadv3...");
startActivityForResult(requestNew, REQUEST_NEW);
}
}
if (returnCode == 2){
System.out.println("returnCode == 2 - Cancelling activity");
}else{
if (title.matches("")){
System.out.println("Variable is null. Returning...");
doorCall();
mDbHelper.close();
return;
}else{
System.out.println("Checking mRowId for null");
if (mRowId == null) {
Toast.makeText(this, "Success, product saved successfully", duration).show();
System.out.println("Switching activity to 'NotesDbAdapter'");
long id = mDbHelper.createNote(title, barcode, price);
mRowId = id;
}else{
System.out.println("mRowId is not null. Calling updateNote");
mDbHelper.updateNote(mRowId, title, barcode, price);
}
}
}
System.out.println("saveState() Finished");
if (doorCall()==true){
System.out.println("Database is Open");
}else{
System.out.println("Database is Closed");
}
}
}
Notepadv3.java:
public class Notepadv3 extends ListActivity implements OnClickListener {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.notes_list);
mDbHelper = new NotesDbAdapter(this);
mDbHelper.open();
mAddButton = (Button) findViewById(R.id.addButton);
mAddButton.setOnClickListener(this);
mScanButton = (Button) findViewById(R.id.scanButtonList);
mScanButton.setOnClickListener(this);
fillData();
registerForContextMenu(getListView());
}
#SuppressWarnings("deprecation")
private void fillData() {
Cursor notesCursor = mDbHelper.fetchAllNotes();
startManagingCursor(notesCursor);
// Create an array to specify the fields we want to display in the list (only TITLE)
String[] from = new String[]{NotesDbAdapter.KEY_TITLE, NotesDbAdapter.KEY_PRICE};
// and an array of the fields we want to bind those fields to (in this case just text1)
int[] to = new int[]{R.id.text1, R.id.text2};
// Now create a simple cursor adapter and set it to display
SimpleCursorAdapter notes =
new SimpleCursorAdapter(this, R.layout.notes_row, notesCursor, from, to);
setListAdapter(notes);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.addButton:
createNote();
break;
case R.id.scanButtonList:
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
intent.putExtra("SCAN_MODE", "ONE_D_MODE");
startActivityForResult(intent, REQUEST_BARCODE);
}
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.add(0, DELETE_ID, 0, R.string.menu_delete);
}
#Override
public boolean onContextItemSelected(MenuItem item) {
switch(item.getItemId()) {
case DELETE_ID:
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
mDbHelper.deleteNote(info.id);
fillData();
return true;
}
return super.onContextItemSelected(item);
}
public void createNote() {
Intent i = new Intent(this, NoteEdit.class);
startActivityForResult(i, ACTIVITY_CREATE);
}
private void viewNote() {
System.out.println("viewNote(). Starting NoteEdit...");
Intent i = new Intent(this, NoteView.class);
i.putExtra(NotesDbAdapter.KEY_BARCODE, barcode);
startActivityForResult(i, ACTIVITY_EDIT);
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Intent i = new Intent(this, NoteEdit.class);
i.putExtra(NotesDbAdapter.KEY_ROWID, id);
startActivityForResult(i, ACTIVITY_EDIT);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
System.out.println("Notepadv3. requestCode is " + requestCode + ", and resultCode is " + resultCode);
if (requestCode == REQUEST_BARCODE) {
if (resultCode == RESULT_OK) {
barcode = (intent.getStringExtra("SCAN_RESULT"));
System.out.println("Calling viewNote()...");
viewNote();
} else if (resultCode == RESULT_CANCELED) {
} else if (resultCode == RESULT_FIRST_USER) {
}
}else if (requestCode == REQUEST_NEW){
System.out.println("Notepadv3. requestCode is REQUEST_NEW. Calling createNote()...");
createNote();
}
super.onActivityResult(requestCode, resultCode, intent);
fillData();
}
}
Stack trace:
FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to pause activity {com.android.demo.notepad3/com.android.demo.notepad3.NoteEdit}: java.lang.NullPointerException
at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2706)
at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2662)
at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:2640)
at android.app.ActivityThread.access$800(ActivityThread.java:123)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1158)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at android.content.ComponentName.<init>(ComponentName.java:75)
at android.content.Intent.<init>(Intent.java:3148)
at com.android.demo.notepad3.NoteEdit.saveState(NoteEdit.java:206)
at com.android.demo.notepad3.NoteEdit.onPause(NoteEdit.java:187)
at android.app.Activity.performPause(Activity.java:4590)
at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1195)
at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2693)
First of all, if you use mContext, you should initialize it in the onCreate method:
mContext=getApplicationContext();
//I recommend using the application context for avoiding memory leaks
Don't start an Activity from the onPause method.
I fixed it!!!
This won't be a fix for most that are looking for answers, but I hope I can point you in the right direction. As new as I am to Android (and Java in general), I am still totally convinced that this 'skipping' of code is, in fact, a bug.
However! As I'm calling saveState() from another activity, instead of launching a new intent that launches an activity from a separate class, which then launches an activity from the class where the first intent originated from, I simply replaced it with return;. Yeah- still quite derpy with learning the logic, but there it is. Simple, elegant, solution (well, simple and elegant compared to the horrendous code that existed before it :P)