将多个 Uris 从 Activity 传递给服务的处理程序

问题描述

我正在尝试实现一个应用程序,该应用程序接收包含多个文件/资源​​的 ArrayList<Uri> 并将它们上传到远程。

Activity 从外部接收 Uris。用户选择某个目标文件夹并单击某个按钮以提交上传。然后将 Uris 传递给服务。来自 onStartCommand 的 Uris 通过 android.os.Message->obj 更深入地传递到 Handler 中。但是当谈到 ServiceHandler->handleMessage 时,我得到“java.lang.SecurityException: Permission Denial: opening provider com.google.android.libraries.storage.storagelib.FileProvider from ProcessRecord{...} 这不是从 UID 10071" 导出。当我尝试查询任何 Uri 时抛出此异常,例如读取其内容getContentResolver().openInputStream(uri)

请帮助我让它工作。也许有一种方法可以更正确地将这些 Uris 提供给 Handler?或者我应该以某种方式配置 Service 或 Handler?

MyActivity.java:

public class MyActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // ...
        
        Intent recvIntent = getIntent();
        if (Intent.ACTION_SEND_MULTIPLE.equals(recvIntent.getAction())) {
            // Get provided Uris (there can be a list of arbitrary files,// selected within any filesystem navigator app or a photos from GDrive):
            ArrayList<Uri> receivedUris = recvIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
            
            // In a wild following code runs just after user selects
            // remote destination folder and clicks a button to submit upload:
            Intent intent = new Intent();
            intent.setClass(MyActivity.this,MyService.class);
            intent.putExtra(MyService.EXTRA_COMMAND,MyService.COMMAND_UPLOAD);
            intent.putExtra(Intent.EXTRA_STREAM,receivedUris);
            intent.setType("*/*");
            
            /*
             * AFAIK following perms can be applied for a single Uri,* that is set via intent.setData(uri) or for a ClipData,* that is set via intent.setClipData(clipData).
             * But in this case it does nothing:
             */
            // intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
            
            
            // If I query any passed Uri here within activity,// there are no errors,everything works as expected:
            // getContentResolver().openInputStream(receivedUris.get(0)); // Mkay
            
            
            // Start service to upload selected resources in background,// stop current activity and resume prevIoUs application:
            startService(intent);
            finish();
        }
    }
}

文件末尾出现错误 MyService.java:

public class MyService extends Service {
    final public static String EXTRA_COMMAND = "command";
    final public static int COMMAND_UPLOAD = 1;
    
    private ServiceHandler serviceHandler;
    
    @Override
    public void onCreate() {
        // Start up the thread running the service:
        HandlerThread thread = new HandlerThread("ServiceStartArguments",HandlerThread.MIN_PRIORITY);
        thread.start();
        
        // Get the HandlerThread's Looper and use it for our Handler:
        serviceHandler = new ServiceHandler(thread.getLooper());
    }
    
    @Override
    public int onStartCommand(Intent intent,int flags,int startId) {
        ArrayList<Uri> uris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
        
        // For each start request,send a message to start a job and deliver the
        // start ID so we kNow which request we're stopping when we finish the job:
        Message msg = serviceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.arg2 = intent.getIntExtra(EXTRA_COMMAND,0);
        msg.obj = uris;
        
        // If I query any passed Uri here within onStartCommand,everything works as expected:
        // getContentResolver().openInputStream(uris.get(0)); // Mkay
        
        // Finally,run upload process:
        serviceHandler.sendMessage(msg);
        
        // If we get killed,after returning from here,restart:
        return START_REDELIVER_INTENT;
    }
    
    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }
        
        @Override
        public void handleMessage(Message msg) {
            final int startId = msg.arg1;
            final int command = msg.arg2;
            
            // ... (prepare ongoing notification here for startForeground,etc)
            
            if (command == COMMAND_UPLOAD) {
                ArrayList<Uri> uris = (ArrayList<Uri>) msg.obj;
                
                
                // If I query any passed Uri here within ServiceHandler,// there is a java.lang.SecurityException:
                
                // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                getContentResolver().openInputStream(uris.get(0)); // Not mkay :(
                // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                
                // I'm getting "java.lang.SecurityException: Permission Denial: opening provider com.google.android.libraries.storage.storagelib.FileProvider from ProcessRecord{...} that is not exported from UID 10071"
            }
            
            // Stop the service using the startId,so that we don't stop
            // the service in the middle of handling another job:
            stopSelf(msg.arg1);
            stopForeground(true);
        }
    }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)