I have the MainActivity from where I am starting the SecondActivity.
There, I select an image from gallery and I want to push it back to the MainActivity.
MainActivity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
...
srButton = findViewById(R.id.super_resolution)
srButton.setOnClickListener { view: View ->
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)
val bitmap = getIntent().getParcelableExtra<Bitmap>("bitmap")
SecondActivity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_selected_image)
image = findViewById(R.id.the_selected_image);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
val permissions = arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE)
requestPermissions(permissions, SelectedImage.PERMISSION_CODE)
} else {
chooseImageGallery()
}
} else {
chooseImageGallery()
}
}
// Receiver for camera
private val getResultCamera =
registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
if (it.resultCode == Activity.RESULT_OK) {
image.setImageURI(it.data?.data)
imageUri = it.data?.data as Uri
bitmap = uriToBitmap(imageUri!!)!!
image.setImageBitmap(bitmap)
val intent = Intent(this, MainActivity::class.java)
//intent.data = imageUri;
intent.putExtra("bitmap", bitmap)
startActivity(intent)
}
}
private fun chooseImageGallery() {
val intent = Intent(Intent.ACTION_PICK)
intent.type = "image/*"
getResultCamera.launch(intent)
}
Right now, I am receiving null for the bitmap.
Also, when I select the image from the gallery , the screen goes to MainActivity, so the user can't see the activity_selected_image
layout (hence , the image)
CodePudding user response:
First of all, if you want to pass something back to the first activity, the second activity should be using setResult()
and then finish()
so it sends the object back to the existing MainActivity. The way you're doing it is creating a second copy of MainActivity on the stack.
Secondly, startActivity()
calls are asynchronous. In your MainActivity's click listener, when you call startActivity()
, it queues the second activity to start on the main thread, but it will finish the code that's already running on the main thread first, i.e., the rest of your click listener code. So your val bitmap
line is evaluated before the second activity even appears. Anyway, you can't even guarantee that the MainActivity instance that will be around after the SecondActivity is done will even be the same instance you started with. The OS freely destroys and regenerates Activity instances under several types of conditions, one of the big ones being screen rotations.
The MainActivity should use registerActivityForResult()
to start the second activity and respond to the result in the register contract.
class MainActivity: AppCompatActivity() {
private val getImageResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val bitmap = result.data?.getParcelableExtra<Bitmap>("bitmap")
if (bitmap != null) {
//...
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// ...
srButton = findViewById(R.id.super_resolution)
srButton.setOnClickListener {
val intent = Intent(this, SecondActivity::class.java)
getImageResult.launch(intent)
}
}
}
// In second activity:
// Receiver for camera
private val getResultCamera =
registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
if (it.resultCode == Activity.RESULT_OK) {
imageUri = it.data?.data as Uri
bitmap = uriToBitmap(imageUri!!)!!
val result = Intent()
intent.putExtra("bitmap", bitmap)
setResult(Activity.RESULT_OK, intent)
finish()
}
}
I took out the part about setting the bitmap to an ImageView in the second activity, because the second activity will be destroyed before it can be seen.
CodePudding user response:
Activity 2:
try {
//Write file
String filename = "bitmap.png";
FileOutputStream stream = this.openFileOutput(filename, Context.MODE_PRIVATE);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
//Cleanup
stream.close();
bmp.recycle();
//Pop intent
Intent in1 = new Intent();
in1.putExtra("image", filename);
setResult(CODE,in1);
startActivity(in1);
} catch (Exception e) {
e.printStackTrace();
}
In Activity 1, load up the bitmap:
Bitmap bmp = null;
String filename = getIntent().getStringExtra("image");
try {
FileInputStream is = this.openFileInput(filename);
bmp = BitmapFactory.decodeStream(is);
is.close();
} catch (Exception e) {
e.printStackTrace();
}
UPDATE Activity 2
//Convert to byte array
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
Intent in1 = new Intent();
in1.putExtra("image",byteArray);
setResult(CODE,in1)
Then in Activity 1:
byte[] byteArray = getIntent().getByteArrayExtra("image");
Bitmap bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);