PasteBin

Newer Version New Note

15

Created: 2026-03-19 16:10:03

Expires: Never

Syntax: Plain Text

package com.pingxo.app;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.content.pm.PackageManager;
import android.provider.MediaStore;

import androidx.annotation.NonNull;

import com.getcapacitor.JSObject;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.annotation.CapacitorPlugin;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@CapacitorPlugin(name = "InstagramShare")
public class InstagramSharePlugin extends Plugin {

    private final ExecutorService executorService = Executors.newSingleThreadExecutor();

    @PluginMethod
    public void shareToStory(PluginCall call) {
        String imageUrl = call.getString("imageUrl");
        String contentUrl = call.getString("contentUrl");

        if (imageUrl == null || imageUrl.isEmpty()) {
            call.reject("imageUrl is required");
            return;
        }

        final String contentUrlFinal =
                (contentUrl == null || contentUrl.isEmpty())
                        ? "https://pingxo.com/app"
                        : contentUrl;

        executorService.execute(() -> {
            try {
                Uri imageUri = downloadAndCacheImage(imageUrl);
                if (imageUri == null) {
                    call.reject("Failed to download image");
                    return;
                }

                Intent intent = new Intent("com.instagram.share.ADD_TO_STORY");
                intent.setPackage("com.instagram.android");

                // Data + MIME type for the story background (Instagram expects JPEG in many cases)
                intent.setDataAndType(imageUri, "image/jpeg");

                // Grant URI access to Instagram
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                // Required extras for Instagram Story composer
                String facebookAppId = call.getString("facebookAppId");

                // If you didn't set FB App ID, fallback to package name for backward compatibility.
                // Instagram may still open the composer; if it doesn't, set instagram_facebook_app_id in strings.xml.
                if (facebookAppId == null || facebookAppId.isEmpty()) {
                    facebookAppId = getContext().getPackageName();
                }

                // Facebook App ID is required (Jan 2023+) for sharing to Stories
                intent.putExtra("source_application", facebookAppId);
                // Attribution URL for the shared content
                intent.putExtra("content_url", contentUrlFinal);
                // For background-only sharing, Instagram typically uses the intent data/type.
                // (When sharing background + sticker, then background_asset_uri is used.)

                PackageManager pm = getContext().getPackageManager();
                if (intent.resolveActivity(pm) == null) {
                    call.reject("Instagram is not installed");
                    return;
                }

                // Ensure Instagram can read the URI
                getContext().grantUriPermission(
                        "com.instagram.android",
                        imageUri,
                        Intent.FLAG_GRANT_READ_URI_PERMISSION
                );

                // Start on UI thread (safer than starting from executor thread)
                getActivity().runOnUiThread(() -> getActivity().startActivity(intent));

                JSObject result = new JSObject();
                result.put("success", true);
                call.resolve(result);
            } catch (Exception e) {
                call.reject("Error sharing to Instagram: " + e.getMessage(), e);
            }
        });
    }

    private Uri downloadAndCacheImage(@NonNull String imageUrl) throws IOException {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        try {
            URL url = new URL(imageUrl);
            connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.connect();
            inputStream = new BufferedInputStream(connection.getInputStream());
            Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
            if (bitmap == null) {
                return null;
            }

            String filename = "pingxo_story_" + System.currentTimeMillis() + ".jpg";
            ContentResolver resolver = getContext().getContentResolver();
            ContentValues values = new ContentValues();
            values.put(MediaStore.Images.Media.DISPLAY_NAME, filename);
            values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                values.put(MediaStore.Images.Media.IS_PENDING, 1);
            }

            Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
            if (imageUri == null) {
                return null;
            }

            try (java.io.OutputStream out = resolver.openOutputStream(imageUri)) {
                if (out == null) {
                    return null;
                }
                bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
            }

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                values.clear();
                values.put(MediaStore.Images.Media.IS_PENDING, 0);
                resolver.update(imageUri, values, null, null);
            }

            return imageUri;
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException ignored) {
                }
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
    }
}