代码之家  ›  专栏  ›  技术社区  ›  Tyler V

使用ACTION_CREATE_写入的文件在Google驱动器上是空的,但不是本地存储

  •  2
  • Tyler V  · 技术社区  · 8 年前

    我有一个应用程序,它使用 ACTION_CREATE_DOCUMENT 意图获取要写入的Uri一段时间以来,这一切都很好,但最近当我去保存一个文件并选择Google驱动器时,我注意到生成的文件是空的(0字节)但是,如果我选择下载文件夹作为目标(本地存储),则会正确地创建和写入文件。

    Result of saving to Google Drive (correctly written file is 14 bytes)

    我将问题简化为一个简单的测试活动(如下),并验证代码的所有部分实际上都在执行(没有捕获到异常, ParcelFileDescriptor 不为空等)。

    我在Android 7和Android 8模拟器以及android8物理设备上进行了测试,结果都显示了相同的行为,但是一个旧的Android 5手机工作正常??).

    应用程序的完整版本具有并正确请求读取和写入外部存储权限以处理某些 third party file managers ,但Google Drive不需要这样做,所以我在本例中省略了它(行为与授予的权限相同)。

    我得到的uri看起来像一个有效的内容uri( content://com.google.android.apps.docs.storage/document/acc%3... )

    还有人看到这个问题吗我在这里做错什么了吗我怎样才能让谷歌硬盘再次发挥作用?

    public class MainActivity extends AppCompatActivity {
    
        private static final int FILE_EXPORT_REQUEST_CODE = 12;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    
            if (resultCode != RESULT_OK)
                return;
    
            switch(requestCode) {
                case FILE_EXPORT_REQUEST_CODE:
                    if( data != null ) {
                        Uri uri = data.getData();
                        if( uri != null ) {
                            new ExportCSV(this).execute(uri);
                        }
                    }
                    break;
            }
        }
    
        // test Activity has a single button that calls this
        public void saveFile(View v) {
            Intent exportIntent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
            exportIntent.addCategory(Intent.CATEGORY_OPENABLE);
            exportIntent.setType("text/csv");
            String filename = "test.csv";
            exportIntent.putExtra(Intent.EXTRA_TITLE, filename);
            startActivityForResult(exportIntent, FILE_EXPORT_REQUEST_CODE);
        }
    
        private static class ExportCSV extends AsyncTask<Uri, Void, Boolean> {
            private final WeakReference<Context> context;
    
            ExportCSV(Context c) {
                context = new WeakReference<>(c);
            }
    
            @Override
            protected Boolean doInBackground(Uri... uris) {
                Uri uri = uris[0];
                Context c = context.get();
    
                if( c == null ) {
                    return false;
                }
    
                String data = "colA,colB\n1,2\n";
                boolean success = false;
    
                try {
                    ParcelFileDescriptor pfd = c.getContentResolver().openFileDescriptor(uri, "w");
                    if( pfd != null ) {
                        FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
                        fileOutputStream.write(data.getBytes());
                        fileOutputStream.close();
                        success = true;
                    }
                }
                catch(Exception e) {
                    e.printStackTrace();
                }
                return success;
            }
        }
    }
    
    1 回复  |  直到 8 年前
        1
  •  0
  •   Tyler V    7 年前

    来自@greenapps的评论让我走上了正确的道路更改为使用 getContentResolver().openOutputStream(...) 解决了问题:

    try {
        OutputStream os = c.getContentResolver().openOutputStream(uri);
        if( os != null ) {
            os.write(data.getBytes());
            os.close();
        }
    }
    catch(IOException e) {
        e.printStackTrace();
    }
    

    更新 :在我的应用程序中使用此功能一段时间后,问题再次出现(写入Google驱动器的文件为0字节,但可以在本地写入)清除我的应用程序的缓存数据再次解决了这个问题。