无法在奥利奥上选择文件

Posted

技术标签:

【中文标题】无法在奥利奥上选择文件【英文标题】:Unable to pick file on Oreo 【发布时间】:2018-11-30 08:45:33 【问题描述】:

android Nougat 及以下版本中,我可以使用以下代码简单地在我的存储中获取一些文件:

Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.setType("*/*.jpg");
chooseFile = Intent.createChooser(chooseFile, "Choose a file");
startActivityForResult(chooseFile, 111);

并使用 :

获取文件路径
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 111 && resultCode == RESULT_OK && data.getData() != null)
       String path = data.getData().getPath();


但在 Android Oreo 上,这不起作用。文件选择器正在显示,但我什至无法使用默认文件选择器选择文件。一开始我以为这和permission有关。但是当我在运行时添加了对外部存储的读写权限并授予后,这个问题仍然存在。

【问题讨论】:

"The file picker is showing up, but I cannot even pick the file using the default file picker." 为什么不能? onActivityResult() 没有被调用还是什么?或resultCode != RESULT_OK ? 类似于列表视图或按钮,但没有 onClick 方法。我根本无法单击它,并且永远不会调用 onActivityResult。 我不知道你在说什么……什么按钮?什么点击? 按钮和列表视图是隐喻。我只是无法单击设备上的文件(默认)文件选择器 这个问题是因为最近的对话引起的吗? 【参考方案1】:

由于 OREO 上的默认文件选择器很麻烦,目前我正在使用自定义类来选择文件或目录。另一种解决方案是您可以使用 ES 文件资源管理器等,但并非所有用户都拥有它,主要问题仍然存在。

public class FileChooser 

    private Activity activity;
    private Item[] fileList;
    private File path;

    private boolean rootDir  = true; //check if the current directory is rootDir
    private boolean pickFile = true; //flag to get directory or file

    private String title = "";
    private String upTitle = "Up";
    private String positiveTitle = "Choose Path";
    private String negativeTitle = "Cancel";

    private ListAdapter adapter;
    private ArrayList<String> str = new ArrayList<>(); //Stores names of traversed directories, to detect rootDir
    private Listener listener;

    /**
     * @param pickFile true for file picker and false for directory picker
     * */
    public FileChooser(Activity activity, boolean pickFile, Listener fileChooserListener) 
        this.activity = activity;
        this.pickFile = pickFile;
        this.listener = fileChooserListener;
        title = pickFile ? "Choose File" : "Choose Directory";
        path = new File(String.valueOf(Environment.getExternalStorageDirectory()));
    


    /**
     * The view of your file picker
     * */
    public void openDirectory() 
        loadFileList();
        AlertDialog.Builder builder = new AlertDialog.Builder(activity, AlertDialog.THEME_DEVICE_DEFAULT_DARK);
        if (fileList == null)
            builder.create();

        builder.setTitle(title + "\n" + path.toString());
        builder.setAdapter(adapter, new DialogInterface.OnClickListener() 
            @Override
            public void onClick(DialogInterface dialog, int position) 
                String chosenFile = fileList[position].file;
                File selectedFile = new File(path + File.separator + chosenFile);

                if (selectedFile.isDirectory())  // user click on folder
                    rootDir = false;
                    str.add(chosenFile); // Adds chosen directory to list
                    path = selectedFile;
                    openDirectory();
                
                else if (chosenFile.equalsIgnoreCase(upTitle) && !selectedFile.exists())  // 'up' was clicked
                    String s = str.remove(str.size() - 1); // present directory
                    path = new File(
                            path.toString().substring(0, path.toString().lastIndexOf(s))); // exclude present directory
                    if (str.isEmpty()) // no more directories in the list, rootDir
                        rootDir = true;
                    openDirectory();

                
                else if (listener != null && pickFile)
                    listener.onSelectedPath(selectedFile.getAbsolutePath());

            
        );

        if (!pickFile) 
            builder.setPositiveButton(positiveTitle, new DialogInterface.OnClickListener() 
                @Override
                public void onClick(DialogInterface dialogInterface, int i) 
                    if (listener != null)
                        listener.onSelectedPath(path.getPath());
                
            );
        
        builder.setNegativeButton(negativeTitle, null);
        builder.show();
    

    /**
     * Setup your file picker data
     * */
    private void loadFileList() 
        fileList = null;
        if (path.exists()) 
            FilenameFilter filter = new FilenameFilter() 
                @Override
                public boolean accept(File dir, String filename) 
                    File file = new File(dir, filename);
                    // Filters based on whether the file is hidden or not
                    return ((pickFile && file.isFile()) || file.isDirectory()) && !file.isHidden();
                
            ;

            String[] fList = path.list(filter); //set filter
            if (fList != null) 
                fileList = new Item[fList.length];
                for (int i = 0; i < fList.length; i++)
                    fileList[i] = new Item(fList[i], new File(path, fList[i]).isDirectory() ?
                            R.drawable.ic_folder : R.drawable.ic_file); //set icon, directory or file

                if (!rootDir) 
                    Item temp[] = new Item[fileList.length + 1];
                    System.arraycopy(fileList, 0, temp, 1, fileList.length);
                    temp[0] = new Item(upTitle, R.drawable.ic_undo);
                    fileList = temp;
                
            

         else
            path = new File(String.valueOf(Environment.getExternalStorageDirectory()));

        try 
            adapter = new ArrayAdapter<Item>(activity,
                    android.R.layout.select_dialog_item, android.R.id.text1,
                    fileList) 
                @NonNull
                @Override
                public View getView(int position, View convertView, @NonNull ViewGroup parent) 
                    // creates view
                    View view = super.getView(position, convertView, parent);
                    TextView textView = view.findViewById(android.R.id.text1);
                    textView.setTextColor(Color.WHITE);

                    // put the image on the text view
                    textView.setCompoundDrawablesWithIntrinsicBounds(fileList[position].icon, 0, 0, 0);

                    // add margin between image and text (support various screen densities)
                    int dp5 = (int) (5 * activity.getResources().getDisplayMetrics().density + 0.5f);
                    textView.setCompoundDrawablePadding(dp5);

                    return view;
                
            ;
         catch (Exception e) 
            e.printStackTrace();
        
    

    private class Item 
        public String file;
        public int icon;

        private Item(String file, Integer icon) 
            this.file = file;
            this.icon = icon;
        

        @Override
        public String toString() 
            return file;
        
    

    public interface Listener 
        void onSelectedPath(String path);
    


【讨论】:

以上是关于无法在奥利奥上选择文件的主要内容,如果未能解决你的问题,请参考以下文章

在语言选择上选择适当的 .rc 文件

无法在 IOS 和 Android 移动设备上选择文件

在android上选择文件夹对话框?

奥利奥通知栏圆形图标

即时应用在奥利奥设备上未激活

无法在 iOS 8 上选择联系人