Calling a method from another Activity (call Fragment) - java

I have called method:
protected void ask(){
Fragment newContent = new QuestionsFragment();
((MainActivity) getActivity()).switchContent(newContent, R.string.questions, MenuFragment.questions_id, BottomActionBarMode.QUESTIONS);
}
MainActivity:
https://docs.google.com/file/d/0B30eXgoSJlFsczNSdkE5Qnc5eG8/edit?usp=sharing
Error:
08-21 17:16:28.574: E/AndroidRuntime(26360): FATAL EXCEPTION: main
08-21 17:16:28.574: E/AndroidRuntime(26360): java.lang.ClassCastException: com.chiv.successteritory.activities.AskLikeQuestionDetailsActivity cannot be cast to com.chiv.successteritory.activities.MainActivity
how to call? thanks in advance

If you are on MainActivity and starts the AskLikeQuestionDetailsActivity, it's not guaranteed that MainActivity is still there, as the OS can garbage collect any Activities on background.
If you want change a Fragment on MainActivity after the ask() method is called on AskLikeQuestionDetailsActivity, I would suggest you to do the following:
On MainActivity, instead of calling startActivity to start AskLikeQuestionDetailsActivity, call startActivityForResult and override the onActivityResult method to change the Fragment depending on the result received.
On AskLikeQuestionDetailsActivity's ask(), call setResult with Activity.RESULT_OK and a configured Intent to send some information back to MainActivity, then call finish() (if you have to exit the AskLikeQuestionDetailsActivity Activity right away).
Is it clear? Hope it helps.

In ask() AskLikeQuestionDetailsActivity:
Intent intent = new Intent(getActivity(), MainActivity.class);
int condition = 1;
intent.putExtra("condition", condition);
startActivity(intent);
In onCreate() MainActivity.class:
Bundle extras = getIntent().getExtras();
if (extras != null) {
showQuestions();
}

Related

Starting an Activity from a Notification and passing data onBackPressed

I have 3 Activities on the app:
MainMenuActivity -> ExecuteTrainingActivity -> ExecuteExerciseActivity.
From MainMenuActivity to ExecuteTrainingActivity, I'm passing an idExecution and an idExercise for ExecuteTrainingActivity query and load the initial data.
ExecuteTrainingActivity onCreate:
#Override
protected void onCreate(Bundle savedInstanceState) {
//...
initialize();
setupRecyclerView(exercises);
}
private void initialize() {
Bundle extras = getIntent().getExtras();
if (extras != null) {
if (extras.containsKey("id_execution")) {
idExecution = extras.getLong("id_execution");
idExercise = extras.getLong("id_exercise");
execution = queryExecution(idExecution);
} else {
insertExecution();
}
}
}
In the 3rd activity, ExecuteExerciseActivity, I have a TimerFragment that, and when TimerCountdown reaches 0, it opens a Notification popup, that when clicked open an fresh ExecuteExerciseActivity.
On this TimerFragment, I'm passing as Extras the same ids, so I can get them in the new fresh ExecuteExerciseActivity:
public class TimerFragment extends Fragment {
//...
private void showNotification(){
Intent intent = new Intent(getActivity(), ExecuteExerciseActivity.class);
intent.putExtra("id_execution", idExecution);
intent.putExtra("id_exercise", idExercise);
intent.putExtra("position", position);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(getActivity());
stackBuilder.addNextIntentWithParentStack(intent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
/*=== CHECK IF NOTIFICATION CHANNEL IS ACTIVE ===*/
boolean ok = isNotificationChannelEnabled(getActivity(), Constants.CHANNEL_ID);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(requireNonNull(getActivity()), Constants.CHANNEL_ID)
.setSmallIcon(R.drawable.d77)
.setContentTitle("Teste Notificação")
.setContentText("Ababa")
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getActivity());
notificationManager.notify(0, mBuilder.build());
}
From this new fresh ExecuteExerciseActivity, I want to make the system maintain the same navigation flow of Activities, but when I backpress from the new ExecuteExerciseActivity to ExecuteTrainingActivity, i can't pass the Id's for the ExecuteTrainingActivity query and load.
Is there a way to pass arguments onBackPress?
Is the best approach override onBackPress creating a new intent and a starting a new Activity?
**My manifest is using parentActivityName correctly.
Save your query and id into a SharedPreferences in onDestroy of your ExecuteExerciseActivity then pull out the query and id again in the old ExecuteTrainingActivity. onBackPressed triggers onDestroy event of an activity's life cycle. Then in the onResume of ExecuteTrainingActivity pull this data back out.
I think you can achieve this by overriding onOptionsItemSelected() method of ExecuteExerciseActivity. Try this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
Intent intent = new Intent(this, ExecuteExerciseActivity.class);
//Add the extras to the intent
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
In Android, if your Activity starts another Activity and want to pass data to that Activity, you would add those data as Intent extras.
This Activity A to Activity B type of sending data is something you're using already.
But for Activity B back to Activity A, there's actually a built-in solution for this, which is through startActivityForResult(Intent, REQUEST_CODE) instead of startActivity(Intent).
Now in Activity B, you simply have to code:
#Override
public void onBackPressed()
{
Intent resultIntent = getIntent();
resultIntent.putExtra(EXTRA_NAME, extra_value);
setResult(Activity.RESULT_OK, resultIntent);
finish();
}
Basically, in Activity B, you're setting the data you want to send back to the Activity A that started Activity B, since there's a connection between these two Activities.
Next, in your Activity A, just override the onActivityResult() method.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// get data through data.getIntExtra() and etc
}
}
}
The request code needs to match the REQUEST_CODE you used for Activity B, so Activity A knows which Activity to respond to. The result code is just a quick way for you to categorize the type of result you're getting back from Activity B, since there might be more than one type of result being returned from Activity B.
This solution of passing data is better than creating a new Intent and starting a new Activity because you don't need to start a new Activity. Your Activity A already exists, so there's no reason to rebuild the entire layout, reload all the data, and have a new Activity existing on the Activity stack.
Since your only intention is to pass data from Activity B back to the Activity A that started it, use startActivityForResult() and onActivityResult() to handle this type of data sharing.

Default Intent for launcher Activity

What is value of Intent of launcher activity
hello friends, I'm new to android. I'm working on android activity and Intent. As i did in my launcher activity
Intent in = new Intent(getApplicationContext(), SecondActivity.class);
startActivity(in);
and in second activity i use getIntent() method to get an reference of calling intent in OnCreate method as:
Intent in = getIntent();
if(in != null) //do something..
In second activity getIntent() method return the reference of calling intent. But when I Use getIntent() method in onCreate method of launcher activity, its value was not null. So what reference is passed to intent when we use getIntent() method in launcher activity
Well the Android OS starts the activity when you click your app_icon, it looks through your manifest file and finds the launcher activity and then launches it
Get the intent which has started your activity using the getIntent() method:
Intent intent = getIntent();
Your data is represented as strings, then you can use intent.getStringExtra(String name) method. In your case:
String id = intent.getStringExtra("id");
String name = intent.getStringExtra("name");

Intent onPostExecute() AsyncTask

Im running an AsyncTask in an inner class and once complete within the onPostExecute() I want to use an intent to pass values to another activity however I have two errors that im not sure how to fix.
The errors occur on the setResult() line at RESULT_OK and the finish() line explaining that these two actions cannot occur outside of an activity. How would i use this intent in the onPostExecute of the 'AsyncTask'?
Code:
protected void onPostExecute(Void result)
{
// TODO Auto-generated method stub
super.onPostExecute(result);
Intent intent = new Intent();
intent.putExtra("jobs", jobStatus);
intent.putExtra("requestsSent", requests);
setResult(RESULT_OK, intent);
finish();
}
you need use Context of Activity class like following for finish method:
YourActivity.this.finish()
and RESULT_OK exists on activity class, so you need:
Activity.RESULT_OK
so your code must be like following:
Intent intent = new Intent();
intent.putExtra("jobs", jobStatus);
intent.putExtra("requestsSent", requests);
setResult( Activity.RESULT_OK, intent);
YourActivity.this.finish()
setResult and finish() are method of Activity class. You will need activity context for the same
http://developer.android.com/reference/android/app/Activity.html.
Now pass the Activity context to the constructor of AsyncTask
new TheTask(ActivityName.this).execute(params);
Then
Context mContext;
public TheTask(Context context)
{
mContext = context;
}
If AsyncTask is an inner class of the Activity you can use ActivityName.this
((Activity) mContext).setResult(Activity.RESULT_OK, intent);
((Activity) mContext).finish();

Can startActivityForResult() send data?

I am learning android and curious to know as if startActivityForResult() contains the properties of startActivity() too, i.e. can it be used to send data like startActivity() beside receiving data from called activity?
Here is the code:
SendData Activity:
Intent data= new Intent(SendData.this, RecieveData.class);
Bundle check = new Bundle();
check.putString("UmerData", cheese);
medt.setText(cheese);
data.putExtras(check);
startActivityForResult(data, 5);
Should receive data in this activity (RecieveData Activity)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recievedata);
Initializek();
Bundle got = getIntent().getExtras();
String ss= got.getString("UmerData");
if(getIntent()!=null && ss!=null ) {
rt1.setText("Is not Null");
}
}
Your help will be really appreciated !
Thanks
Yes, startActivity & startActivityForResult, both take intent as param. You can bundle launch data inside intent and pass it over to target activity.
When you use startActivityForResult(), you have to also create a onActivityResult() method within the Activity that called startActivityForResult(). onActivityResult() is where you can access the Intent stored by the Activity you start for a result.
In the Activity that is then started, you have to call setResult() to store the Intent that you store the data in.
Read over this: http://developer.android.com/reference/android/app/Activity.html#StartingActivities
edit: Misread your question. For passing a Bundle of options through, I would use this overload:
startActivity(Intent, int, Bundle)
I'm working in Xamarin Android so the code is C# but I had the same problem except I'm sending between separate apps. I eventually got it working so here is my example.
var intent = new Intent();
intent.SetComponent(new ComponentName("com.company.packageName", "com.company.packageName.activityName"));
intent.PutExtra(Intent.ExtraText, message);
StartActivityForResult(intent, 1);
// in app being started
protected override void OnResume()
{
base.OnResume();
Intent intent = Intent; // Equivalent to getIntent()
if (intent != null)
{
string str = intent.GetStringExtra(Intent.ExtraText);
if (str != null)
{
// Do stuff with str
}
else
{
//Show Error
}
}
else
{
//Show Error
}
}

Activity being created twice on android

First of all, I'm new to Android Development so please have patience with me.
I'll start from the UI, I have a button that once you tap it, starts an activity for a result.
public class GUIActivity extends Activity
#Override
public void onClick(....){
Intent intent = new Intent(getApplicationContext(), GetImageActivity.class);
intent.putExtra("action", FROM_CAMERA);
startActivityForResult(intent, GET_IMAGE);
}
#Override
onActivityResult(int requestCode, int resultCode, Intent data){
Log(TAG, "onActivityResult");
//handle result
}
}
The GetImageActivity class is a wrapper for two other activities, one to capture an image from the camera and other to get it from the gallery. It returns and Uri object of the selected image.
public class GetImageActivity extends Activity{
private Uri mediaUri;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Bundle extras = getIntent().getExtras();
int action = extras.getInt("action");
Log.d(TAG, "onCreate");
switch(action){
case FROM_CAMERA:
mediaUri = Uri.fromFile(new File(....));
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT, mediaUri);
Log.d(TAG, "Calling camera activity"
startActivityForResult(intent, action);
break;
case FROM GALLERY:
//...
}
}
#Override
onActivityResult(int requestCode, int resultCode, Intent data){
Log.d(TAG, "onActivityResult");
switch(requestCode){
case FROM_CAMERA:
if(resultCode == Activity.RESULT_OK){
Intent data = new Intent();
data.putExtra("uri", mediaUri);
setResult(Activity.RESULT_OK, data);
finish();
}else{
Log.e(TAG, "Camera activity failed!");
setResult(Activity.RESULT_CANCELED);
finish();
}
break;
case FROM_GALLERY:
//...
}
}
}
This is what is expected to happen when the user clicks on the button:
The camera activity should start.
Once the user takes a picture it should send back its URI to the GUI class.
Sometimes (it's usually a 50% chance) it works at expected, but other times this is what happens:
The camera activity starts.
The user takes a picture.
The camera activity starts AGAIN.
The user can either take another picture or go back.
Either case, the URI that gets back to the GUI class does not exist.
I've added a couple of debug log lines to follow the sequence of events. When I get the bad behaviour this is the output I get:
GetImageActivity - onCreate
GetImageActivity - Calling Camera Activity
The camera opens, and once I've taken a picture it says:
GetImageActivity - onCreate (again)
GetImageActivity - Calling Camera Activity
GetImageActivity - onActivityResult
The camera opens for the second time. The user takes another picture and:
GetImageActivity - onActivityResult
GUIActivity - onActivityResult
So my question is... what could cause the GetImageActivity to be called twice?
The problem is improper handling of the Activity lifecycle.
The second call to onCreate is for handling the result.
Android may choose to destroy an Activity that is waiting for the call to onActivityResult; especially when free memory is running low. Some devices appear more aggressive about destroying Activitys that are on the task stack. I can reliably recreate the issue on a Samsung device set to a debugging mode called "strict mode".
You can verify whether this is your issue by logging calls to onCreate & onDestroy.
In the case of a destroyed activity, when the activity result needs to be processed, Android will recreate the Activity, passing a savedInstanceState to onCreate. So, the remedy is to check the value of savedInstanceState in your GetImageActivity.onCreate. If it is not null then don't make any calls to startActivity because your Activity is being recreated to call onActivityResult.
Optionally, if you need to preserve any state then override onSaveInstanceState(Bundle outState) and put data you need into outState.
Add this to your Activity definition in AndroidManifest.xml:
android:launchMode = "singleTask"
Add this to your Activity definition in AndroidManifest.xml:
android:launchMode = "singleInstance"
When you call startActivityForResult it is telling Android that you want the result to be delivered to the Activity which is making that call. Which explains what you see when you logged GetImageActivity - onCreate (again).
Since you call startActivityForResult in your first activity, that is, GUIActivity than you should be calling setResult in GetImageActivity to properly pass back the result.
So in GetImageActivity.onActivityResult() right before you call finish() you should call setResult so that when you return back to GUIActivity it can handle the expected result.

Categories