3

サービスが他のアプリに画像を送信する必要があるAndroidアプリを作成しています(ブロードキャストメッセージを介して、またはサービスを開始することにより、画像の受信に関心のある複数のアプリがあります)。

画像を Bitmap オブジェクトにロードし、インテントの「エクストラ」として配置すると、実際に機能します。ただし、代わりに ParcelFileDescriptor を送信して、クライアントが独自に Bitmap オブジェクトをロードできるかどうかを確認したいと思います (仕様を読むと、ParcelFileDescriptor はプロセス間でファイルを共有するためだけに作成されているようです)。ここでは、インテント経由で大きなオブジェクトを送信しないようにしています。だから私はこのようなものを書きました:

    @Override
public int onStartCommand(Intent intent, int flags, int startId) {
    System.out.println("Service is called" + this.getClass());
    Intent newIntent = new Intent(MY_ACTION);
    try {
        File icon = new File(getExternalFilesDir(null), "robot_icon.jpg");
        icon.setReadable(true, false);
        if( !icon.exists() ) {
            System.out.println("Writting file " + icon);
                FileOutputStream out;
                out = new FileOutputStream(icon);
                BitmapFactory.decodeResource(getResources(), R.drawable.two_face_answer_map).compress(CompressFormat.JPEG, 100, out);
                out.close();
                System.out.println("Closing file after writing" + icon);
        }

        newIntent.putExtra(EXTRA_BITMAP, ParcelFileDescriptor.open(icon, ParcelFileDescriptor.MODE_READ_WRITE));
//          sendBroadcast(newIntent);
        startService(newIntent);
    } catch (FileNotFoundException e) {
        Log.e(TAG, "Error opening robot icon file", e);
    }catch (IOException e) {
        Log.e(TAG, "Error opening robot icon file", e);
    }

    System.out.println("No Exception");
    return super.onStartCommand(intent, flags, startId);
}

このコードが実行されると、「ここにファイル記述子を書き込むことは許可されていません」という RuntimeException を常に受け​​取ります。sendBroadcast と startService オプションの両方で問題が発生することに注意してください。ここで許可されていない理由を知っている人はいますか?私は何を間違えましたか?ParcelFileDescriptor を誤解しましたか? トレースは次のとおりです。

01-01 08:06:02.589: E/AndroidRuntime(7483): 致命的な例外: メイン 01-01 08:06:02.589: E/AndroidRuntime(7483): java.lang.RuntimeException: サービス com.test を開始できません。 robotsample.MyService@4161a0a8 with Intent { cmp=com.test.robotsample/.MyService }: java.lang.RuntimeException: ここにファイル記述子を書き込むことは許可されていません 01-01 08:06:02.589: E/AndroidRuntime(7483): at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2507) 01-01 08:06:02.589: E/AndroidRuntime(7483): android.app.ActivityThread.access$1900(ActivityThread.java:130) 01-01 08 :06:02.589: E/AndroidRuntime(7483): android.app.ActivityThread$H.handleMessage(ActivityThread.java:1292) 01-01 08:06:02.589: E/AndroidRuntime(7483): android.os で。 Handler.dispatchMessage(Handler.java:99) 01-01 08:06:02.589: E/AndroidRuntime(7483): android.os.Looper で。loop(Looper.java:137) 01-01 08:06:02.589: E/AndroidRuntime(7483): android.app.ActivityThread.main(ActivityThread.java:4745) 01-01 08:06:02.589: E/ AndroidRuntime(7483): java.lang.reflect.Method.invokeNative(Native Method) 01-01 08:06:02.589: E/AndroidRuntime(7483): java.lang.reflect.Method.invoke(Method.java: 511) 01-01 08:06:02.589: E/AndroidRuntime(7483): com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 01-01 08:06:02.589: E/ AndroidRuntime (7483): com.android.internal.os.ZygoteInit.main (ZygoteInit.java:553) 01-01 08:06:02.589: E/AndroidRuntime (7483): dalvik.system.NativeStart.main (Native Method) 01-01 08:06:02.589: E/AndroidRuntime(7483): 原因: java.lang.RuntimeException: ここにファイル記述子を書き込むことは許可されていません 01-01 08:06:02.589: E/AndroidRuntime(7483):アンドロイドで。os.Parcel.nativeWriteFileDescriptor(ネイティブ メソッド) 01-01 08:06:02.589: E/AndroidRuntime(7483): android.os.Parcel.writeFileDescriptor(Parcel.java:552) 01-01 08:06:02.589: E /AndroidRuntime(7483): android.os.ParcelFileDescriptor.writeToParcel(ParcelFileDescriptor.java:412) 01-01 08:06:02.589: E/AndroidRuntime(7483): android.os.Parcel.writeParcelable(Parcel.java: 1254) 01-01 08:06:02.589: E/AndroidRuntime(7483): android.os.Parcel.writeValue(Parcel.java:1173) 01-01 08:06:02.589: E/AndroidRuntime(7483): at android.os.Parcel.writeMapInternal(Parcel.java:591) 01-01 08:06:02.589: E/AndroidRuntime(7483): android.os.Bundle.writeToParcel(Bundle.java:1619) 01-01 08: 06:02.589: E/AndroidRuntime(7483): android.os.Parcel.writeBundle(Parcel.java:605) 01-01 08:06:02.589: E/AndroidRuntime(7483): android.content で。Intent.writeToParcel(Intent.java:6470) 01-01 08:06:02.589: E/AndroidRuntime(7483): android.app.ActivityManagerProxy.startService(ActivityManagerNative.java:2468) 01-01 08:06:02.589: E/AndroidRuntime(7483): android.app.ContextImpl.startService(ContextImpl.java:1149) 01-01 08:06:02.589: E/AndroidRuntime(7483): android.content.ContextWrapper.startService(ContextWrapper.java) :383) 01-01 08:06:02.589: E/AndroidRuntime(7483): com.test.robotsample.MyService.onStartCommand(MyService.java:63) 01-01 08:06:02.589: E/AndroidRuntime(7483) ): at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2490) 01-01 08:06:02.589: E/AndroidRuntime(7483): ... 10 もっと見る2468) 01-01 08:06:02.589: E/AndroidRuntime(7483): android.app.ContextImpl.startService(ContextImpl.java:1149) 01-01 08:06:02.589: E/AndroidRuntime(7483): at android.content.ContextWrapper.startService(ContextWrapper.java:383) 01-01 08:06:02.589: E/AndroidRuntime(7483): com.test.robotsample.MyService.onStartCommand(MyService.java:63) 01-01 で08:06:02.589: E/AndroidRuntime(7483): android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2490) 01-01 08:06:02.589: E/AndroidRuntime(7483): ... 10 以上2468) 01-01 08:06:02.589: E/AndroidRuntime(7483): android.app.ContextImpl.startService(ContextImpl.java:1149) 01-01 08:06:02.589: E/AndroidRuntime(7483): at android.content.ContextWrapper.startService(ContextWrapper.java:383) 01-01 08:06:02.589: E/AndroidRuntime(7483): com.test.robotsample.MyService.onStartCommand(MyService.java:63) 01-01 で08:06:02.589: E/AndroidRuntime(7483): android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2490) 01-01 08:06:02.589: E/AndroidRuntime(7483): ... 10 以上onStartCommand(MyService.java:63) 01-01 08:06:02.589: E/AndroidRuntime(7483): android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2490) 01-01 08:06:02.589: E/ AndroidRuntime(7483): ... 10 以上onStartCommand(MyService.java:63) 01-01 08:06:02.589: E/AndroidRuntime(7483): android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2490) 01-01 08:06:02.589: E/ AndroidRuntime(7483): ... 10 以上

4

1 に答える 1

4

はい、インテントを介して ParcelFileDescriptor を渡すことはできません。これは Android ドキュメントに明確に記載されていないようですが。

代替案:

  • Bundle.putBinder() を使用して、(API 18 から) PFD を含むパーセルを返す Binder を渡します。
  • Context.bindService() で始まる「バインドされたサービス」を使用します。ここで、PFD を取得するための Binder を再度取得します。
于 2014-05-21T06:41:43.293 に答える