首页 > 解决方案 > 选择在 Android 中保存原始数据

问题描述

我试图在应用程序中保存一些数组以在其他平台(C++)中使用它们被序列化。我使用 pick 方法让用户选择文件名和目录,但首先我尝试像这样定义根目录,因为创建文档的处理需要 Android 10 在正确定义的目录中启动:

'''

     String a = getExternalStorageDirectory().getPath();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

            try {

                String public_dir = "sistemaderiegoandroid_arduino" + MyDocuments.fileSeparator;
                file = new File(a, public_dir);

                file.setWritable(true);

                    if (!file.mkdirs()) {

                        file.mkdir();

                    }
                    ;
                    DocumentsContract.createDocument(context.getContentResolver(), DocumentsContract.buildRootUri(MyDocuments.AUTORITY,MyDocuments.ROOT), DocumentsContract.Document.MIME_TYPE_DIR,MyDocuments.INITIALURI);
                    fileUri = DocumentsContract.buildDocumentUri(MyDocuments.AUTORITY,MyDocuments.INITIALURI);

                } catch (Exception e) {
                    errorMsg(MyDocuments.falloCrear + e.toString());
                }
        }else{
            file = new File(a);

            file.setWritable(true);
            };

            String StfileR = "arduino_data_resumen.bin";
            String StfileT = "arduino_data_tiempo.bin";
            String StfileH = "arduino_data_humedad.bin";
            String StfileL = "arduino_data_luz.bin";
       try{
            createFile(fileUri, StfileT, CREATE_FILE_T);
            createFile(fileUri, StfileL, CREATE_FILE_L);
            createFile(fileUri, StfileH, CREATE_FILE_H);
            createFile(fileUri, StfileR, CREATE_FILE_R);

        } catch (Exception e) {

            errorMsg(MyDocuments.falloCrear + e.toString());
        }
        try {

            allData.saveData(context);

        } catch (Exception e) {
            errorMsg(MyDocuments.falloGrabar + e.toString());
        }

private void createFile(Uri pickerInitialUri, String file_name, int result_option_Flag) {

    //DocumentsUI
    Intent intent = new Intent(ACTION_CREATE_DOCUMENT);
    intent.setType(MyDocuments.MINETYPE);
    intent.putExtra(Intent.EXTRA_TITLE, file_name);
    intent.putExtra(Intent.EXTRA_RETURN_RESULT, RESULT_OK);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri);
        intent.putExtra(Intent.EXTRA_RETURN_RESULT, RESULT_OK);
    }

    //    intent.putExtra(DocumentsContract.EXTRA_EXCLUDE_SELF,true);

    startActivityForResult(intent, result_option_Flag);


};

'''

清单中的权限是:

'''

      <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>         

     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>         

    <uses-permission-sdk-23 android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>         

    <uses-permission-sdk-23 android:name="android.permission.READ_EXTERNAL_STORAGE"/>           

'''

提供者是:

'''

    <provider       

     android:name="com.sistemaderiegoandroid_arduino.MyDocuments"        

    android:authorities="com.sistemaderiegoandroid_arduino.documents"          
    android:grantUriPermissions="true"        

    android:exported="true"        
    android:permission="android.permission.MANAGE_DOCUMENTS">         
     <intent-filter>        
    <action android:name="android.content.action.DOCUMENTS_PROVIDER" />         
    </intent-filter>        
    </provider>        

'''

为了将数据保存在文件中,我使用 FileDescriptor 和 getContentResolver().openFileDescriptor MODE_APPEND 方法,这给出了 ParcelFileDescriptor 和 getFileDescriptor() 方法,我使 FileOuputStream 如下所示:

'''

        FileDescriptor fdR = null;        

    parcelFileDescriptorL = getContentResolver().openFileDescriptor(fileNameL, "MODE_APPEND", null);
                fdL = parcelFileDescriptorL.getFileDescriptor();
                arduinoDataL = new FileOutputStream(fdL);
                serializatorDataL = new ObjectOutputStream(arduinoDataL);
                for (int i = 0; i < allData.arrayDatosLuz.length; i++) {

                    serializatorDataL.writeObject(allData.arrayDatosLuz[i]);

                    serializatorDataL.flush();

                    fdL.sync();

                }
                ;
                serializatorDataL.close();

'''

完整的包在这里:

https://github.com/DarioLobos/sistemariego

我添加了这个授予权限请求,但无论如何手机不要求权限。我在手机的应用程序管理器中重置了限制和许可的缓存,无论如何在我安装程序时不要要求授予它们。其他应用程序在安装和手机请求授予权限时没有问题。

'''

 int granted = PackageManager.PERMISSION_GRANTED;

    grantRequested =
            ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != granted |
                    ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != granted |
                    ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH) != granted |
                    ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_ADMIN) != granted;

    if ((grantRequested)) {

        if ((ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_SETTINGS) != PackageManager.PERMISSION_GRANTED)) {

            final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
            alertDialogBuilder.setTitle(grantDialog).setMessage(R.string.requestWriteSetting);
            alertDialogBuilder.setCancelable(false)
                    .setPositiveButton("Ok", new DialogInterface.OnClickListener() {

                        public void onClick(DialogInterface dialog, int id) {
                            if (callBackFlag == 0) {
                                Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
                                startActivity(intent);
                                callBackFlag++;
                                int granted = PackageManager.PERMISSION_GRANTED;
                                if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_SETTINGS) == granted) {

                                    grantRequested =
                                            ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != granted |
                                                    ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != granted |
                                                    ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH) != granted |
                                                    ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_ADMIN) != granted;
                                    if (grantRequested) {

                                        ActivityCompat.requestPermissions(MainActivity.this,
                                                new String[]{
                                                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                                                        Manifest.permission.READ_EXTERNAL_STORAGE,
                                                        Manifest.permission.BLUETOOTH,
                                                        Manifest.permission.BLUETOOTH_ADMIN}, RESULT_OK);


                                    } else {
                                        if (grantRequested) {

                                            final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
                                            alertDialogBuilder.setTitle(exit).setMessage(R.string.permitNotGranted);
                                            alertDialogBuilder.setCancelable(false)
                                                    .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                                                        public void onClick(DialogInterface dialog, int id) {

                                                            MainActivity.this.finish();
                                                            System.exit(0);
                                                        }
                                                    });


                                            AlertDialog alertDialog = alertDialogBuilder.create();
                                            alertDialog.show();

                                        }
                                    }
                                }
                            } else {
                                dialog.dismiss();

                                alertDialogBuilder.setTitle(exit).setMessage(R.string.permitNotGranted);
                                alertDialogBuilder.setCancelable(false)
                                        .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                                            public void onClick(DialogInterface dialog, int id) {

                                                MainActivity.this.finish();
                                                System.exit(0);
                                            }
                                        });


                                AlertDialog alertDialog = alertDialogBuilder.create();
                                alertDialog.show();

                            }
                        }

                    });

        }
    }
}


@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    boolean grantChecker = false;


    if (grantResults.length > 0) {
        grantChecker = true;

        for (int i = 0; grantResults.length > i; i++) {
            boolean a = grantResults[i] == PackageManager.PERMISSION_GRANTED;
            grantChecker = grantChecker & a;
        }
    }

    if (requestCode != RESULT_OK) {

        int granted = PackageManager.PERMISSION_GRANTED;

        if (!grantChecker & (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_SETTINGS) == granted)) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                ResumenFragment.errorMsg(permitHandling);
                ActivityCompat.requestPermissions(this,
                        new String[]{
                                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                                Manifest.permission.READ_EXTERNAL_STORAGE,
                                Manifest.permission.BLUETOOTH,
                                Manifest.permission.BLUETOOTH_ADMIN}, RESULT_OK);

            } else {

                grantRequested =
                        ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != granted |
                                ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != granted |
                                ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH) != granted |
                                ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_ADMIN) != granted;

                if (grantRequested) {

                    final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);


                    alertDialogBuilder.setTitle(exit).setMessage(R.string.permitNotGranted);
                    alertDialogBuilder.setCancelable(false)
                            .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int id) {

                                    MainActivity.this.finish();
                                    System.exit(0);
                                }
                            });


                    AlertDialog alertDialog = alertDialogBuilder.create();
                    alertDialog.show();

                }
                ;
            }

        }
    }

''' OPENDOCUMENT 和 CREATEDOCUMENT 结果的 Intents 在重写方法 onActivityResult 中提供了有关拾取文件的信息。如果获得文件的 URI,则使用 intent.getData(),然后使用 contentResolver.openFileDescriptor 可以打开并使用 getFileDescriptor() 方法执行 FileOutputStream 或 FileInputStream 同步。像这样:

'''

    @Override
public void onActivityResult(int requestCode, int resultCode,
                             Intent resultData) {
    if (resultCode == Activity.RESULT_OK) {


        //           The result data contains a URI for the document or directory that
        //           the user selected.
        if (resultData != null) {

            Uri uriData = resultData.getData();
         //   String fileId =DocumentsContract.getDocumentId(uriData);



                    if (requestCode == CREATE_FILE_L) {
                        Data.fileNameL = uriData;
                    }
                    if (requestCode == CREATE_FILE_H) {
                        Data.fileNameH = uriData;
                    }
                    if (requestCode == CREATE_FILE_R) {
                        Data.fileNameR = uriData;
                    }
                    if (requestCode == CREATE_FILE_T) {
                        Data.fileNameR = uriData;
                    }

                    if (requestCode == PICK_FILE_T) {
                        Data.fileNameT = uriData;
                    }
                    if (requestCode == PICK_FILE_L) {
                        Data.fileNameL = uriData;
                    }
                    if (requestCode == PICK_FILE_H) {
                        Data.fileNameH = uriData;
                    }
                    if (requestCode == PICK_FILE_R) {
                        Data.fileNameR = uriData;

'''

我需要知道定义根目录和目录下载以及从意图结果中收集的提取名称和目录的正确方法。我做了很多没有解决方案的试验,欢迎任何帮助。

标签: androidfileexceptionpermissionssave

解决方案


推荐阅读