Android开发-纯按键操控文件浏览器

作者:袖梨 2026-05-30

本文分享一个教育平板项目的按键交互文件浏览器实现方案,通过纯DPAD按键操作实现本地音频资源的分层浏览功能。

Android开发纯按键文件浏览器

  1. 硬件:低端 TV 盒子/,配红外遥控器,无触屏设备
  2. 内容:TF 卡 /听力 目录下,按年级分文件夹,叶子节点是 .mp3 或自定义加密音频
  3. 核心诉求
    1. 上下键循环选中(到顶再按上回到底部)
    2. 确定键进入文件夹或播放
    3. 返回键回到上级目录,且焦点停留在刚才进入的那个文件夹上(这是 TV 交互的硬需求)
    4. 文件过滤:隐藏系统目录,按年级名排序

1、定义变量

TextView title; //标题
RecyclerView recyclerView; //列表
UnitAdapter mUnitAdapter; //适配器
ArrayList> unitList; //列表数据
LinearLayout ll_no_data; //无数据view
boolean isNoData = false; //无数据标识String sDcardDir; //根目录名称
String cur_name; //当前目录名称
String cur_path; //当前目录路径
String last_title; //上次标题名称
int last_mPos = 0; //上次选择位置
int first_mPos = 0; //第一次点击位置String root_name = ""; //一级目录名称
String title_str = "";

2、初始化和加载

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_list);        title_str = getIntent().getStringExtra("title"); //传入的标题
        title = findViewById(R.id.title);
        if (!TextUtils.isEmpty(title_str)) {
            root_name = title_str;
        }
        title.setText(root_name);
        sDcardDir = SDCardUtils.getTfStorageDirectory(this) + "/听力"; //根目录路径        recyclerView = findViewById(R.id.recyclerView);
        ll_no_data = findViewById(R.id.ll_no_data);
        title.setTextColor(getResources().getColor(R.color.col_1E2736));
        
        unitList = new ArrayList<>();
        mUnitAdapter = new UnitAdapter(this, new View.OnClickListener() {
            @Override
            public void onClick(View v) {// item点击
                mUnitAdapter.mPosSomeTime = ((int) v.getTag());
                Log.d("TAG", "((int) v.getTag()---> " + ((int) v.getTag()));
                mUnitAdapter.notifyDataSetChanged();
                ClickSelect(); //选择目录或文件
            }
        });
        recyclerView.setAdapter(mUnitAdapter);
        verifyStoragePermissions(this); //权限请求
    }    /**
	 * 获取tf卡根目录
	 * @param context
	 * @return
	 */
	public static String getTfStorageDirectory(Context context) {
		String tfDir = null;
		StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
		Class<?> smc = sm.getClass();
		
		try {
			Method getPaths = smc.getMethod("getVolumePaths", new  Class[0]);
			String[] paths = (String[])getPaths.invoke(sm, new  Object[]{});
			if (paths.length >= 2) {
				tfDir = paths[1];
			}
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return tfDir;
	}private static final int REQUEST_EXTERNAL_STORAGE = 1;
    private static String[] PERMISSIONS_STORAGE = {
            "android.permission.READ_EXTERNAL_STORAGE",
            "android.permission.WRITE_EXTERNAL_STORAGE"};    //然后通过一个函数来申请
    public static void verifyStoragePermissions(Activity activity) {
        try {
            //检测是否有写的权限
            int permission = ActivityCompat.checkSelfPermission(activity,
                    "android.permission.WRITE_EXTERNAL_STORAGE");
            if (permission != PackageManager.PERMISSION_GRANTED) {
                // 没有写的权限,去申请写的权限,会弹出对话框
                ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
            }else{
                findData(sDcardDir,false); //查找目录
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

3、查找目录/文件 、排序并显示

//搜索数据方法 传入目录 和 是否返回标识
private void findData(String sDcardDir, boolean isReturn) {
        if (new File(sDcardDir).exists()) {//文件存在
            Log.e("TAG", "222 path=" + sDcardDir);
            File[] files = new File(sDcardDir).listFiles();
            SearchFile(files);
            Log.e("TAG", "last_mPos=" + last_mPos);//上一个目录的索引
            if (isReturn){
                mUnitAdapter.mPosSomeTime = last_mPos;
                if(title.getText().toString().equals(root_name)){
                     mUnitAdapter.mPosSomeTime = first_mPos;
                }
            }else {
                mUnitAdapter.mPosSomeTime = 0;
            }
            Log.e("TAG", "mUnitAdapter.mPosSomeTime=" + mUnitAdapter.mPosSomeTime);
            if(unitList!=null && unitList.size()>0){
                ListSort(unitList);//排序
                mUnitAdapter.mCurPos = -1;
                mUnitAdapter.updateData(unitList); //刷新列表
                recyclerView.scrollToPosition(mUnitAdapter.mPosSomeTime);
            }else {
                isNoData = true;
            }
        } else {
            isNoData = true;
            toast("找不到相关文件");
        }
        //隐藏或显示  无数据view/列表
        ll_no_data.setVisibility(isNoData?View.VISIBLE:View.GONE);
        recyclerView.setVisibility(isNoData?View.GONE:View.VISIBLE);
    }private void SearchFile(File[] files) { //搜索文件
        unitList.clear(); //清空上次搜索的文件列表
        for (File file : files) {
            if (file.isDirectory()) {
                if (file.getName().contains("XX") || file.getName().contains("语文")) {               
                     //自定义拦截条件 不显示这个文件
                      continue;
                    }
                HashMap<String, String> map = new HashMap();//创建文件对象
                if (file.getName().equals("英语"))) { //自定义显示文件名称
                    map.put("item", "XXX");
                } else {
                    if (file.getName().contains("_")) { //截取_
                        map.put("item", file.getName().substring(file.getName().indexOf("_") + 1));
                    } else {
                        map.put("item", file.getName());//文件名称
                    }
                }
                map.put("path_name", file.getPath());//文件路径
                map.put("file_type", "file");//文件夹类型
                unitList.add(map);//加入列表            } else if (file.isFile()) {
                String path = file.getPath();
                String data_type = "";
                if (path.endsWith(".XXX")) {//查找指定扩展名的文件
                        data_type = "xxx";
                    } else if (path.endsWith(".AAA")) {
                        data_type = "aaa";
                    } else if (path.endsWith(".BBB")) {
                        data_type = "bbb";
                    }                 if (!TextUtils.isEmpty(data_type)) {
                    HashMap<String, String> map = new HashMap();
                    map.put("item", file.getName()); 
                    map.put("path_name", file.getPath());
                    map.put("data_type", data_type);
                    map.put("file_type", "book");//具体文件类型  比如书本
                    unitList.add(map);
                }
            }
        }
        if (unitList == null || unitList.size() == 0) {
            toast("找不到相关文件");
            mUnitAdapter.updateData(unitList);
            isNoData = true;
        }else {
            isNoData = false;
        }
    }//按年级排序
private ArrayList<HashMap<String, String>> ListSort(ArrayList> list){
        if(list.get(0).get("file_type").equals("file")){
            for (int i = 0; i < list.size(); i++) {
                String item=list.get(i).get("item");
                if (TextUtils.isEmpty(item)){
                    break;
                }
                if(item.contains("一年级") || item.contains("1年级") || item.contains("人民教育")){
                    list.get(i).put("index", "1");
                }else if(item.contains("二年级") || item.contains("2年级")){
                    list.get(i).put("index", "2");
                }else if(item.contains("三年级") || item.contains("3年级")){
                    list.get(i).put("index", "3");
                }else if(item.contains("四年级") || item.contains("4年级")){
                    list.get(i).put("index", "4");
                }else if(item.contains("五年级")  || item.contains("5年级")){
                    list.get(i).put("index", "5");
                }else if(item.contains("六年级") || item.contains("6年级")){
                    list.get(i).put("index", "6");
                }else if(item.contains("七年级") || item.contains("7年级")){
                    list.get(i).put("index", "7");
                }else if(item.contains("八年级") || item.contains("8年级")){
                    list.get(i).put("index", "8");
                }else if(item.contains("九年级") || item.contains("9年级")){
                    list.get(i).put("index", "9");
                }else {
                    list.get(i).put("index", (i+10)+"");
                }
            }            Comparator<HashMap<String, String>> comparator = (details1, details2) -> {
                if (details1.get("index") != null && (Integer.parseInt(details1.get("index")) > Integer.parseInt(details2.get("index")))) {
                    return 1;
                } else if (details1.get("index") != null && (Integer.parseInt(details1.get("index")) < Integer.parseInt(details2.get("index")))) {
                    return -1;
                } else {
                    

相关文章

精彩推荐