Android 6 - 以编程方式将应用程序文件复制到另一个文件夹

Android 6 - Programmatically copy an app file to another folder

我在 Android 6 中有一个应用 运行 可以从 BLE 设备流式传输数据。这在使用类似以下内容时效果很好:

myFile = new File(getExternalFilesDir(文件路径), MyData);

生成的文件位于如下所示的位置:

文件路径:/storage/emulated/0/Android/data/my_package/files/my_file

我想将此文件复制到 Android/data 目录下未被埋没的新文件夹中,以便用户可以轻松找到和检索连接到 phone/tablet 的数据通过 USB 数据线。到目前为止,我一直无法弄清楚如何做到这一点......或者它是否可能。我尝试的任何事情似乎都会导致权限异常。

如果可能,我希望此文件夹与 ~/Android/data 处于同一级别。如果没有,还有其他选择吗?比如把数据放到SD卡上。

我通读了许多关于 Android 文件系统的帖子和文章。这一切都非常混乱和模糊。 Android 的新版本似乎改变了工作方式。如果有人知道关于 Android 6 (Marshmallow) 的清晰简洁的解释(甚至可能有工作示例!),请告诉我。

谢谢,马克斯

android 6.0 出于某些安全原因限制获得 运行 时间权限。因此,以下代码将帮助您获得许可。

注意不要从清单中删除权限,下面给出的过程仅适用于 6.0 其他 android OS 将从清单中授予权限

public static final int galleryPermissionRequestCode=4;


public void chkForPermissoins(){



if (Build.VERSION.SDK_INT >= 23) {
                    //do your check here

                    isStoragePermissionGranted(camPermissionRequestCode);

                } else {

                   //You already have the permission because the os you appp is running on is less tahn 23 (6.0)

                }


}


public  boolean isStoragePermissionGranted(int requsetCode) {
        if (Build.VERSION.SDK_INT >= 23) {
            if (ContextCompat.checkSelfPermission(getActivity(),android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    == PackageManager.PERMISSION_GRANTED) {

               //Now you have permsssion
                return true;
            } else {


                ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, requsetCode);
                return false;
            }
        }
        else { //permission is automatically granted on sdk<23 upon installation

           //Now you have permsssion
            return true;
        }


    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(grantResults[0]== PackageManager.PERMISSION_GRANTED){

        //Now you have permsssion
         //resume tasks needing this permission
        }
    }

我使用了 Adeel Turk 的许可建议。我不需要检查构建版本,因为我只使用 Android 6 (API 23).

//
// Get storage write permission
//
public  boolean isStoragePermissionGranted(int requestCode) {
    if (ContextCompat.checkSelfPermission(MyActivity.this,android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
            == PackageManager.PERMISSION_GRANTED) {

        //Now you have permission
        return true;
    } else {


        ActivityCompat.requestPermissions(MyActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, requestCode);
        return false;
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {

        //Now you have permission

        // Check file copy generated the request
        // and resume file copy
        if(requestCode == WFileRequest)
            try {
                copyFile(OriginalDataFileName);
            } catch (IOException e) {
                e.printStackTrace();
            }
    }
}

虽然这通过了权限异常,但它没有回答如何在默认应用程序目录之外创建文件夹的问题。以下代码获得许可并在 /storage/emulated/0 处创建一个名为 AppData 的文件夹,该文件夹出现在设备存储的顶层。在 Adeel Turk 的示例中,权限请求代码 WFileRequest 设置为 4,但我知道您可以使用任何数字。权限请求回调然后检查请求代码并使用最初写入的文件的名称再次调用 copyFile 例程。

大部分代码使用了本论坛 how to create a folder in android External Storage Directory? and

中其他几个帖子的示例
    public void copyFile(String SourceFileName) throws FileNotFoundException, IOException
{
    String filepath = "";
    //
    // Check permission has been granted
    //
    if (isStoragePermissionGranted(WFileRequest)) {
        //
        // Make the AppData folder if it's not already there
        //
        File Directory = new File(Environment.getExternalStorageDirectory() + "/AppData");
        Directory.mkdirs();

        Log.d(Constants.TAG, "Directory location: " + Directory.toString());
        //
        // Copy the file to the AppData folder
        // File name remains the same as the source file name
        //
        File sourceLocation = new File(getExternalFilesDir(filepath),SourceFileName);
        File targetLocation = new File(Environment.getExternalStorageDirectory() + "/AppData/" + SourceFileName);

        Log.d(Constants.TAG, "Target location: " + targetLocation.toString());

        InputStream in = new FileInputStream(sourceLocation);
        OutputStream out = new FileOutputStream(targetLocation);

        // Copy the bits from instream to outstream
        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
        in.close();
        out.close();
    }

}