3

我正在编写一个 android 应用程序,我的服务需要将图像发送到其他一些应用程序(通过广播消息或通过启动服务 - 有多个应用程序可能有兴趣接收图像)。

如果我将图像加载到 Bitmap 对象中并将其作为 Intent 的“额外”,它实际上会起作用。但是,我想看看我是否可以发送 ParcelFileDescriptor,并让客户端自己加载 Bitmap 对象(从阅读规范来看,看起来 ParcelFileDescriptor 是为此目的而创建的——在进程之间共享文件)。在这里,我试图避免通过 Intent 发送大对象。所以我写了这样的东西:

    @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): 致命异常: main 01-01 08:06:02.589: E/AndroidRuntime(7483): java.lang.RuntimeException: 无法启动服务 com.test。带有 Intent { cmp=com.test.robotsample/.MyService } 的 robotssample.MyService@4161a0a8:java.lang.RuntimeException:不允许在此处写入文件描述符 01-01 08:06:02.589:E/AndroidRuntime(7483):在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。循环(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): at java.lang.reflect.Method.invokeNative(Native Method) 01-01 08:06:02.589: E/AndroidRuntime(7483): at 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方法) 01-01 08:06:02.589: E/AndroidRuntime(7483): Caused by: java.lang.RuntimeException: Not allowed to write file descriptors here 01-01 08:06:02.589: E/AndroidRuntime(7483):在安卓。os.Parcel.nativeWriteFileDescriptor(Native Method) 01-01 08:06:02.589: E/AndroidRuntime(7483): at 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): 在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 ): 在 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): 在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): 在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

是的,不可能通过 Intent 传递 ParcelFileDescriptor。尽管这似乎没有在 Android 文档中明确记录。

备择方案:

  • 使用 Bundle.putBinder() 传递一个 Binder,它将返回一个带有 PFD 的 Parcel(来自 API 18)。
  • 使用“绑定服务”,从 Context.bindService() 开始,您再次获得一个 Binder,通过它获取 PFD。
于 2014-05-21T06:41:43.293 回答