5

ユーザーが選択したソーシャルメディアネットワークを使用して画像を共有できるようにするボタンをAndroidアプリに作成しようとしています。画像ファイルはアプリのアセットフォルダーに保存されます。

私の計画は、画像への外部アクセスを提供するカスタムContentProviderを実装してから、コンテンツプロバイダー内の画像のURIを指定するTYPE_SENDインテントを送信することです。

私はこれを実行し、Google +とGMailで機能しますが、他のサービスでは失敗します。最も難しい部分は、ContentProviderのquery()メソッドから返されるはずの情報を見つけることです。一部のアプリはプロジェクションを指定しますが(たとえば、Google +は_idと_dataを要求します)、一部のアプリはプロジェクションとしてnullを渡します。射影が指定されている場合でも、列にどのような実際のデータ(タイプ)が期待されているのかわかりません。これに関するドキュメントは見つかりません。

ContentProviderのopenAssetFileメソッドも実装しました。これは(Google+で2回!)呼び出されますが、必然的にqueryメソッドも呼び出されます。queryメソッドの結果のみがカウントされるようです。

私が間違っているアイデアはありますか?クエリメソッドから何を返す必要がありますか?

以下のコード:

// my intent

Intent i = new Intent(android.content.Intent.ACTION_SEND);
i.setType("image/jpeg");
Uri uri = Uri.parse("content://com.me.provider/ic_launcher.jpg");
i.putExtra(Intent.EXTRA_STREAM, uri);       
i.putExtra(android.content.Intent.EXTRA_TEXT, text);
startActivity(Intent.createChooser(i, "Share via"));

// my custom content provider

public class ImageProvider extends ContentProvider
{
private AssetManager _assetManager;

public static final Uri CONTENT_URI = Uri.parse("content://com.me.provider");

// not called
@Override
public int delete(Uri arg0, String arg1, String[] arg2) 
{
    return 0;
}

// not called
@Override
public String getType(Uri uri) 
{
    return "image/jpeg";
}

// not called
@Override
public Uri insert(Uri uri, ContentValues values) 
{
    return null;
}

@Override
public boolean onCreate() 
{
    _assetManager = getContext().getAssets();
    return true;
}

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 
{
    MatrixCursor c = new MatrixCursor(new String[] { "_id", "_data" });

    try
    {
                    // just a guess!! works for g+ :/
        c.addRow(new Object[] { "ic_launcher.jpg",  _assetManager.openFd("ic_launcher.jpg") });
    } catch (IOException e)
    {
        e.printStackTrace();
        return null;
    }

    return c;
}

// not called
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 
{
    return 0;
}

// not called  
@Override
public String[] getStreamTypes(Uri uri, String mimeTypeFilter)
{

    return new String[] { "image/jpeg" };
}

// called by most apps
@Override
public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException 
{

    try 
    {
        AssetFileDescriptor afd = _assetManager.openFd("ic_launcher.jpg");
        return afd;
    } catch (IOException e) 
    {
        throw new FileNotFoundException("No asset found: " + uri);
    }
}

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

    return super.openFile(uri, mode);
}

}

4

1 に答える 1

1

ありがとう、あなたの質問は私のものを解決しました;)私はあなたの問題とまったく逆の問題を抱えていました.g +を除くすべてのサービスが機能します. クエリ メソッドで null を返していたため、g+ がクラッシュしました。

私の画像を実際に公開する唯一のことは、実装することでしたopenFile()。私の画像はアセットではなくファイルシステムに保存されていますが、あなたはParcelFileDescriptorあなたから を取得してAssetFileDescriptor返すことができると思います。私のopenFile()方法は次のようになります。

@Override
public ParcelFileDescriptor openFile(Uri uri, String mode)
        throws FileNotFoundException {
    String path = uri.getLastPathSegment();
    if (path == null) {
        throw new IllegalArgumentException("Not a Path");
    }
    File f = new File(getContext().getFilesDir() + File.separator + "solved" + path + ".jpg");
    int iMode;
    if ("r".equals(mode)) {
        iMode = ParcelFileDescriptor.MODE_READ_ONLY;
    } else if ("rw".equals(mode)) {
        iMode = ParcelFileDescriptor.MODE_READ_WRITE;
    } else if ("rwt".equals(mode)) {
        iMode = ParcelFileDescriptor.MODE_READ_WRITE | ParcelFileDescriptor.MODE_TRUNCATE;
    } else {
        throw new IllegalArgumentException("Invalid mode");
    }       
    return ParcelFileDescriptor.open(f, iMode); 
}

ACTION_SENDこれは、 g + を除くインテントでインストールしたすべてのサービスで機能します。クエリ メソッドを使用すると、Google プラスでも機能します。

于 2012-09-10T23:13:26.770 に答える