Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android:通过Intent发送ParcelFileDescriptor的异常_Android_File_Android Intent - Fatal编程技术网

Android:通过Intent发送ParcelFileDescriptor的异常

Android:通过Intent发送ParcelFileDescriptor的异常,android,file,android-intent,Android,File,Android Intent,我正在编写一个android应用程序,其中我的服务需要将图像发送到其他一些应用程序(通过广播消息或启动服务-可能有多个应用程序有兴趣接收图像) 如果我将图像加载到位图对象中,并将其作为一个“额外”的意图,它实际上会工作。但是,我想看看是否可以发送一个ParcelFileDescriptor,让客户端自己加载位图对象(从读取规范来看,似乎ParcelFileDescriptor就是为了这个目的而创建的——在进程之间共享文件)。在这里,我试图避免通过Intent发送大型对象。所以我写了这样的东西:

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

如果我将图像加载到位图对象中,并将其作为一个“额外”的意图,它实际上会工作。但是,我想看看是否可以发送一个ParcelFileDescriptor,让客户端自己加载位图对象(从读取规范来看,似乎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选项都存在问题。有人知道为什么这里不允许吗?我做错了什么?我是不是误解了包裹的描述?以下是跟踪:

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出于意图{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.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(本机方法) 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.writeMapineral(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更多

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

备选方案:

  • 使用Bundle.putBinder()传递一个活页夹,该活页夹将返回带有PFD的包裹(来自API 18)
  • 使用一个“绑定服务”,从Context.bindService()开始,再次获得一个绑定器,通过该绑定器可以获得PFD

如果我从ContentProvider返回PaecelFileDescriptor,它就可以正常工作。因此,至少我认为问题不应该出在文件本身(文件的存储方式、存储位置及其权限…)。我只能猜测,ParcelFileDescriptor不能用于广播或服务目的。只希望规范能更清楚一点。