Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning an Image to whatsapp

I've been trying to build an app that shows up as an optional image source when a user tries to share an image using whatsapp. So far I have managed to get my app to show up in the service picker that whatsapp launches using intent filters but I cannot get the image to return correctly to whatsapp. Im posting my code below :

public void returnImage(View v){
    //Bitmap img;
    //Bundle selectedImage = new Bundle();
    Uri imageURI;
    Intent shareIntent = new Intent();
    switch(v.getId()){
    case R.id.eric1 :
        imageURI =  saveToCache(R.drawable.cartman1);
        shareIntent.putExtra(Intent.EXTRA_STREAM, imageURI);
        shareIntent.setType("image/png");
        setResult(RESULT_OK, shareIntent);
        Utils.makeToast("Selected",this);
        System.out.println("--------------------------------");
        System.out.println(imageURI.toString());
        finish();
    }
}

   private Uri saveToCache(int resID) {
    // TODO Auto-generated method stub
    Bitmap image = BitmapFactory.decodeResource(getResources(), resID);
    File imageFile;
    Date d = new Date();
    String imgName = ((Long.toString(d.getTime())).subSequence(1,
            9)).toString();
    String state = Environment.getExternalStorageState();
    printDebug(state);
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        File file = getExternalFilesDir(null);
        if (file != null) {
            try {
                //String root = file.getAbsolutePath();
                imageFile = new File(file, imgName+".png");
                printDebug(imageFile.getAbsolutePath());
                FileOutputStream stream = new FileOutputStream(imageFile);
                boolean complete = image.compress(Bitmap.CompressFormat.PNG, 100, 
                    stream);
                if (!complete) {
                    Log.d("tag", "image not saved");
                }
                Log.d("tag", "image saved");
                // Tell the media scanner about the new file so that it is
                // immediately available to the user.
                MediaScannerConnection.scanFile(this,
                        new String[] { imageFile.toString() }, null,
                        new MediaScannerConnection.OnScanCompletedListener() {
                    public void onScanCompleted(String path, Uri uri) {
                        Log.i("ExternalStorage", "Scanned " + path + ":");
                        Log.i("ExternalStorage", "-> uri=" + uri);
                    }
                });

                return Uri.parse(imageFile.getAbsolutePath());
            } catch (IOException e) {
                Log.d("tag", "Can't save image", e);
            }
        }
    }
    return null;
    }

The app opens and i select the image but whatsapp reports that the image cannot be shared. LogCat shows no errors or warnings.

I read the resource Intent-Filter for Whatsapp -> share image

but there is no mention of how or what was returned by the app so I'm at a complete loss here.

like image 294
hanut Avatar asked Dec 21 '22 07:12

hanut


1 Answers

After searching for days, here is a working solution to return images to all other applications (tested for GMail and WhatsApp).

First, you need to set an intent-filter in your AndroidManifest.xml (Inside application > activity). This will list your application when other apps are calling for this intent (like when requesting an image). Note: WhatsApp is using the action.PICK - intent. Adding all intent-filters below even though will provide great compatibility with other apps.

<intent-filter>
                <action android:name="android.intent.action.PICK" /> 
                <category android:name="android.intent.category.DEFAULT"  /> 
                <category android:name="android.intent.category.OPENABLE" />
                <data android:mimeType="image/*" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.OPENABLE" />
                <data android:mimeType="image/*" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.GET_CONTENT" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.OPENABLE" />
                <data android:mimeType="image/*" />
            </intent-filter>

The second thing you need to care for is responding to an idling intent. This should consist of two parts: First you should check whether your application has been executed to return an image or if its run all by itself.

Intent intent = getIntent();
        if (intent!=null && intent.getType()!=null)  //check if any application has executed your app
        {
             if(intent.getType().indexOf("image/") != -1) isinint=true; //check if the requested type is an image. If true, set a public static boolean, f.e. named isinint to true. Default is false.
        }

Now, when the user has picked an image, set the result as following. Due to memory issues, you should copy the file you want to return onto the sdcard and return the Uri.

if(isinint) //check if any app cares for the result
        {
            Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND, Uri.fromFile(openprev)); //Create a new intent. First parameter means that you want to send the file. The second parameter is the URI pointing to a file on the sd card. (openprev has the datatype File)

            ((Activity) context).setResult(Activity.RESULT_OK, shareIntent); //set the file/intent as result
            ((Activity) context).finish(); //close your application and get back to the requesting application like GMail and WhatsApp
            return; //do not execute code below, not important
        }

Note!: You can leave out ((Activity) context) when calling the data in OnCreate or similiar void's. As i use this snippet in another void, i need to provide a context in any case that has to be defined as displayed.

like image 117
James Cameron Avatar answered Dec 29 '22 11:12

James Cameron