I have a ListActivity which displays all the aggregate contacts. When the user clicks one, my code calls startActivityForResult. All this works properly. When the user finishes editing, I want my ListActivity to be displayed again. Instead, the "people" activity gets displayed. Similarly, my onActivityResult function never gets called.
Here is the code handling the click:
#Override
public void onItemClick (AdapterView<?> parent, View view, int position, long id)
{
Cursor cur = ((SimpleCursorAdapter)parent.getAdapter()).getCursor();
cur.moveToPosition (position);
String key = cur.getString (2); // "2" is the col containing the LOOKUP_KEY
System.out.println ("clicked " + key);
// make intent to edit contact
Intent intent = new Intent (Intent.ACTION_EDIT);
intent.setData (Uri.parse (ContactsContract.Contacts.CONTENT_LOOKUP_URI + "/" + key));
startActivityForResult (intent, 2);
}
And I also have an onActivityResult function:
#Override
protected void onActivityResult (int requestCode, int resultCode, Intent data)
{
System.out.println ("request " + requestCode + ", result " + resultCode);
}
Any suggestions?
I filed a bug to android about this. Someone looked at it and responded that there is an undocumented workaround. From the bug report:
The undocumented workaround is to call putExtra("finishActivityOnSaveCompleted", true); on the ACTION_EDIT Intent.
However, as this is undocumented, I have no idea which Android version(s) will use it.
I tried it and it works for the version of Android I'm using: 4.1.2. See issue 39262 for more info.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check which request we're responding to
if (requestCode == 2) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
// The user picked a contact.
// The Intent's data Uri identifies which contact was selected.
// Do something with the contact here (bigger example below)
}
}
}
Replace your onActivity result to this. for request code get after
they will work
Add
super.onActivityResult(requestCode, resultCode, data);
in OnActivtyResult().
Make sure you are calling startActivityForResult from an activity, then only your onActivityResult will be called. For example, if you have the similar code in an fragment, the onActivityResult will never be called.
Related
I have a share button in my application, whose purpose is to share a string of information with user selected app (for example twitter or gmail). The problem is when you click the share button, the share window appears and the app becomes black in the background. After done sharing, the user is returned to menu / home screen and has to open the app again in order to continue using it from where they left.
What I need is to go back to my app after done sharing.
This is the OnClickListener I used:
shareButton.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View view) {
String text = mContext.getString(R.string.shareText) + " " + profileInfo.getName() + " " + mContext.getString(R.string.shareText2);
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_TEXT, text);
shareIntent.setType("text/plain");
startActivity(shareIntent);
}
}
);
What am I doing wrong here? Any help is appreciated.
Use startActivityForResult() instead of startActivity(). This will return to the starting Activity after the Intent action is completed. See the Getting a Result from an Activity post for an example.
And wait for response by overriding onActivityResult() method :
#Override public void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub if(requestCode == 0) {
// You will get callback here when email activity is exited
// perform you task here
}
There is noting wrong with your share intent code which you mentioned above, although there could be some thing wrong with your onPause() method, you probably doing some thing there, try to debug the code after adding logs So you can track the issue OR put your activity code here So exact issue can be identified.
When im trying to delete a show with an AsyncTask. I want to call finish() after the AsyncTask has been completed and return an Intent with the result.
from the activity:
new DeleteShowTask().execute();
Intent intent = new Intent(SeasonActivity.this, FragmentShows.class); // I'm not sure if this works
intent.putExtra("tvdbid", tvdbId);
setResult(DELETECODE, intent);
finish();
then in the fragment i have this:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d("RESULTCODE", resultCode + "");
Log.d("REQUEST CODE", requestCode +"");
if (resultCode == SeasonActivity.DELETECODE)
{
if (requestCode == SeasonActivity.SHOW)
{
String tvdbid = data.getStringExtra("tvdbid");
for (int i = 0; i < adapter.getCount(); i++) {
SickbeardSerie serie = adapter.getItem(i);
if (serie.getTvdbId().equals(tvdbid))
{
adapter.remove(serie);
adapter.notifyDataSetChanged();
}
}
}
}
}
But it seems like it doenst run through this onAcitivityResult().
I have logged the onActivityResult() as you see but i dont get any logs.
Only thing i get is: 10-19 16:21:44.631: W/FragmentActivity(27672): Activity result fragment index out of range: 0x2fffe
I fixed it for now by using a work around.
I now reload my AsyncTask in the onResume() instead of just removing an item from the arraylist and calling adapter.notifyDataSetChanged(). But its not the best solution.
if you using a Fragment in a another Fragment. You should be call
getParentFragment().startActivityForResult(i, SELECT_PICTURE);
I'm wondering if I am understanding the concepts of requestCode correectly. What is this integer for and does it matter what integer I set it to in:
private static int CAMERA_REQUEST = ???;
Thank you
The requestCode helps you to identify from which Intent you came back. For example, imagine your Activity A (Main Activity) could call Activity B (Camera Request), Activity C (Audio Recording), Activity D (Select a Contact).
Whenever the subsequently called activities B, C or D finish and need to pass data back to A, now you need to identify in your onActivityResult from which Activity you are returning from and put your handling logic accordingly.
public static final int CAMERA_REQUEST = 1;
public static final int CONTACT_VIEW = 2;
#Override
public void onCreate(Bundle savedState)
{
super.onCreate(savedState);
// For CameraRequest you would most likely do
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
// For ContactReqeuest you would most likely do
Intent contactIntent = new Intent(ACTION_VIEW, Uri.parse("content://contacts/people/1"));
startActivityForResult(contactIntent, CONTACT_VIEW);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (resultCode == Activity.RESULT_CANCELED) {
// code to handle cancelled state
}
else if (requestCode == CAMERA_REQUEST) {
// code to handle data from CAMERA_REQUEST
}
else if (requestCode == CONTACT_VIEW) {
// code to handle data from CONTACT_VIEW
}
}
I hope this clarifies the use of the parameter.
Look my example here. The integer you have to set can be any one positive. Only do not make them the same, you don't want to mix them, do you? And don't put them to 0 - it is returning without result, IMHO, I had strange behaviours with 0. As for negatives, don't use them, too, they are reserved for negative results in other callActivities functions.
public void onActivityResult(int requestCode, int resultCode, Intent data)
app receives results from the different intents via above method only. So how will you understand which intent had replied to you? For that reason, before invoking the intents we put a self defined TAG/Label which is called requestCode. By our own defined requestCODE we can check which intent's result we have received.
Here in requestCode in the example I have given 1001 for Camera Intent. You can put any of your desired number. 1200 or 2001 or 21. Any Positive integers ranging to ~2^16.
See the picture attached.
Using an integer out of the range will raise a "java.lang.IllegalArgumentException: Can only use lower 16 bits for requestCode" exception.
So keep in mind that request is not just any positive integer but an integer of 16 bits, so from 0 to 65535.
Similarly, validateRequestPermissionsRequestCode in FragmentActivity requires requestCode to be of 8 bits, so between 0 and 255.
I know the listeners are supposed to make life easier, especially in a multi-tasking environment like android, but sometimes (to me) it just makes things harder.
Right now I have an ExpandableList activity which presents a list of events, and I want the user to select the group & child of interest and select a notification sound that will play when that event happens. So the list is set up and I have a setOnChildClickListener set up which runs my SetRingtone method:
protected void SetRingtone(int groupPosition, int childPosition) {
Intent intent = new Intent( RingtoneManager.ACTION_RINGTONE_PICKER);
intent.putExtra( RingtoneManager.EXTRA_RINGTONE_TYPE,
RingtoneManager.TYPE_ALL);
intent.putExtra( RingtoneManager.EXTRA_RINGTONE_TITLE,
"Select Tone");
startActivityForResult( intent, PICK_NOTIFICATION_SOUND);
}
So that method has access to the selected group and child positions. The problem is that to get the ringtone selected from the ringtone selector, you have to set up another lister, onActivityResult:
protected void onActivityResult(int requestCode,
int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
Uri uri =
data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
if (uri != null) {
String ringTonePath = uri.toString();
ExpandableListView variableView =
(ExpandableListView)findViewById(android.R.id.list);
int p = variableView.getSelectedItemPosition();
Log.d("phca", "The selected item number was: " +
p + "; The sound selected is: " + uri );
}
}
}
And now I don't have access to the selected group and child. As you can see, I tried to get the position from the getSelectedItemPosition, but it always returns -1 here.
I know I am probably making this harder than it really is.
You could just store the group and child in instance variables before the call to startActivityForResult and then use these instance variables in onActivityResult.
Did you try to use variableView.getSelectedItem()?
If this return null so it mean that something wrong with your list
First post, so please go easy.
I have an app with a handful of tabs, the first is opened on running the app.
One of the tabs is 'My Account' (a ListActivity) showing account options. I switch to this and if the user is not logged in, it, in turn, runs a UserLogon activity using the following:
Intent logonActivity = new Intent(getBaseContext(), UserLogon.class);
startActivityForResult(logonActivity, 0);
To catch the result, I use the following code:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 0){
MainBlock ta = (MainBlock) this.getParent();
TabHost th = ta.getMyTabHost();
th.setCurrentTab(0);
finish();
}
if (requestCode == 100)
{
showAccountOptions();
}
}
In the UserLogon class, I have the usual fare; TextView's and Button's. The intention is that if the user cancels the login, it will revert to the initial tab, or if login is successful, it will show the Account Options. And this is indeed what does happen.
All good so far.
The problem I'm having is that if I cancel the login and return to the first tab, when I select the Accounts tab again, I'm not presented with the UserLogon activity. I was under the impression that finish() would close the UserLogon activity, and the Accounts activity but it would appear not.
So, my question is simply, how do I, in effect, restart the Accounts activity so that the user would be presented with the option to login once more.
We're good people and all willing to help ;-) I'll give it a shot. Still, I'm not quite sure I get that all right.
Basically you have an TabActivity which you setup and where you do something like that:
myTabHost.setOnTabChangedListener(new OnTabChangeListener(){
#Override
public void onTabChanged(String tabId) {
if (tabId.equals("account") && !loggedIn) {
Intent logonActivity = new Intent(getBaseContext(), UserLogon.class);
startActivityForResult(logonActivity, 0);
}
}});
You're basically saying that the first Activity start of UserLogon works, but the second one doesn't, right? Did you debugged to that point to check whether you reach the code which starts the activity again?
Update based on comment
Your UserLogon should always provide a result information, here's a blueprint:
public class UserLogon extends Activity {
public void onCreate(Bundle bundle) {
// ... do something ...
// if activity is canceled this will be the "last" result
setResult(RESULT_CANCELED);
}
public void checkLoginOrSomethingLikeThat() {
Intent result = new Intent();
// put your results in this intent
setResult(RESULT_OK, intent);
// close activity since we have the information we need
finish();
}
}
The parent activity which is waiting for the result should do it like that:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// it's good practice to use a constant for 0 like LOGIN_REQUEST
// otherwise you will ask yourself later "What the hell did 0 stand for?"
if(requestCode == 0){
if (resultCode == RESULT_OK) {
// get needed data from data intent and react on that
} else {
// no success, react on that
}
}
// ... I don't know what your resultCode 100 is but handle itwith the same pattern
}