android从资源文件夹共享图像

Bud*_*ril 19 android share assets image

我正在尝试从我的资源文件夹中共享图像.我的代码是:

Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/jpg");
share.putExtra(Intent.EXTRA_STREAM, Uri.parse("file:///assets/myImage.jpg"));
startActivity(Intent.createChooser(share, "Share This Image"));
Run Code Online (Sandbox Code Playgroud)

但它不起作用.你有什么想法?

smi*_*324 15

可以通过自定义从资源文件夹共享文件(包括图像) ContentProvider

您需要扩展ContentProvider,在清单中注册并实现该openAssetFile方法.然后,您可以通过Uris 评估资产

    @Override
    public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
        AssetManager am = getContext().getAssets();
        String file_name = uri.getLastPathSegment();

        if(file_name == null) 
            throw new FileNotFoundException();
        AssetFileDescriptor afd = null;
        try {
            afd = am.openFd(file_name);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return afd;
    }
Run Code Online (Sandbox Code Playgroud)


int*_*dis 11

这个博客解释了这一切:
http ://nowherenearithaca.blogspot.co.uk/2012/03/too-easy-using-contentprovider-to-send.html

基本上,这就在清单中:

<provider android:name="yourclass.that.extendsContentProvider"                android:authorities="com.yourdomain.whatever"/>
Run Code Online (Sandbox Code Playgroud)

内容提供程序类具有以下内容:

@Override
public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
    AssetManager am = getContext().getAssets();
    String file_name = uri.getLastPathSegment();
    if(file_name == null) 
        throw new FileNotFoundException();
    AssetFileDescriptor afd = null;
    try {
        afd = am.openFd(file_name);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return afd;//super.openAssetFile(uri, mode);
}
Run Code Online (Sandbox Code Playgroud)

调用代码执行此操作:

Uri theUri = Uri.parse("content://com.yourdomain.whatever/someFileInAssetsFolder");
Intent theIntent = new Intent(Intent.ACTION_SEND);
theIntent.setType("image/*");
theIntent.putExtra(Intent.EXTRA_STREAM,theUri);
theIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,"Subject for message");                        
theIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Body for message");
startActivity(theIntent);
Run Code Online (Sandbox Code Playgroud)


Kik*_*uto 11

补充@intrepidis回答的内容:

您将需要覆盖方法,例如上面的示例类:

package com.android.example;

import android.content.ContentProvider;
import android.net.Uri;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import java.io.FileNotFoundException;
import android.content.ContentValues;
import android.database.Cursor;
import java.io.IOException;
import android.os.CancellationSignal;

public class AssetsProvider extends ContentProvider
{

        @Override
        public AssetFileDescriptor openAssetFile( Uri uri, String mode ) throws FileNotFoundException
        {
                Log.v( TAG, "AssetsGetter: Open asset file" );
                AssetManager am = getContext( ).getAssets( );
                String file_name = uri.getLastPathSegment( );
                if( file_name == null )
                        throw new FileNotFoundException( );
                AssetFileDescriptor afd = null;
                try
                {
                        afd = am.openFd( file_name );
                }
                catch(IOException e)
                {
                        e.printStackTrace( );
                }
                return afd;//super.openAssetFile(uri, mode);
        }

        @Override
        public String getType( Uri p1 )
        {
                // TODO: Implement this method
                return null;
        }

        @Override
        public int delete( Uri p1, String p2, String[] p3 )
        {
                // TODO: Implement this method
                return 0;
        }

        @Override
        public Cursor query( Uri p1, String[] p2, String p3, String[] p4, String p5 )
        {
                // TODO: Implement this method
                return null;
        }

        @Override
        public Cursor query( Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal )
        {
                // TODO: Implement this method
                return super.query( uri, projection, selection, selectionArgs, sortOrder, cancellationSignal );
        }

        @Override
        public Uri insert( Uri p1, ContentValues p2 )
        {
                // TODO: Implement this method
                return null;
        }

        @Override
        public boolean onCreate( )
        {
                // TODO: Implement this method
                return false;
        }

        @Override
        public int update( Uri p1, ContentValues p2, String p3, String[] p4 )
        {
                // TODO: Implement this method
                return 0;
        }
}
Run Code Online (Sandbox Code Playgroud)

我需要重写两次查询方法.并在androidmanifest.xml中的标记上方添加以下行:

<provider
  android:name="com.android.example.AssetsProvider"
  android:authorities="com.android.example"
  android:grantUriPermissions="true"
  android:exported="true" />
Run Code Online (Sandbox Code Playgroud)

有了这个,所有的工作就像一个魅力:D

  • 对不起,我迟到了.你如何将文件发送到intent?我认为代码没问题.你需要像这样的地址调用图像:file:///android_asset/folder/image1.png如果你需要共享它,你需要使用这个代码:String file ="folder/image1.png"; Uri theUri = Uri.parse("content://com.example.yourproject/"+ file); Intent theIntent = new Intent(Intent.ACTION_SEND); theIntent.setType("image/*"); theIntent.putExtra(Intent.EXTRA_STREAM,theUri); startActivity(Intent.createChooser(theIntent,"Send to:"); (2认同)
  • @Kikuto实际上,如果你的资产中有子文件夹,那么你应该将AssetsProvider openAssetFile方法file_name更改为String file_name = uri.getPath().substring(1,uri.getPath().length()); (2认同)

Ben*_*ger 5

由于这里的其他答案都不适合我(2019 年),我通过将资产复制到应用程序的内部文件目录然后共享此文件来解决问题。就我而言,我需要共享资产文件夹中的 pdf 文件。

在 AndroidManifest.xml 中添加一个文件提供程序(无需使用自定义提供程序):

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/filepaths" />
</provider>
Run Code Online (Sandbox Code Playgroud)

在 res/xml/ 中创建 filepaths.xml 文件

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <files-path
        name="root"
        path="/" />
</paths>
Run Code Online (Sandbox Code Playgroud)

当然,如果您管理应用程序目录中的其他文件,则应该在此处使用子目录。

现在在您想要触发共享意图的类中。

1.在files目录下创建一个空文件

private fun createFileInFilesDir(filename: String): File {
    val file = File(filesDir.path + "/" + filename)
    if (file.exists()) {
        if (!file.delete()) {
            throw IOException()
        }
    }
    if (!file.createNewFile()) {
        throw IOException()
    }
    return file
}
Run Code Online (Sandbox Code Playgroud)

2.将asset的内容复制到文件中

private fun copyAssetToFile(assetName: String, file: File) {
    val buffer = ByteArray(1024)
    val inputStream = assets.open(assetName)
    val outputStream: OutputStream = FileOutputStream(file)
    while (inputStream.read(buffer) > 0) {
        outputStream.write(buffer)
    }
}
Run Code Online (Sandbox Code Playgroud)

3. 为文件创建共享意图

private fun createIntentForFile(file: File, intentAction: String): Intent {
    val uri = FileProvider.getUriForFile(this, applicationContext.packageName + ".provider", file)
    val intent = Intent(intentAction)
    intent.flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
    intent.setDataAndType(uri, "application/pdf")
    return intent
}
Run Code Online (Sandbox Code Playgroud)

4. 执行1-3并触发intent

private fun sharePdfAsset(assetName: String, intentAction: String) {
    try {
        val file = createFileInFilesDir(assetName)
        copyAssetToFile(assetName, file)
        val intent = createIntentForFile(file, intentAction)
        startActivity(Intent.createChooser(intent, null))
    } catch (e: IOException) {
        e.printStackTrace()
        AlertDialog.Builder(this)
            .setTitle(R.string.error)
            .setMessage(R.string.share_error)
            .show()
    }
}
Run Code Online (Sandbox Code Playgroud)

5. 调用函数

sharePdfAsset("your_pdf_asset.pdf", Intent.ACTION_SEND)
Run Code Online (Sandbox Code Playgroud)

如果您想在共享后删除该文件,您可能可以startActivityForResult()在共享后使用并删除它。通过更改,intentAction您还可以通过使用此过程来执行“打开方式...”操作Intent.ACTION_VIEW。对于assets, filesDir, ... 您需要参加Activity或拥有一个Context课程。