Androidアプリ開発

アプリ間でファイル連携する

この記事は約14分で読めます。
記事内に広告が含まれています。
スポンサーリンク

この記事はAndroidスマホ用のアプリ開発の中で、
今後の開発で再使用性が高いと思われるコーディングをまとめたものです。
Javaの開発経験、XML構文規則、Androidのアプリ開発経験がある方を対象としています。
Androidのアプリ開発でお役にたててれば、嬉しいです。
(これからAndroidのアプリ開発やJavaでの開発を始めたい方への案内は、
記事の最後で紹介します)

この記事のテーマ


ファイルを起動引数として、別アプリ(サービス)を起動する

HERO12以降は熱暴走という爆弾も解消され、車載動画の撮影に最適です

ポイント

アプリ間でファイルを連携する場合、出力と入力でファイル指定のユーザ操作が必要となります。
今回は、アプリ間でのファイル連携をワンストップで実現する、ファイルを起動引数とした別アプリ(サービス)を起動する方法を紹介します。

起動引数の連携はClipDataを使用します。

ClipData

ClipData

ファイル指定のユーザ操作を必要としない出力先として、内部ストレージと外部ストレージがあります。
内部ストレージと外部ストレージはアプリ固有のストレージのため、別のアプリからアクセスできません。
アプリ間でファイル連携する場合、起動引数にファイル(Uri)をClipDataに格納、アプリを起動する必要があります。

起動する側

AndroidManifestに起動される側のアプリの情報と外部ストレージにアクセスするためのFileProviderを設定します。

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest
    :
    <queries>
        <package android:name="com.jiseifirm.duel" />
        :
        <intent>
            <action android:name="android.intent.action.SEND" />
            <data android:mimeType="*/*" />
        </intent>
    </queries>
    :
    <application
        :
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_path"/>
        </provider>
    </application>
</manifest>

Intentに設定するActionSENDmimeTypeは連携するファイルがZipファイルのため”*/*”を設定します。
FileProviderのパス情報はxmlフォルダにprovider_path.xmlとして格納します。

<package>に起動される側のパッケージを登録する必要があります。

provider_path.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="external_files" path="."/>
</paths>

アプリの起動はIntentを使用します。
IntentActionと起動するアプリのパッケージ名、起動引数のClipDataにファイル(Uri)格納します。

// Zipファイルを起動引数にセットして、アプリを起動する
Intent intent = new Intent(Intent.ACTION_SEND).setPackage("com.jiseifirm.duel");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setType("application/zip");
intent.putExtra(Intent.EXTRA_STREAM, getUri(zip));
intent.setClipData(ClipData.newRawUri("", getUri(zip)));
startForegroundService(intent);
:

// Uri取得 //
public Uri getUri(String fileName, int type) {
    Context context = getApplicationContext();
    file = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), fileName);
    return FileProvider.getUriForFile(context, context.getPackageName() + ".fileProvider", file);
}
:

連携ファイルの格納先は外部ストレージのDocumentsフォルダを使用します。

起動される側

AndroidManifestに外部アプリから起動できるようにintent-filter設定します。

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest
    :
    <application
        :
         <service
            android:name="com.jiseifirm.duel.service.VideoService"
            android:foregroundServiceType="dataSync"
            android:exported="true"
            tools:ignore="ExportedService">
            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <data android:mimeType="*/*"/>
            </intent-filter>
        </service>
        :
    :
    </application>
</manifest>

アプリ起動時にIntentから連携ファイルのUriを取得します。

public class VideoService extends Service {
    private Uri EXTRA_STREAM;
    private final Handler handler = new Handler(Looper.getMainLooper());
    private ZipInputStream zipInputStream;
    private BufferedOutputStream bufferedOutputStream;
    private ZipEntry zipEntry;
    private File zipFile;
    private int len;
    :

    @Override
    public int onStartCommand(@SuppressLint("UnsafeIntentLaunch") Intent intent, int flags, int startId) {
        // 引数セット
        EXTRA_STREAM = intent.getParcelableExtra(Intent.EXTRA_STREAM);
        :

        videoService();
        return START_NOT_STICKY;
    }
    :

    private void videoService() {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.execute(() -> {
            try {
                Uri fileUri = null;
                zipInputStream = new ZipInputStream(context.getContentResolver().openInputStream(EXTRA_STREAM));
                while ((zipEntry = zipInputStream.getNextEntry()) != null) {
                    OutputStream outputStream = null;
                    ContentValues values = new ContentValues();
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                        values.put(MediaStore.MediaColumns.DISPLAY_NAME, zipEntry.getName());
                        values.put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4");
                        values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_MOVIES);
                        fileUri = context.getContentResolver().insert(MediaStore.Video.Media.getContentUri("external"), values);
                        outputStream = context.getContentResolver().openOutputStream(Objects.requireNonNull(fileUri));
                    } else {
                        zipFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).toString(), zipEntry.getName());
                        fileUri = Uri.fromFile(zipFile);
                        outputStream = Files.newOutputStream(zipFile.toPath());
                    }
                    if (outputStream != null) {
                        bufferedOutputStream = new BufferedOutputStream(outputStream);
                        byte[] buffer = new byte[1024];
                        while ((len = zipInputStream.read(buffer)) != -1) {
                            bufferedOutputStream.write(buffer, 0, len);
                        }
                        bufferedOutputStream.close();
                    }
                    zipInputStream.closeEntry();
                }
            } catch (IOException e) {
                // エラー処理
                :

            }
            handler.post(() -> {
               // 後処理
              :

            });
        });
    }

サンプルでは、連携ファイルが動画ファイル(mp4)の圧縮ファイル(Zip)です。
起動引数のUriを使用して、Zipファイルを解凍、メディアストアに登録しています。

今回は、ここまでです。

アプリ間でファイル連携しているAndroidアプリです。

誤字脱字、意味不明でわかりづらい、
もっと詳しく知りたいなどのご意見は、
このページの最後にある
コメントか、
こちらから、お願いいたします♪

ポチッとして頂けると、
次のコンテンツを作成する励みになります♪

ブログランキング・にほんブログ村へ

これからAndroidのアプリ開発やJavaでの開発を始めたい方へ

アプリケーション開発経験がない方や、アプリケーション開発経験がある方でも、JavaやC#などのオブジェクト指向言語が初めての方は、Androidのアプリ開発ができるようになるには、かなりの時間がかかります。
オンラインスクールでの習得を、強くおススメします。

未経験者からプログラマーを目指すのに最適です。まずは無料カウンセリングから♪

ゲーム系に強いスクール、UnityやUnrealEngineを習得するのに最適です。まずは無料オンライン相談から♪

参考になったら、💛をポッチとしてね♪

スポンサーリンク
シェアする
msakiをフォローする
スポンサーリンク

コメント欄

タイトルとURLをコピーしました