I have an activity to add an object to a database in my application, and the database is displayed in activity which calls an AddActivity. My problem is I need to refresh ArrayList after i update a database, but i can't have access to it inside my AddActivity. So i wanted to track in MainActivity when the AddActivity has ended and then call the refreshing function. For now i tried using code below and this is working, but i don't think this is the way i should do it, I feel like there is better function for that but I couldn't find it.
Code in MainActivity inside onClickListener:
Intent intent = new Intent(mContext, ExerciseAdd.class);
startActivityForResult(intent, 1);
Code in AddActivity also inside onClickListener:
dataBaseAccess = ExercisesDataBaseAccess.getInstance(getApplicationContext());
dataBaseAccess.open();
dataBaseAccess.addExercise(nameString, typeString, "NULL");
dataBaseAccess.close();
Intent intent = new Intent();
intent.putExtra("result", 1);
setResult(1, intent);
finish();
And refhresing function in MainActivity:
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
dataBaseAccess.open();
exercises = dataBaseAccess.getAllExercises();
dataBaseAccess.close();
adapter.setExercises(exercises);
adapter.notifyDataSetChanged();
}
Or maybe is there any way to pass an reference to ArrayList to AddActivity? it was hard to me to find any information about this
The way you are doing it is the most robust and clean way. You are storing your data in the database and you have one Activity that adds items to the database and another Activity that reads the data from the database and displays it. This may seem like overkill, but this architecture is more robust than sharing data in memory between activities.
Of course, it is possible to share data in memory between activities. You can store a reference to your ArrayList<Exercise> in a public static variable and it can be accessed by both activities. This is a simple way to share data but can be tricky if your app goes to the background and Andriod kills off the OS process hosting the app and then the user returns to the app. If he was last using the AddActivity, when he returns to the app, Android will create a new OS process to host the app and instantiate the AddActivity, but MainActivity is not yet instantiated and your shared public static data will be gone. So this approach is error-prone.
Another approach would be to use Live Data. This is a more complicated approach to sharing data in memory between activities. You can read more about live data here: https://developer.android.com/topic/libraries/architecture/livedata
Related
So I have a Fragment that calls the following method which launches the camera:
private void launchCamera() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
And I expect to receive the picture data in this method in my fragment:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (!(resultCode == RESULT_OK)) return;
if (requestCode == REQUEST_IMAGE_CAPTURE || requestCode == REQUEST_GALLERY_IMAGE) {
Uri imageURI = data.getData();
// do something
}
}
However, after I take a picture and confirm it, the app goes to my launcher. After setting breakpoints in the onActivityResult method, the app never even reaches this method before crashing. I've granted made sure to grant all permissions in both the manifest and at runtime.
There are also no outputs to Logcat with this crash, both in the app logs and the device logs. I have also tested on both my device (Moto G5 Plus) & Pixel XL API 26 emulator; both have the same result.
I think you need to call super.onActivityResult().
The fragment is the one making the startActivityForResult() call, but the activity gets the first shot at handling the result so you need to implement super.onActivityResult() to make the fragment handle the result.
the app immediately crashes to my launcher
No, the camera app immediately brings up the launcher. Apparently, the developers of this camera app wrote it to bring up the home screen when the user is done taking the picture. This is a bug, of course, but there is little that you can do about it.
Use ACTION_IMAGE_CAPTURE when you would like a picture but do not mind if you do not get it, due to bugs in some of the hundreds of camera apps that you are integrating with. Otherwise, use a camera library (Fotoapparat, CameraKit-Android, etc.) to take the picture directly in your own app.
Also, and FWIW, ACTION_IMAGE_CAPTURE does not return a Uri, so your onActivityResult() code will not work anyway. Given your particular ACTION_IMAGE_CAPTURE Intent configuration, in onActivityResult(), data.getParcelableExtra("data") will return a Bitmap representing a thumbnail-sized image.
I believe this is yet another manifestation of the Android: Activity getting Destroyed after calling Camera Intent.
The bottom line is, the system restarts your app from scratch and your activity is created but has a chance to restore its state.
So you must implement onRestoreInstanceState(). I am not sure you can guarantee that the fragment will be ready to receive onActiviyResult() timely, so to be in the safe side, I prefer to handle the captured image in activity itself.
So this issue was actually because of an intent flag I had attached to the activity. My activity was started using the NO_HISTORY intent flag, which apparently prevented it from being recreated when returned from a startActivityForResult call.
I'm developing two android applications let's call them app A and app B.
App A opens app B through and Share Intent and pass it params through a bundle, until this point it's ok, works.
Now, I want to realize some operations in app B and once these have finished close app B and return a message that operations has finished and the result of these operations to app A but I don't know how to solve it or how looking for.
I have thought another intent but it will reopen my app and delete the content of my screen that I have previously. Any suggestion?
Try to use ResultReceiver:
https://developer.android.com/reference/android/os/ResultReceiver.html
Or Messenger:
https://developer.android.com/reference/android/os/Messenger.html
I worked with ResultReceiver only, when developed SDK for one application. In first app you create an instance of ResultReceiver:
public ResultReceiver generateParcelableReceiver(ResultReceiver actualReceiver) {
Parcel parcel = Parcel.obtain();
actualReceiver.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
ResultReceiver receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel);
parcel.recycle();
return receiverForSending;
}
and then pass it as an extra parameter to Intent:
requestLogin.putExtra("EXTRA_TARGET_RECEIVER", mAndroidUtils.generateParcelableReceiver(emptyReceiver));
Where emptyReceiver is:
ResultReceiver emptyReceiver = new ResultReceiver(null) {
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
//do nothing
}
};
As you can see, it receives Bundle. And in your second application, retrive the receiver, and pass the result when needed.
NOTE
Please, make sure you use android.support.v4.os.ResultReceiver, because there is another implementation of it(with different package name), and it doesn't work very well. This implementation contains in:
compile 'com.android.support:appcompat-v7:23.1.1'
Consider scenario 1:
I have activity and launch another activity to do something. After 2nd activity done (action complete) - I need to update 1st activity. I understand this can be done using "launch for result"
Scenario #2:
I have service that runs on background, fetches data, etc. This also can update 1st activity. In this case activity can be live or it can be paused too.
In iOS I just use NotificationCenter and it works. How can I "register" to receive events in Activity and make sure it is updated even if activity sleeps at that moment? I was thinking about creating global flags and check them onResume, but not sure what is the proper way to handle this scenarios most proper and "loose" way?
There are two common options.
LocalBroadcastManager is provided by the compatibility library and will allow Android components in the same app to send and receive messages in the form of Intents. It's a lot like normal broadcasts.
You can also find a third party "event bus" library, which will be a little more flexible.
You are correct, you would use startActivityForResult() when starting your second activity. Then, in your first activity, override onActivityResult() which you will put logic in to receive the result from the second activity. For example:
First Activity
int REQUEST_CODE = 1;
Intent newActivityIntent = new Intent(this, SecondActivity.class);
startActivityForResult(newActivityIntent, REQUEST_CODE);
then override onActivityResult()
#Override
protected void onActivityResult (int requestCode, int resultCode, Intent data) {
// Make sure the result is OK.
if (resultCode == RESULT_OK) {
// Make sure this result is from the corresponding request.
if (requestCode == REQUEST_CODE) {
// Extract your data from the intent.
MyData myResultData = data.getExtra("my_extra"); // Generic example.
}
}
}
In the second activity you simply gather the information needed to send back when the user is finished, and put it in the return intent.
Second Activity
Intent returnIntent = new Intent();
returnIntent.putExtra("my_extra", data);
// Now set the result.
setResult(RESULT_OK, returnIntent);
// Call finish, and the return intent is passed back.
finish();
This is probably the easiest and least complex way to achieve what you want. This way, you know the activity receiving the result will always be unpaused when it gets the result.
I am new to Android so apologies if I am asking something silly. I am trying to develop an alarm clock application - basically, it's my final project and I am trying to develop an alarm like there is in API level 2.3.3.
I have designed the list view that takes input through a dialog box like time. I have also coded it to set an alarm.
Now I want to save that alarm as an intent in the other class, and I don't have any idea how to save different alarms in the other activity. I have also checked for the desk-clock alarm code but I didn't get that too.
Please help me someone, I am stuck here for the code for more than a week. Please someone help me, I shall be thankful to you.
If you want to send an Intent from one Activity to another, and then retrieve information from inside the Intent, the best way is use the Bundle object inside the intent:
Let's supose you send the intent from Activity1 to Activity2...
In Activity 1:
Intent intent = new Intent(Activity1.class,Activity2.class);
//I use the String class name as a key value, but you can use whatever key
intent.putExtra(String.class.getCanonicalName(), myString);
startActivity(intent);
//Or this other method if you want to retrieve a result from Activity2
//startActivityForResult(intent,Activity2);
In Activity 2:
Intent intent = this.getIntent();
Bundle bundle = intent.getExtras();
String myString = bundle.getString(String.class.getCanonicalName());
Say I have 2 activities (ActivityOne and ActivityTwo). How would I call ActivityTwo from ActivityOne? Then how would I return to ActivityOne from ActivityTwo? For example, I have a listview with all the contacts on the host phone. When I tap on a contact, another activity shows information and allows editing of that contact. Then I could hit the back button, and I would go back to the exact state that ActivityOne was in before I called ActivityTwo. I was thinking an Intent object, but I am not sure. Could someone post some code?
In your first activity (AcitvityOne) you could call
Intent intent = new Intent(this, ActivityTwo.class);
startActivityForResult(intent, CODE);
Then you can override
public void onActivityResult(int reqCode, int resultCode, Intent data) {
to receive the result of this activity
In your example, it seems like you will want to pass data between Activity One and Activity Two (namely, the reference of the contact you want to edit), so you should use a Bundle with your intent in Activity One.
Intent myIntent = new Intent(this, ActivityTwo.class);
myIntent.putExtra("CONTACT", position);
this.startActivity(myIntent);
"CONTACT" is a key and position is a value (position would have been defined before, it could be whatever you want it to be, for example an integer. The way you retrieve it is slightly different based on what type it is, note the getInt() in Activity Two code below).
And in Activity Two, in onCreate()
Bundle extras = getIntent().getExtras();
if (extras != null) {
contact = extras.getInt("CONTACT");
/**Do what you want with the integer value you have retrieved**/
}
As for your other question, the back button removes the current Activity from the top of the tasks stack and therefore, you return to the previous Activity, normally in exactly the same state as you have left it.
However, if the phone is running low on memory, Android might kill off a process or Activity so it is possible in theory that your previous Activity will not show in exactly the same state as you have left it. If you have any important data, you should save it before launching Activity Two. If you just want to return to Activity One in the same state for user friendliness, then it's fine to rely on the back button.