Совместное использование Bitmap с помощью Android Intent

В моем приложении для Android у меня есть растровое изображение (скажем, b) и кнопка. Теперь, когда я нажимаю кнопку, я хочу поделиться растровым изображением. Я использую приведенный ниже код внутри моего onClick() для достижения этого: -

Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/png");
intent.putExtra(Intent.EXTRA_STREAM, b);
startActivity(Intent.createChooser(intent , "Share"));

Я ожидал список всех приложений, которые могут справиться с этим намерением, но я ничего не получаю. Список приложений отсутствует, и в студии Android нет ошибок. Мое приложение просто подвешивается на некоторое время, а затем завершает работу.

Я проверил битмап, и это нормально (это не пусто).

Где я ошибаюсь?

Ответ 1

Я нашел 2 варианта решения. Оба варианта включают сохранение растрового изображения в хранилище, но изображение не будет отображаться в галерее.

Первый вариант:

Сохранение на внешнее хранилище

  • но в личную папку приложения.
  • для API & lt; = 18 требуется разрешение, для более нового - нет.

1. Установка разрешений

Добавьте в AndroidManifest.xml перед тегом

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18"/>

2. Метод сохранения:

 /**
 * Saves the image as PNG to the app private external storage folder.
 * @param image Bitmap to save.
 * @return Uri of the saved file or null
 */
private Uri saveImageExternal(Bitmap image) {
    //TODO - Should be processed in another thread
    Uri uri = null;
    try {
        File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "to-share.png");
        FileOutputStream stream = new FileOutputStream(file);
        image.compress(Bitmap.CompressFormat.PNG, 90, stream);
        stream.close();
        uri = Uri.fromFile(file);
    } catch (IOException e) {
        Log.d(TAG, "IOException while trying to write file for sharing: " + e.getMessage());
    }
    return uri;
}

3. Проверка доступности хранилища

Внешнее хранилище может быть недоступно, поэтому перед его сохранением следует проверить его: https://developer.android.com/training/data-storage/files

/**
 * Checks if the external storage is writable.
 * @return true if storage is writable, false otherwise
 */
public boolean isExternalStorageWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
}

Второй вариант

Сохранение в cacheDir с помощью FileProvider. Это не требует каких-либо разрешений.

1. Настройте FileProvider в AndroidManifest.xml

<manifest>
    ...
    <application>
        ...
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.mydomain.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
                <meta-data
                    android:name="android.support.FILE_PROVIDER_PATHS"
                    android:resource="@xml/file_paths" />
        </provider>
        ...
    </application>
</manifest>

2. Добавьте путь к файлу res/xml/file_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <paths xmlns:android="http://schemas.android.com/apk/res/android">
         <cache-path name="shared_images" path="images/"/>
    </paths>
</resources>

3. Метод сохранения:

 /**
 * Saves the image as PNG to the app cache directory.
 * @param image Bitmap to save.
 * @return Uri of the saved file or null
 */
private Uri saveImage(Bitmap image) {
    //TODO - Should be processed in another thread
    File imagesFolder = new File(getCacheDir(), "images");
    Uri uri = null;
    try {
        imagesFolder.mkdirs();
        File file = new File(imagesFolder, "shared_image.png");

        FileOutputStream stream = new FileOutputStream(file);
        image.compress(Bitmap.CompressFormat.PNG, 90, stream);
        stream.flush();
        stream.close();
        uri = FileProvider.getUriForFile(this, "com.mydomain.fileprovider", file);

    } catch (IOException e) {
        Log.d(TAG, "IOException while trying to write file for sharing: " + e.getMessage());
    }
    return uri;
}

Подробнее о поставщике файлов - https://developer.android.com/reference/android/support/v4/content/FileProvider

Сжатие и сохранение могут занимать много времени, поэтому это должно быть сделано в другом потоке

Актуальный обмен

/**
 * Shares the PNG image from Uri.
 * @param uri Uri of image to share.
 */
private void shareImageUri(Uri uri){
    Intent intent = new Intent(android.content.Intent.ACTION_SEND);
    intent.putExtra(Intent.EXTRA_STREAM, uri);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.setType("image/png");
    startActivity(intent);
}

Ответ 2

Как заявляет CommonsWare, вам нужно получить URI в растровое изображение и передать его как дополнительный.

String bitmapPath = Images.Media.insertImage(getContentResolver(), bitmap,"title", null);
Uri bitmapUri = Uri.parse(bitmapPath);
...
intent.putExtra(Intent.EXTRA_STREAM, bitmapUri );

Ответ 3

** наконец-то я получил решение. **

Шаг 1: Поделиться блоком обработки намерений. Появится окно со списком приложений в телефоне

public void share_bitMap_to_Apps() {

    Intent i = new Intent(Intent.ACTION_SEND);

    i.setType("image/*");
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    /*compress(Bitmap.CompressFormat.PNG, 100, stream);
    byte[] bytes = stream.toByteArray();*/


    i.putExtra(Intent.EXTRA_STREAM, getImageUri(mContext, getBitmapFromView(relative_me_other)));
    try {
        startActivity(Intent.createChooser(i, "My Profile ..."));
    } catch (android.content.ActivityNotFoundException ex) {

        ex.printStackTrace();
    }


}

Шаг 2: Преобразование вашего представления в BItmap

public static Bitmap getBitmapFromView(View view) {
    //Define a bitmap with the same size as the view
    Bitmap returnedBitmap = Bitmap.createBitmap(view.getWidth(),      view.getHeight(), Bitmap.Config.ARGB_8888);
    //Bind a canvas to it
    Canvas canvas = new Canvas(returnedBitmap);
    //Get the view background
    Drawable bgDrawable = view.getBackground();
    if (bgDrawable != null)
        //has background drawable, then draw it on the canvas
        bgDrawable.draw(canvas);
    else
        //does not have background drawable, then draw white background on the canvas
        canvas.drawColor(Color.WHITE);
    // draw the view on the canvas
    view.draw(canvas);
    //return the bitmap
    return returnedBitmap;
}

Шаг 3:

Чтобы получить URI из растрового изображения

public Uri getImageUri(Context inContext, Bitmap inImage) {
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);

    String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
    return Uri.parse(path);
}

Ответ 4

Привет, кодеры. Попробуйте мой официальный блог

ImageButton capture_share = (ImageButton) findViewById(R.id.share);
capture_share.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View view) {

    String bitmapPath = MediaStore.Images.Media.insertImage(getContentResolver(), bitmap,"title", null);
    Uri bitmapUri = Uri.parse(bitmapPath);

        Intent intent = new Intent(Intent.ACTION_SEND);
        intent.setType("image/png");
        intent.putExtra(Intent.EXTRA_STREAM, bitmapUri);
        startActivity(Intent.createChooser(intent, "Share"));



  }
});

Ответ 5

Цитирование документации:

Содержание: URI, содержащий поток данных, связанных с Intent, используемый с ACTION_SEND для отправки отправляемых данных.

b, следовательно, не должен быть Bitmap, а скорее a Uri, указывающим на Bitmap, обслуживаемый ContentProvider. Например, вы можете записать Bitmap в файл, а затем использовать FileProvider для его обслуживания.

Ответ 6

Потратив много времени на это:

Проверьте, предоставлены ли разрешения. Затем:

Шаг 1: Создайте ImageView изображения, которое вы хотите в упражнении, а затем преобразуйте его в растровое изображение

ImageView imageView = findViewById(R.id.image);
Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();

//save the image now:
saveImage(bitmap);
//share it
send();

Шаг 2. Сохраните изображение во внутренней папке:

private static void saveImage(Bitmap finalBitmap) {

    String root = Environment.getExternalStorageDirectory().getAbsolutePath();
    File myDir = new File(root + "/saved_images");
    Log.i("Directory", "==" + myDir);
    myDir.mkdirs();

    String fname = "Image-test" + ".jpg";
    File file = new File(myDir, fname);
    if (file.exists()) file.delete();
    try {
        FileOutputStream out = new FileOutputStream(file);
        finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
        out.flush();
        out.close();

    } catch (Exception e) {
        e.printStackTrace();
    }
}

Шаг 3: Отправьте сохраненное изображение:

public void send() {
    try {
        File myFile = new File("/storage/emulated/0/saved_images/Image-test.jpg");
        MimeTypeMap mime = MimeTypeMap.getSingleton();
        String ext = myFile.getName().substring(myFile.getName().lastIndexOf(".") + 1);
        String type = mime.getMimeTypeFromExtension(ext);
        Intent sharingIntent = new Intent("android.intent.action.SEND");
        sharingIntent.setType(type);
        sharingIntent.putExtra("android.intent.extra.STREAM", Uri.fromFile(myFile));
        startActivity(Intent.createChooser(sharingIntent, "Share using"));
    } catch (Exception e) {
        Toast.makeText(getBaseContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
    }
}

Теперь после отправки вы можете удалить сохраненное изображение, если оно вам не нужно. Проверьте другую ссылку, чтобы сделать это.