简体   繁体   English

在 Android 应用中与内容提供者共享图像

[英]Share an image with a content provider in Android app

I'm developing an Android app that is a gallery of images in which the images are downloaded from internet for display on the screen of smathphone.我正在开发一个 Android 应用程序,它是一个图像库,其中的图像是从互联网下载的,以显示在 smathphone 的屏幕上。 Images are displayed one at a time and the application has a button to share the image that is displayed.图像一次显示一个,应用程序有一个按钮来共享显示的图像。

Following the directions I've found in some StackOverflow post which indicated that the right way to share an image was using a ContentProvider I have implemented the following code that works to share the images of certain applications (eg Twitter, Gmail ...) but does not work for others (Facebook, Yahoo, MMS ...).按照我在一些 StackOverflow 帖子中找到的指示,表明共享图像的正确方法是使用 ContentProvider 我已经实现了以下代码,用于共享某些应用程序(例如 Twitter、Gmail ......)的图像,但是不适用于其他人(Facebook、Yahoo、MMS ...)。

Then I show the code used hoping you can help me get the correct implementation to share images in all applications.然后我展示了使用的代码,希望你能帮助我获得正确的实现,以便在所有应用程序中共享图像。

Initially I capture the button press to share:最初我捕获按钮按下以共享:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

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

        // I get the image being displayed on the screen
        View root = getView();
        ImageView imageView = (ImageView) root.findViewById(R.id.image);
        Drawable imageToShareDrawable = imageView.getDrawable();

        if (imageToShareDrawable instanceof BitmapDrawable) {

            // I convert the image to Bitmap
            Bitmap imageToShare = ((BitmapDrawable) imageToShareDrawable).getBitmap();

            // Name of de image extracted from a bean property
            String fileName = quote.getImage(); 

            // I keep the image in the folder "files" of internal storage application
            TempInternalStorage.createCachedFile(fileName, imageToShare, getActivity().getApplicationContext());

            // I start the Activity to select the application to share the image after the intent Built with the method "getDefaultShareIntent"
            startActivity(getDefaultShareIntent(fileName));
        } else {
            Toast.makeText(getActivity().getApplicationContext(), "Please wait, the quote is being downloaded", Toast.LENGTH_SHORT).show();
        }
    } 

    return true;
}

The method for saving the image to the internal storage of the application is as follows:将图像保存到应用程序内部存储的方法如下:

public static void createCachedFile(String fileName, Bitmap image, Context context) {

    try {
        File file = new File(context.getFilesDir(), fileName);

        if (!file.exists()) {
            FileOutputStream fos = new FileOutputStream(file);
            image.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            fos.flush();
            fos.close();
        } 
    } catch (Exception e) {
        Log.e("saveTempFile()", "**** Error");
    }
}

The method that constructs the Intent to share it:构造 Intent 以共享它的方法:

private Intent getDefaultShareIntent(String fileName) {
    final Intent shareIntent = new Intent();
    shareIntent.setAction(Intent.ACTION_SEND);
    shareIntent.setType("image/jpeg");
    shareIntent.putExtra(Intent.EXTRA_TEXT, "Test text");
    shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + CachedFileProvider.AUTHORITY + File.separator + "img" + File.separator + fileName));
    shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

    return shareIntent;
}

Finally ContentProvider code is as follows:最后ContentProvider代码如下:

public class CachedFileProvider extends ContentProvider {

private static final String CLASS_NAME = "CachedFileProvider";

public static final String AUTHORITY = "com.example.appname.cachefileprovider";

private UriMatcher uriMatcher;

@Override
public boolean onCreate() {
    uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    uriMatcher.addURI(AUTHORITY, "img/*", 1);

    return true;
}

@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {

    String LOG_TAG = CLASS_NAME + " - openFile";

    Log.i(LOG_TAG, "Called with uri: '" + uri + "'." + uri.getLastPathSegment());

    switch (uriMatcher.match(uri)) {

    case 1:

        String fileLocation = getContext().getFilesDir() + File.separator + uri.getLastPathSegment();

        ParcelFileDescriptor image = ParcelFileDescriptor.open(new File(fileLocation), ParcelFileDescriptor.MODE_READ_ONLY);

        return image;

    default:
        Log.i(LOG_TAG, "Unsupported uri: '" + uri + "'.");
        throw new FileNotFoundException("Unsupported uri: " + uri.toString());
    }
}

@Override
public int update(Uri uri, ContentValues contentvalues, String s, String[] as) {
    return 0;
}

@Override
public int delete(Uri uri, String s, String[] as) {
    return 0;
}

@Override
public Uri insert(Uri uri, ContentValues contentvalues) {
    return null;
}

@Override
public String getType(Uri uri) {
    return null;
}

@Override
public Cursor query(Uri uri, String[] projection, String s, String[] as1, String s1) {

    MatrixCursor c = null;

    Log.i(">>>> projection", java.util.Arrays.toString(projection));

    String fileLocation = getContext().getFilesDir() + File.separator + uri.getLastPathSegment();

    File file = new File(fileLocation);

    long time = System.currentTimeMillis();

    c = new MatrixCursor(new String[] { "_id", "_data", "orientation", "mime_type", "datetaken", "_display_name" });

    c.addRow(new Object[] { 0,  file, 0, "image/jpeg", time, uri.getLastPathSegment() });

    return c;
}

@Override
public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
    return null;
}

} }

I have found that when the image is sharing some applications only call the method "query" (these are where the code does not work and I can not share the image) while there are others that also call the method "query" also call the method "openFile" and these do work and I can share the image.我发现当图像共享时,某些应用程序只调用方法“查询”(这些是代码不起作用的地方,我无法共享图像),而其他应用程序也调用方法“查询”也调用方法“openFile”,这些确实有效,我可以分享图像。

I hope you can help me, thank you very much in advance.我希望你能帮助我,非常感谢你提前。

As @Sun Ning-s comment noted some "share target apps" can handle URI-s starting with "content://.." which you have implemented.正如@Sun Ning-s 评论所指出的,一些“共享目标应用程序”可以处理以“content://..”开头的 URI-s,您已经实现了。

Other apps handle file uri-s starting with "file://...." so you have to implement a 2nd share menue "share as file"其他应用程序处理以“file://....”开头的文件 uri-s,因此您必须实现第二个共享菜单“共享为文件”

private Intent getFileShareIntent(String fullPathTofile) {
    final Intent shareIntent = new Intent();
    shareIntent.setAction(Intent.ACTION_SEND);
    shareIntent.setType("image/jpeg");
    shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + fullPathTofile));
    shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

    return shareIntent;
}

You can use the android app intentintercept to find out what other "share source apps" provide.您可以使用android 应用程序意图拦截来找出其他“共享源应用程序”提供的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM