首页 > 解决方案 > 如何知道文件来自android的内部或外部存储?

问题描述

我想知道如何确定文件路径是来自内部存储还是外部存储。

我想删除一个文件。在删除它之前,我想检查它是来自内部存储器还是外部存储器。如果文件来自内部存储,那么我可以像这样简单地删除它

file.delete();

但是如果文件来自外部存储(SD卡)。然后我会先检查权限,然后通过存储访问框架将其删除。

我目前正在这样做。

            File selectedFile = Constant.allMemoryVideoList.get(fPosition).getFile().getAbsoluteFile();

            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (???????????? check if file is not from internal storage ???????????) {
                    List<UriPermission> permissions = getContentResolver().getPersistedUriPermissions();
                    if (permissions != null && permissions.size() > 0) {
                        sdCardUri = permissions.get(0).getUri();
                        deleteFileWithSAF();
                    } else {
                        AlertDialog.Builder builder = new AlertDialog.Builder(this);
                        builder.setTitle("Please select external storage directory (e.g SDCard)")
                                .setMessage("Due to change in android security policy it is not possible to delete or rename file in external storage without granting permission")
                                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        // call document tree dialog
                                        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
                                        startActivityForResult(intent, REQUEST_CODE_OPEN_DOCUMENT_TREE);
                                    }
                                })
                                .setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {

                                    }
                                })
                                .show();
                    }

                } else {
                    deleteFile();
                }
            } else {
                deleteFile();
            }

deleteFileWithSAF()

    private void deleteFileWithSAF() {
        //First we get `DocumentFile` from the `TreeUri` which in our case is `sdCardUri`.
        DocumentFile documentFile = DocumentFile.fromTreeUri(this, sdCardUri);

        //Then we split file path into array of strings.
        //ex: parts:{"", "storage", "extSdCard", "MyFolder", "MyFolder", "myImage.jpg"}
        // There is a reason for having two similar names "MyFolder" in
        //my exmple file path to show you similarity in names in a path will not
        //distract our hiarchy search that is provided below.
        String[] parts = (selectedFile.getPath()).split("\\/");

        // findFile method will search documentFile for the first file
        // with the expected `DisplayName`

        // We skip first three items because we are already on it.(sdCardUri = /storage/extSdCard)
        for (int i = 3; i < parts.length; i++) {
            if (documentFile != null) {
                documentFile = documentFile.findFile(parts[i]);
            }
        }

        if (documentFile == null) {

            // File not found on tree search
            // User selected a wrong directory as the sd-card
            // Here must inform user about how to get the correct sd-card
            // and invoke file chooser dialog again.

            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("Please select root of external storage directory (click SELECT button at bottom)")
                    .setMessage("Due to change in android security policy it is not possible to delete or rename file in external storage without granting permission")
                    .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            // call for document tree dialog
                            Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
                            startActivityForResult(intent, REQUEST_CODE_OPEN_DOCUMENT_TREE);
                        }
                    })
                    .setNegativeButton("CANCEL", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {

                        }
                    })
                    .show();

        } else {

            // File found on sd-card and it is a correct sd-card directory
            // save this path as a root for sd-card on your database(SQLite, XML, txt,...)

            // Now do whatever you like to do with documentFile.
            // Here I do deletion to provide an example.


            if (documentFile.delete()) {// if delete file succeed
                // Remove information related to your media from ContentResolver,
                // which documentFile.delete() didn't do the trick for me.
                // Must do it otherwise you will end up with showing an empty
                // ImageView if you are getting your URLs from MediaStore.


                getApplicationContext().sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(selectedFile)));
//                              Methods.removeMedia(this,selectedFile.getPath());

                if (deleteSingleFileCall){
                    Constant.allMemoryVideoList.remove(videoPosition);
                    adapter.notifyItemRemoved(videoPosition);
                    deleteSingleFileCall = false;
                }

                /*update the playback record to
                 * getFileName() contain file.getName()*/
                for (int i = 0; i < Constant.filesPlaybackHistory.size(); i++) {
                    if ((selectedFile.getName()).equals(Constant.filesPlaybackHistory.get(i).getFileName())) {
                        Constant.filesPlaybackHistory.remove(i);
                        break;
                    }
                }

                //save the playback history
                Paper.book().write("playbackHistory", Constant.filesPlaybackHistory);

            }
        }
    }

这就是我加载内部和外部存储文件的方式。

StorageUtil 是库https://github.com/hendrawd/StorageUtil

String[] allPath = StorageUtil.getStorageDirectories(this);
private File directory;
for (String path: allPath){
    directory = new File(path);
    Methods.load_Directory_Files(directory);
}

以下数组列表中的所有已加载文件。

//all the directory that contains files
public static ArrayList<File> directoryList = null;
//list of all files (internal and external)
public static ArrayList<FilesInfo> allMemoryVideoList = new ArrayList<>();

FilesInfo:包含有关文件的所有信息,例如缩略图、持续时间、目录、新的或之前播放的、如果播放则最后播放位置等

加载目录文件()

public static void  load_Directory_Files(File directory) {

    //Get all file in storage
    File[] fileList = directory.listFiles();
    //check storage is empty or not
    if(fileList != null && fileList.length > 0)
    {
        for (int i=0; i<fileList.length; i++)
        {
            boolean restricted_directory = false;
            //check file is directory or other file
            if(fileList[i].isDirectory())
            {
                for (String path : Constant.removePath){
                    if (path.equals(fileList[i].getPath())) {
                        restricted_directory = true;
                        break;
                    }
                }
                if (!restricted_directory)
                    load_Directory_Files(fileList[i]);
            }
            else
            {
                String name = fileList[i].getName().toLowerCase();
                for (String ext : Constant.videoExtensions){
                    //Check the type of file
                    if(name.endsWith(ext))
                    {
                        //first getVideoDuration
                        String videoDuration = Methods.getVideoDuration(fileList[i]);
                        long playbackPosition;
                        long percentage = C.TIME_UNSET;
                        FilesInfo.fileState state;

                        /*First check video already played or not. If not then state is NEW
                         * else load playback position and calculate percentage of it and assign it*/

                        //check it if already exist or not if yes then start from there else start from start position
                        int existIndex = -1;
                        for (int j = 0; j < Constant.filesPlaybackHistory.size(); j++) {
                            String fListName = fileList[i].getName();
                            String fPlaybackHisName = Constant.filesPlaybackHistory.get(j).getFileName();
                            if (fListName.equals(fPlaybackHisName)) {
                                existIndex = j;
                                break;
                            }
                        }

                        try {
                            if (existIndex != -1) {
                                //if true that means file is not new
                                state = FilesInfo.fileState.NOT_NEW;
                                //set playbackPercentage not playbackPosition
                                MediaMetadataRetriever retriever = new MediaMetadataRetriever();
                                retriever.setDataSource(fileList[i].getPath());
                                String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
                                retriever.release();

                                int duration = Integer.parseInt(time);
                                playbackPosition = Constant.filesPlaybackHistory.get(existIndex).getPlaybackPosition();

                                if (duration > 0)
                                    percentage = 1000L * playbackPosition / duration;
                                else
                                    percentage = C.TIME_UNSET;

                            }
                            else
                                state = FilesInfo.fileState.NEW;

                            //playbackPosition have value in percentage
                            Constant.allMemoryVideoList.add(new FilesInfo(fileList[i],
                                    directory,videoDuration, state, percentage, storageType));

                            //directory portion
                            currentDirectory = directory.getPath();
                            unique_directory = true;

                            for(int j=0; j<directoryList.size(); j++)
                            {
                                if((directoryList.get(j).toString()).equals(currentDirectory)){
                                    unique_directory = false;
                                }
                            }

                            if(unique_directory){
                                directoryList.add(directory);
                            }

                            //When we found extension from videoExtension array we will break it.
                            break;

                        }catch (Exception e){
                            e.printStackTrace();
                            Constant.allMemoryVideoList.add(new FilesInfo(fileList[i],
                                    directory,videoDuration, FilesInfo.fileState.NOT_NEW, C.TIME_UNSET, storageType));
                        }

                    }
                }
            }
        }
    }
    Constant.directoryList = directoryList;
}

图片 这样读者就可以很容易地理解发生了什么。

在此处输入图像描述

标签: delete-filestorage-access-frameworkandroid-storage

解决方案


推荐阅读