Android Use startActivityForResult from a nested activity in a tab. - android

I am writing an application that is composed of several tabs created in a tabhost with:
intent = new Intent().setClass(this, Home.class);
spec = tabHost.newTabSpec("Home").setIndicator("Home",
res.getDrawable(R.drawable.home))
.setContent(intent);
tabHost.addTab(spec);
In the tab in question I am using an ActivityGroup to change to different Activities in the tab:
Intent intent = new Intent(Info1.this, Enroll2.class);
intent.putExtra("info", Info);
View newView = Group.group.getLocalActivityManager().startActivity("Info1", intent
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
.getDecorView();
Group.group.replaceView(newView);
From one of these Activities I need to take a picture and I am trying to use the default camera app on the device using:
//define the file-name to save photo taken by Camera activity
String fileName = "picture" + Integer.toString(pictureCount);
//create parameters for Intent with filename
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, fileName);
values.put(MediaStore.Images.Media.DESCRIPTION,"Image capture by camera");
//imageUri is the current activity attribute, define and save it for later usage (also in onSaveInstanceState)
imageUri = getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
//create new Intent
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
This starts the camera app correctly, but after taking a picture it does not enter the onActivityResult method. I've tried placing this method in every class in the chain for the tab and it doesn't enter the code in any of them.
I noticed that this question was asked before at How to startactivityforresult in tab child of TabHost but the only potentially useful answer was a redirect to How to return a result (startActivityForResult) from a TabHost Activity? which is a question about using startActivityForResult from a basic Activity to start a tabActivity and not starting an Activity from a tabActivity so it was no use.
I also keep seeing people say that this doesn't work when you're using an ActivityGroup, but no one suggests how else to go about doing it.
Any help would be appreciated.

Alright, I was able to find a solution to this problem.
First, I created another activity that I started using the basic startActivity() call I called a Result Controller. This does not pass any data back to the tabbed activity which means you don't have to worry about where it's going.
Second, I created a simple static data class which I called DataConnector. The ResultController would get the instance of the DataConnector and insert the Data there
Then, in the original activity(in the tabs) I implemented the onWindowFocusChanged method to determine when the user is back to it. I got the instance of DataConnector and was able to pull the data I needed out of there.

Related

Video capture intent causing issues on low RAM device

The problem is pretty complex. Basically, I have a FragmentActivity (HomeActivity) that holds a fragment (CategoriesFragment) that holds another fragment (VideoFragment which covers the containing fragment completely when added) that I am using to record video which works great on most devices, but as I test on a SGH-T989 running android 4.1.2 the following happens. The VideoFragment that records video is gone when I am done recording and the underlying CategoriesFragment is visible. The onActivityResult() of the VideoFragment is not called, instead the HomeActivity onActivityResult() is called, but with a different request code than what I used to create the intent. I also get this warning in the log:
W/FragmentActivity﹕ Activity result fragment index out of range: 0x300c8
Both of these issues are probably caused by the fragment that sent the intent being destroyed for reason, and so it can't receive the intent result? Any ideas why this would happen?
Here is the code for creating the intent.
//Record Video
private void recordVideo() {
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_VIDEO);
// set video quality
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, mVideoLength);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file
// name
// start the video capture Intent
startActivityForResult(intent, CAMERA_CAPTURE_VIDEO_REQUEST_CODE);
}
I've searched for a long time on this one and any help, ideas or theories would be greatly appreciated
Here is what was happening. The activity that created the fragment that started the intent was destroyed on low RAM devices. The activity was then re-creating the fragment in its onCreate when the intent finished. You want to let Android OS handle the fragment re-creation if it was responsible for the destruction of the fragment so you just need to add this to your onCreate method
if (savedInstanceState == null) {
Create fragments
}else{
Let the OS create them
}

Android: Can I create an activity conditionally?

For eg: I am using one Activity for Different UI pages with different he. So I want to check if an activity with a particular parameter in the intent exists. If it does just bring it to the top or else create another instance of an activity.
I have tried adding the flag FLAG_ACTIVITY_CLEAR_TOP to the intent but that does not solve my purpose.Here is some code: I want to create an activity only if there is a new title.
Intent intent = new Intent(activity, MyActivity.class);
intent.putExtra(DISPLAY_NAME, title);
activity.startActivity(intent);

Canonical way of starting multiple nested activities and getting a result onActivityResult

I have the following requirement:
Activity A ---> Activity B ---> Open Gallery App
Traditionally, i launch nested activities using the TaskStackBuilder. So I would do something like this:
TaskStackBuilder tsb = TaskStackBuilder.create(this);
Intent activityIntentA = new Intent(this, ActivityA.class) // ...
tsb.addNextIntent(activityIntentA);
Intent activityIntentB = new Intent(this, ActivityB.class) // ...
tsb.addNextIntent(activityIntentB);
Intent galleryIntent = new Intent(Intent.ACTION_PICK);
galleryIntent.setType("image/*");
tsb.addNextIntent(galleryIntent);
// this.startActivities(new Intent[] {activityIntentA, activityIntentB, galleryIntent});
tsb.startActivities();
(A side question is if there's a difference between using a task stack builder or the startActivities() call).
The problem with this approach though, is that when the galleryIntent is closed, it doesn't call onActivityResult but rather calls the OnCreate method of ActivityB, which means i lose the information coming in from the gallery app, which is supplied through the intent param "data" on my onActivityResult call of activityB.
An alternative solution, would be to manually kick off the calls, so call first call Activity B, then with a flag/param/argument, launch the galleryIntent, and then follow the regular flow through with OnActivityResult.
Is there a better approach to solving this requirement?
I have the feeling that TaskStackBuilder doesn't adapt very well to your needs. I'd approach it in an easier manner.
*I'm assuming the interaction starts on activity A, and then you need to open the gallery, but need activity B to process the result.
I'd open activity B and launch the intent for the gallery from there. As soon as gallery delivers a result to B you can do any processing there.
After the extra processing and if you need to, you can always deliver another result from Activity B to A.
Note that you need activity B to be already created and listening for results before the gallery gets open.

Android default camera app opens twice

I am starting the default camera app on the android to get a picture in my app using the following code:
//create parameters for Intent with filename
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, fileName);
values.put(MediaStore.Images.Media.DESCRIPTION,"Image capture by camera");
//imageUri is the current activity attribute, define and save it for later usage (also in onSaveInstanceState)
imageUri = getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
//create new Intent
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
startActivityForResult(intent, actionCode);
and catch the picture in an onActivityResult method.
Often, this will work just fine and the device will take the picture and return it to the app, but sometimes after finishing with the camera app(by saving the image or hitting cancel) it will start the camera app a second time. How can I prevent the app from opening twice?
EDIT: Thanks to Krylez's comments I was able to put a solution in place.
I was already using a static class to hold the image from the camera so that it could be accessed by me tabbed Activity so I also put a boolean in there. Now, before I start the Activity to handle the camera I set that boolean to true, then after checking it I set it to false so that if the onCreate method is called again it will not load the camera a second time.
Thanks to Krylez's comments I was able to put a solution in place.
I was already using a static class to hold the image from the camera so that it could be accessed by me tabbed Activity so I also put a boolean in there. Now, before I start the Activity to handle the camera I set that boolean to true, then after checking it I set it to false so that if the onCreate method is called again it will not load the camera a second time.
I was able to solve this issue by using same boolean technique but by shared preferences, storing yes or no in preferences and wraping around new intent.
String val=sharedPref.getString(...);
if(val.equals("true"))
{ launch new intent
sharedPrefEditor.putstring("..","false");
sharedPrefEditor.commit();
}
it solved the problem and camera wil not run twice.
Thanks.

Launching activity through intents

I am implementing a simple app. I need to start an activity based on the state of the Activity. Lets take i am using a button to start the activity.
1. If the activity is not started, I need to start XYZ activity.
2. If the XYZ activity is on focus, then i need to close the activity on the button press.
3. If the XYZ activity is not in focus (like onPause) state then, I need to change the button state.
Can you please help me in the flags that i need to use for starting the intent.
Is it possible to get the state of activity before I start that activity?
Try this
Intent intent = new Intent(currentActivity.this, callingActivity.class);
startActivity(intent);
You can use intent like this to call an activity
The button press will need to be captured by each activity separately, so just code the different responses into each different activity.
First off create a MAIN.java activity that is going to house your other activities. Like others have said you're going to have to code the button captures yourself because that should be common sense if you're trying to deal with intents. When you get that together though, you can start a new activity through intent like so:
// allocate new intent, initialized to the activity you wish to launch
Intent i = new Intent(this, ActivityToBeLaunched.class);
// put information into intent
i.putExtras("KeyName", value); // where "KeyName" is simply a reference string
// and 'value' can be anything from boolean - string.
// launch activity and wait for response
startActivityForResult(i, REQUEST_CODE);
Then within your ActivityToBeLaunched.java class you'll have an oncreate that will pull information from the intent like such:
// get intent
Intent i = this.getIntent();
// get information from intent
booleanVariable = i.getExtras().getBoolean("KeyName");
When you're done with this activity simply use;
// create intent
Intent i = new Intent();
// put information into result to send back to parent
i.putExtras("KeyName", value);
// set the result to be returned
setResult(i, ResultCode);
// finish child, return to parent with results
finish();

Categories

Resources