17

Following up on this question, is there a way to start an intent in android without prompting the user for anything?

Right now, I am retrieving the image like this:

public void changeImage(View view) {
    Intent intent = new Intent();
    intent.setType("image/*");
    intent.setAction(Intent.ACTION_GET_CONTENT);
    startActivityForResult(
        Intent.createChooser(intent, getResources().getString(R.string.select_picture)),
        PICK_IMAGE);
}

Then I store the Uri, and when necessary display the image (I actually resize it first, but that doesn't matter):

Uri _uri = Uri.parse(_path);
InputStream imageStream = null;
try {
    imageStream = getContentResolver().openInputStream(_uri);
} catch (FileNotFoundException e) {
    e.printStackTrace();
}
Bitmap b = BitmapFactory.decodeStream(imageStream);
iv.setImageBitmap(b);

I would like to retrieve the image data given its Uri by "silently" invoking the intent so as to get the relevant permission. So I would need something like:

Edit:

I tried the setPackage() method. This code has the following behavior:

  • If the ACTION_VIEW intent is used, the gallery opens and shows the specific image.

  • If the ACTION_GET_CONTENT intent is used, I get prompted to pick an image from the gallery, even though I supply the specific Uri.

>

Uri _uri = Uri.parse(_path);
InputStream imageStream = null;
Bitmap b = null;
try {
    imageStream = getContentResolver().openInputStream(_uri);
    b = BitmapFactory.decodeStream(imageStream);
    ImageView iv = (ImageView) findViewById(R.id.playerImage);
    iv.setImageBitmap(b);
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (SecurityException e) {
    e.printStackTrace();

    Intent dummyIntent = new Intent(Intent.ACTION_GET_CONTENT);
    //Intent dummyIntent = new Intent(Intent.ACTION_VIEW);
    dummyIntent.setDataAndType(_uri,"image/*");
    dummyIntent.setPackage("com.google.android.gallery3d");

    startActivityForResult(dummyIntent, PICK_IMAGE);
}

Any ideas?

Community
  • 1
  • 1
parakmiakos
  • 2,994
  • 9
  • 29
  • 43
  • 4
    if you `createChooser()` the dialog for choosing will appear. If you know the intent that will return an image from a package that serves images, you can raise the intent directly for that pacakge to serve setting it `Intent.setPackage`. So the chooser won´t appear and the package receiving the intent would handle it. – eduyayo Dec 16 '14 at 11:15
  • And can I use `setData()` to specify the Uri? – parakmiakos Dec 16 '14 at 11:23
  • previously in Facebook , when we open a video , many intent options were available to which software you want to open the video...now a days in facebook.. automatically when we click the video it displays the video without showing any videos... @parakmiakos do you want the same ? – Jamil Dec 16 '14 at 12:09
  • it depends on how the receiving package uses the Intent interface... If you´ve got kind-of a document on how to invoke directly, better follow that – eduyayo Dec 16 '14 at 12:10
  • @Softcoder I am not sure if this is the same. I do not want the application to remember which application it was that was used in the intent. I want to fire off an intent to retrieve data for the specific Uri, without the user knowing. I need this as a workaround for the bug in the question I have linked. I have to "refresh" the permission for the specific Uri supplied by Picasa. – parakmiakos Dec 16 '14 at 12:14
  • Your question can be understood only by reading the other question you did. I advice you to edit it to be understandable without having to read another question. I can easily answer your question but you'll not be satisfied with it (I'm gonna do below). What you really want to ask is "How do I get the permission on a Picasa Uri without forcing the user to pick an image again?" – Daniele Segato Apr 17 '15 at 10:02

3 Answers3

1

You have different types of Intents, the silent ones are the broadcast and service intents. And by silent I mean that there's nothing visible going on for the user by default (no activity is launched).

An intent will just ask the system: is there something capable of handling it? If there is, it will pass it to that something (or in case of multiple options will ask the user). And you have no control after that unless what's handling it is your code.

Your problem is actually with Picasa.

When the user pick an image from Picasa you get an Uri. You can use that Uri with the ContentResolver to get the image. What's actually happening when you do is that a ContentProvider from Picasa will process the Uri and return you the InputStream for the image.

From the other question I understood that you do not immediately get the image, instead you save the Uri in the database and later process it.

Since Picasa use a permission mechanism to provide you the image and since that permission is expired when you try to use the Uri you want to obtain the Uri (along with the permission) again from Picasa without asking the user again.

The problem is that Picasa is in control on that permission and so if Picasa do not provide you with an intent to obtain the permission by knowing the Uri there's nothing you can do.

This is not even a bug in my opinion: you have the permission to access the image when the user decide so, you do not automatically get the permission to access every image from Picasa. A service that "silently" provide you with the permission to access every Picasa image by knowing its Uri would just let you get any image from the user without him knowing. This is probably not what the Picasa developers wants.

The best suggestion I can give you is the same one that you got in the other question: when the user chose the image immediately obtain it and save locally, then use the local Uri to access the image.

Daniele Segato
  • 12,314
  • 6
  • 62
  • 88
  • Thanks for you answer. What I find weird is that, without prompting for user input, I can get Picasa to show me a specific image, using my stored Uri. This is what happens when I use `Intent.ACTION_VIEW`. I was hoping there was some way to take advantage of that. – parakmiakos Apr 17 '15 at 12:57
  • If I had to guess they use the Uri in their app to show the image. You just happened to stumble on that. – Daniele Segato Apr 17 '15 at 14:33
0

Instead of trying to send a "silent" intent, a possible solution could be to save the URI of the file using "Shared Preferences" -- you could save the user and URI as a key/value pair (for example).

When you want to open the file later, it could then be opened without sending an intent.

  • Hey Francisco. This is what I am actually doing. However, the URIs supplied by the Picasa app are one-time only, meaning that the second time I try to access the same URI, I get the security exception. – parakmiakos Dec 31 '14 at 09:50
  • Then, you could try to create a copy of the image the first time you read it. Then you can access from the copy of the image. – Francisco López Dec 31 '14 at 15:47
  • That was the proposed solution in the linked question and what I am doing as a work-around. I would hope however to find a way to make this work. – parakmiakos Dec 31 '14 at 15:52
0

You should be able to get the "real" uri (one that won't change) in the following way:

This is done for audio file, so use "MediaStore.Images.Media.EXTERNAL_CONTENT_URI" and change other details to match your case.

Pre kit-kat:

    String songName = "";
    Cursor cursor = getContext().getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[]{MediaStore.Audio.Media.TITLE}, MediaStore.MediaColumns.DATA + " =?", new String[]{uri.toString()}, null);

    if (cursor != null && cursor.moveToNext()) {
        songName = cursor.getString(0);
    }

    if (cursor != null) {
        cursor.close();
    }
    return songName;

After Kitkat, there is the change due to the document provider, this code should do the trick:

Cursor cursor = null;
    String songName = "";
    try {

        String[] column = new String[]{MediaStore.Audio.Media.TITLE};
        String wholeID = DocumentsContract.getDocumentId(uri);
        // Split at colon, use second item in the array
        String id = wholeID.split(":")[1];
        // where id is equal to
        String sel = MediaStore.Images.Media._ID + " =?";
        cursor = getContext().getContentResolver().
                query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, column, sel, new String[]{id}, null);

        if (cursor != null && cursor.moveToNext()) {
            songName = cursor.getString(0);
        }
    }
    catch (Exception e){
        Logger.log(e);
    }
    finally {
        if (cursor != null) {
            cursor.close();
        }
    }

    return songName;

Again, change the details to match your case and save the real uri taken from the cursor you get (probably get this field in your projections : MediaStore.Images.Media.DATA).

oferiko
  • 1,927
  • 2
  • 16
  • 17