2

I am using both an ImagePicker and a barcode reader in a single activity. The main problem is that both of these require onActivityResult() to display the result. As we know a single activity can only have a single onActivityResult() method in it. How can I display both of them?

I have tried using switch cases to assign multiple requestCodes in the onActivityResult() but can't seem to figure out the solution.

Here's the method I tried.

public class MainActivity extends AppCompatActivity{

private TextView mIdentificationNumber;
private IntentIntegrator scanQR;

//Authentication For Firebase.
private FirebaseAuth mAuth;

//Toolbar
private Toolbar mToolBar;

private DatabaseReference mUserRef;

private ImageView mAssetImg;
private EditText massetName, massetModel, massetBarcode, massetArea, massetDescription;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //Getting the Present instance of the FireBase Authentication
    mAuth = FirebaseAuth.getInstance();

    //Finding The Toolbar with it's unique Id.
    mToolBar = (Toolbar) findViewById(R.id.main_page_toolbar);

    //Setting Up the ToolBar in The ActionBar.
    setSupportActionBar(mToolBar);

    if (mAuth.getCurrentUser() != null){

        mUserRef = FirebaseDatabase.getInstance().getReference().child("Users")
                .child(mAuth.getCurrentUser().getUid());
        mUserRef.keepSynced(true);

    }

    massetBarcode = (EditText) findViewById(R.id.BarcodeAsset);
    scanQR = new IntentIntegrator(this);
    massetBarcode.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            scanQR.initiateScan();

        }
    });

    mAssetImg = (ImageView) findViewById(R.id.asset_img);
    mAssetImg.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            getImage();
        }
    });

}

//OnStart Method is started when the Authentication Starts.
@Override
public void onStart() {
    super.onStart();
    // Check if user is signed in (non-null).
    FirebaseUser currentUser = mAuth.getCurrentUser();

    if (currentUser == null){

        startUser();

    } else {

        mUserRef.child("online").setValue("true");
        Log.d("STARTING THE ACTIVITY" , "TRUE");

    }
}

@Override
protected void onPause() {
    super.onPause();

    FirebaseUser currentUser = mAuth.getCurrentUser();

    if (currentUser != null){

        mUserRef.child("online").setValue(ServerValue.TIMESTAMP);
        Log.d("STOPPING THE ACTIVITY" , "TRUE");

    }

}

private void startUser() {

    //Sending the user in the StartActivity If the User Is Not Logged In.
    Intent startIntent = new Intent(MainActivity.this , AuthenticationActivity.class);
    startActivity(startIntent);
    //Finishing Up The Intent So the User Can't Go Back To MainActivity Without LoggingIn.
    finish();

}

//Setting The Menu Options In The AppBarLayout.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    //Inflating the Menu with the Unique R.menu.Id.
    getMenuInflater().inflate(R.menu.main_menu , menu);

    return true;
}

//Setting the Individual Item In The Menu.(Logout Button)
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    super.onOptionsItemSelected(item);

    if (item.getItemId() == R.id.main_logout_btn){

        FirebaseAuth.getInstance().signOut();
        startUser();

    }

    return true;
}

private void getImage() {

    ImagePicker.Companion.with(this)
            .crop()                 //Crop image(Optional), Check Customization for more option
            .compress(1024)         //Final image size will be less than 1 MB(Optional)
            .maxResultSize(1080, 1080)  //Final image resolution will be less than 1080 x 1080(Optional)
            .start();

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case 0:
            IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
            if (result != null) {
                if (result.getContents() == null) {
                    Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show();
                } else {

                    massetBarcode.setText(result.getContents());

                    Toast.makeText(this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
                }
            }
            break;

        case 1:
            if (resultCode == Activity.RESULT_OK) {

                assert data != null;
                Uri imageURI = data.getData();
                mAssetImg.setImageURI(imageURI);

            }
            break;
    }

}

}

The rest of the answers told to use startActivityForResult() but that method requires Intent to go from one activity to another but I don't want to do this.

Aditya Verma
  • 120
  • 2
  • 10
  • Can you post your fragment's code? – Mohamed Nageh Jan 19 '20 at 14:38
  • If you want to communicate between 2 activities startActivityForResult will solve your problems with different request codes. But if you want to communicate between fragment and activity you should use an interface. See https://stackoverflow.com/questions/14247954/communicating-between-a-fragment-and-an-activity-best-practices – Faruk Toptas Jan 19 '20 at 15:06
  • @mohnage7 hey I made a mistake in the question, it's not a fragment but an imagepicker that directly goes into the gallery to pick images and get's the result in the onActivityResult() method. – Aditya Verma Jan 19 '20 at 16:16

3 Answers3

2

In both cases, the libraries you're using provide a way to specify a request code so you can distinguish the results in onActivityResult.

Your scanQR object should set a request code, per the source code:

massetBarcode.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        scanQR.setRequestCode(123).initiateScan();
    }
});

You getImage() method should also specify a request code, again, per the library's source code.

private void getImage() {
    ImagePicker.Companion.with(this)
        .crop()                 //Crop image(Optional), Check Customization for more option
        .compress(1024)         //Final image size will be less than 1 MB(Optional)
        .maxResultSize(1080, 1080)  //Final image resolution will be less than 1080 x 1080(Optional)
        .start(456); // Start with request code
}

Now, you can handle each request code as needed:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case 123:
            // HANDLE BARCODE
            break;

        case 456:
            // HANDLE IMAGE
            break;
    }
}

Closing thought: I've never used either library. I found the solution by 1) assuming any library that provides an Activity you're supposed to invoke for a result would allow you to specify a request code for it and 2) looking through their documentation and source code for how to do that.

I'd encourage you to thoroughly study the documentation and source code for any open source library you intend to use since as soon as you do their code become your code and their bugs become your bugs, so you better know how to fix or workaround them.

Hope that helps!

dominicoder
  • 9,338
  • 1
  • 26
  • 32
  • hey, I made a mistake in the question, it's not a fragment but an imagepicker that directly goes into the gallery to pick images and get's the result in the onActivityResult() method. The barcode reader is a third party library. I corrected the question. – Aditya Verma Jan 19 '20 at 16:32
  • OK - in neither case are you specifying an code to use in onActivityResult. Show the code for the scanner and image picker, or point to the 3rd party libraries you're using. – dominicoder Jan 19 '20 at 16:59
  • ImagePicker - https://github.com/Dhaval2404/ImagePicker Barcode Scanner - https://github.com/journeyapps/zxing-android-embedded – Aditya Verma Jan 19 '20 at 17:06
0

In order to get results from fragments to your Activity, you can use an Interface to enable communication between them.

StartActivityForResult is used to start an activity and get a result back from it.

Please read more about it from here.

Mohamed Nageh
  • 1,963
  • 1
  • 19
  • 27
0

The startActivityForResult methos can use a second argument, a number so you can distinguish the resul

startActivityForResul(intent, 8)

You dont need to set the code back in the other activity, that is handled under the hood. So you probabbly want to add the number as a contant

private static final CAMERA_INTENT = 2

And then use it like this

startActivityForResul(intent, CAMERA_INTENT)

Finally in the onActivityResult implements the case basis

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {

if (CAMERA_INTENT == requestCode) {
    //DO PHOTO STUFF
}
}

The argument you need to eval is requestCode

cutiko
  • 9,887
  • 3
  • 45
  • 59
  • startActivityForResult() requires intent as a parameter and to instantiate an intent requires two activities. I don't want to go from one activity to another activity. – Aditya Verma Jan 19 '20 at 16:10
  • Is the same, change the explicit intent for an implicit intent `Intent intent = new Intent(Intent.CAMERA_ACTION); startActivityForResult(intent, 7);` – cutiko Jan 19 '20 at 16:36
  • Intent.CAMERA_ACTION shows an error – Aditya Verma Jan 19 '20 at 17:09
  • You cant expect SO makes all the work for you here is the documentation of common intents https://developer.android.com/guide/components/intents-common here for exlicit and implicit intent https://developer.android.com/guide/components/intents-filters and here you have all of the intentens https://developer.android.com/reference/android/content/Intent your questions is how to make 2 activity for result in 1 activity, this is the solution, other questions, other posts – cutiko Jan 20 '20 at 02:52