android - Android:通过Intent发送ParcelFileDescriptor时发生异常

标签 android file android-intent

我正在编写一个android应用程序,其中我的服务需要向其他一些应用程序发送图像(通过广播消息或启动服务-有多个应用程序可能有兴趣接收图像)。
如果我将图像加载到一个位图对象中,并将其作为一个“额外”的意图,它实际上会工作。但是,我想看看是否可以发送一个ParcelFileDescriptor,让客户机自己加载位图对象(从阅读规范来看,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):致命异常:main
01-01 08:06:02.589:e/androidruntime(7483):java.lang.runtimeexception:无法启动服务com.test.robotsample.myservice@4161a0a8,意图是{.cmp=com.test.robotsample/.myservice}: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.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.invokenactive(本机方法)
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.zyteinit$methodandargscaller.run(zyteinit.java:786)
01-01 08:06:02.589:e/androidruntime(7483):位于com.android.internal.os.zygeteinit.main(zygeteinit.java:553)
01-01 08:06:02.589:e/androidruntime(7483):at dalvik.system.nativestart.main(本地方法)
01-01 08:06:02.589:e/androidruntime(7483):原因:java.lang.runtimeexception:不允许在此处写入文件描述符
01-01 08:06:02.589:e/androidruntime(7483):位于android.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):位于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个以上

最佳答案

是的,不可能通过意图传递ParcelFileDescriptor。尽管这似乎没有在android文档中明确记录。
选择:
使用bundle.putbinder()传递一个绑定器,该绑定器将返回带有pfd的包裹(来自api 18)。
使用从context.bindservice()开始的“绑定服务”,在这里您再次获得一个绑定器,通过它可以获得pfd。

关于android - Android:通过Intent发送ParcelFileDescriptor时发生异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18706062/

相关文章:

java - Java 中输出到文本文件

c - 什么更有效率 : reading from a file or allocating memory

android - 从图库中选择多个图像

android - 将 Retrofit 2 添加到 Gradle 中给出未能解决

android - 以编程方式在 edittext 下方创建一个新的 textview

c# - Silverlight 中的 URI 相对资源

java - Intent中的TreeMap变成了HashMap

java - 初学者的 FragmentPagerAdapter

android - AlarmManager 中重复警报的不同间隔时间

android - 如何处理小部件按钮