How can one capture camera/gallery return result in android native code?

I have an application built using Corona Enterprise and I want to allow users to open the device camera and/or browse the device gallery and select/capture an image using native code. Then I want the software to process the image in android native code. I know about opening the camera within Corona (lua) and such but that will not work for the app due to the proceeing required for the selected image, hense the native android code part.

I have created the corona part and the native part separately (both work correctly) and my intent is to join the two parts using the Enterprise version but I am stuck trying to access the onActivityResult method that is called after the intents are launched and finished (android startActivityForResult method is used).

I can open the camera fine and browse the gallery fine but after image selection I can’t figure out how to intercept the onActivityResult return data because I think it is calling the method located in com.ansca.corona.CoronaActivity and I don’ have access to that.

Also, I am using a native view that is displayed on top of corona based on the extending UI sample.

Relevant Code: (located in a view that is ceated in CoronaApplication.java, just like the extending UI sample)

Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
((android.app.Activity)getContext()).startActivityForResult(intent, Config.camera_result_value_success);

public void onActivityResult(int requestCode, int resultCode, android.content.Intent data){
    // this is never reached because the method located in com.ansca.corona.CoronaActivity is whats called.
}

Is what I am trying possible?

You’ll need to use our CoronaActivity.registerActivityResultHandler() method as documented here…
   http://docs.coronalabs.com/daily/native/android/html/com/ansca/corona/CoronaActivity.html
   http://docs.coronalabs.com/daily/native/android/html/com/ansca/corona/CoronaActivity.OnActivityResultHandler.html
 
You can set up an activity result handler like this…

public void showYourActivity() { // Fetch the active Corona activity. CoronaActivity activity = CoronaEnvironment.getCoronaActivity(); if (activity == null) { return; } // Register your activity handler. int requestCode = activity.registerActivityResultHandler(new MyHandler()); // Launch your intent with the above request code. Intent intent = new Intent(MediaStore.ACTION\_IMAGE\_CAPTURE); // intent.putExtra(android.provider.MediaStore.EXTRA\_OUTPUT, yourUri); activity.startActivityForResult(intent, requestCode); } private static class MyHandler implements CoronaActivity.OnActivityResultHandler { public MyHandler() {} @Override public void onHandleActivityResult( CoronaActivity activity, int requestCode, int resultCode, android.content.Intent data) { // Unregister this handler. activity.unregisterActivityResultHandler(this); // Handle the result... } }

 
 
I hope this helps!

Thank you. Is it the same for iphone?

What I posted above will only work for Android.

I’m not the iOS expert here, but my understanding is that you have to use an “IPhonePickerControllerDelegate” whose source type is set to “UIImagePickerControllerSourceTypeCamera”.  You’ll have to figure it out from there.

Oh and on iOS, you can access the application’s UIWindow and UIViewController as documented here…

   http://docs.coronalabs.com/daily/native/ios/CoronaRuntime.html

You can find an example on how to display a view on iOS in Corona Enterprise in file…

   ./CoronaEnterprise/ProjectTemplates/ads-provider/ios/Plugin/IOSMyAdsProvider.mm

I hope this helps!

Thank you sir. Very big help.

You’ll need to use our CoronaActivity.registerActivityResultHandler() method as documented here…
   http://docs.coronalabs.com/daily/native/android/html/com/ansca/corona/CoronaActivity.html
   http://docs.coronalabs.com/daily/native/android/html/com/ansca/corona/CoronaActivity.OnActivityResultHandler.html
 
You can set up an activity result handler like this…

public void showYourActivity() { // Fetch the active Corona activity. CoronaActivity activity = CoronaEnvironment.getCoronaActivity(); if (activity == null) { return; } // Register your activity handler. int requestCode = activity.registerActivityResultHandler(new MyHandler()); // Launch your intent with the above request code. Intent intent = new Intent(MediaStore.ACTION\_IMAGE\_CAPTURE); // intent.putExtra(android.provider.MediaStore.EXTRA\_OUTPUT, yourUri); activity.startActivityForResult(intent, requestCode); } private static class MyHandler implements CoronaActivity.OnActivityResultHandler { public MyHandler() {} @Override public void onHandleActivityResult( CoronaActivity activity, int requestCode, int resultCode, android.content.Intent data) { // Unregister this handler. activity.unregisterActivityResultHandler(this); // Handle the result... } }

 
 
I hope this helps!

Thank you. Is it the same for iphone?

What I posted above will only work for Android.

I’m not the iOS expert here, but my understanding is that you have to use an “IPhonePickerControllerDelegate” whose source type is set to “UIImagePickerControllerSourceTypeCamera”.  You’ll have to figure it out from there.

Oh and on iOS, you can access the application’s UIWindow and UIViewController as documented here…

   http://docs.coronalabs.com/daily/native/ios/CoronaRuntime.html

You can find an example on how to display a view on iOS in Corona Enterprise in file…

   ./CoronaEnterprise/ProjectTemplates/ads-provider/ios/Plugin/IOSMyAdsProvider.mm

I hope this helps!

Thank you sir. Very big help.

HI Joshua,

I tried to call IMAGE_CAPTURE Activity with the above code like this

    public void takePhoto(String path) {

          // Fetch the active Corona activity.

           CoronaActivity activity = CoronaEnvironment.getCoronaActivity();

           if (activity == null) {

              return;

           }

           File tmpFile = getTempFile(activity);

           int requestCode = activity.registerActivityResultHandler(new MyHandler());

           // Launch your intent with the above request code.

           Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

           intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(tmpFile));

           activity.startActivityForResult(intent, requestCode);        

    }

    

    private static class MyHandler implements CoronaActivity.OnActivityResultHandler {

  

            public MyHandler() {}

            @Override

            public void onHandleActivityResult(CoronaActivity activity, int requestCode, 

                    int resultCode, android.content.Intent data) {

                // TODO Auto-generated method stub

                System.out.println("onHandleActivityResult   "+resultCode);

                activity.unregisterActivityResultHandler(this);

                if(resultCode == Activity.RESULT_OK) {

  

                }

        }

But what happens is only once in a while the code enters into onHandleActivityResult, rest of the time it just closes the native side and goes back to lua.

Could you please send me a solution to the above problem asap. 

NB:- There are no exceptions

Are you calling your takePhoto() method on the main UI thread?

I ask because your NamedJavaFunction derived class is not called on the main UI thread.  Calling methods on an activity outside of the main UI thread will definitely cause problems.

Is “Don’t keep activities” check on under the device’s Settings/DeveloperOptions screen?

If so, then that’ll prevent your onHandleActivityResult() from ever being called because your activity will be destroyed when launching the image capture activity.  There is no work-around for this issue if that’s the case you’re running into.

Try building sample app “Media/PhotoPicker” via the Corona Simulator and running it on your device.  Does that sample app correctly display the photo you’ve selected?

Also, have a look at the Android log via “adb logcat”.  Check for anything unusual such as your application being shutdown or activity being destroyed.  This can happen in low memory situations.

That said, I can’t think of any other advise to offer you.  We know that the registerActivityResultHandler() method and its onHandleActivityResult listener works because we use it internally for all popups such as mail, camera, photo gallery, facebook, etc.

HI Joshua,

I tried to call IMAGE_CAPTURE Activity with the above code like this

    public void takePhoto(String path) {

          // Fetch the active Corona activity.

           CoronaActivity activity = CoronaEnvironment.getCoronaActivity();

           if (activity == null) {

              return;

           }

           File tmpFile = getTempFile(activity);

           int requestCode = activity.registerActivityResultHandler(new MyHandler());

           // Launch your intent with the above request code.

           Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

           intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(tmpFile));

           activity.startActivityForResult(intent, requestCode);        

    }

    

    private static class MyHandler implements CoronaActivity.OnActivityResultHandler {

  

            public MyHandler() {}

            @Override

            public void onHandleActivityResult(CoronaActivity activity, int requestCode, 

                    int resultCode, android.content.Intent data) {

                // TODO Auto-generated method stub

                System.out.println("onHandleActivityResult   "+resultCode);

                activity.unregisterActivityResultHandler(this);

                if(resultCode == Activity.RESULT_OK) {

  

                }

        }

But what happens is only once in a while the code enters into onHandleActivityResult, rest of the time it just closes the native side and goes back to lua.

Could you please send me a solution to the above problem asap. 

NB:- There are no exceptions

Are you calling your takePhoto() method on the main UI thread?

I ask because your NamedJavaFunction derived class is not called on the main UI thread.  Calling methods on an activity outside of the main UI thread will definitely cause problems.

Is “Don’t keep activities” check on under the device’s Settings/DeveloperOptions screen?

If so, then that’ll prevent your onHandleActivityResult() from ever being called because your activity will be destroyed when launching the image capture activity.  There is no work-around for this issue if that’s the case you’re running into.

Try building sample app “Media/PhotoPicker” via the Corona Simulator and running it on your device.  Does that sample app correctly display the photo you’ve selected?

Also, have a look at the Android log via “adb logcat”.  Check for anything unusual such as your application being shutdown or activity being destroyed.  This can happen in low memory situations.

That said, I can’t think of any other advise to offer you.  We know that the registerActivityResultHandler() method and its onHandleActivityResult listener works because we use it internally for all popups such as mail, camera, photo gallery, facebook, etc.