Android Bluetooth 文件接收路径修改方法

修改文件:

packages/apps/Bluetooth/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfo.java

相关代码片段:

    public static BluetoothOppReceiveFileInfo generateFileInfo(Context context, int id) {

        ContentResolver contentResolver = context.getContentResolver();
        Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + id);
        String filename = null, hint = null, mimeType = null;
        long length = 0;
        Cursor metadataCursor = null;
        try {
            metadataCursor = contentResolver.query(contentUri, new String[] {
                BluetoothShare.FILENAME_HINT, BluetoothShare.TOTAL_BYTES, BluetoothShare.MIMETYPE
                }, null, null, null);
        } catch (SQLiteException e) {
            if (metadataCursor != null) {
                metadataCursor.close();
            }
            metadataCursor = null;
            Log.e(Constants.TAG, "generateFileInfo: " + e);
        } catch (CursorWindowAllocationException e) {
            metadataCursor = null;
            Log.e(Constants.TAG, "generateFileInfo: " + e);
        }

        if (metadataCursor != null) {
            try {
                if (metadataCursor.moveToFirst()) {
                    hint = metadataCursor.getString(0);
                    length = metadataCursor.getLong(1);
                    mimeType = metadataCursor.getString(2);
                }
            } finally {
                metadataCursor.close();
                if (V) Log.v(Constants.TAG, "Freeing cursor: " + metadataCursor);
                metadataCursor = null;
            }
        }

        File base = null;
        StatFs stat = null;

        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            String root = Environment.getExternalStorageDirectory().getPath();
            base = new File(root + Constants.DEFAULT_STORE_SUBDIR);
            if (!base.isDirectory() && !base.mkdir()) {
                if (D) Log.d(Constants.TAG, "Receive File aborted - can't create base directory "
                            + base.getPath());
                return new BluetoothOppReceiveFileInfo(BluetoothShare.STATUS_FILE_ERROR);
            }
            stat = new StatFs(base.getPath());
        } else {
            if (D) Log.d(Constants.TAG, "Receive File aborted - no external storage");
            return new BluetoothOppReceiveFileInfo(BluetoothShare.STATUS_ERROR_NO_SDCARD);
        }

        /*
         * Check whether there's enough space on the target filesystem to save
         * the file. Put a bit of margin (in case creating the file grows the
         * system by a few blocks).
         */
        if (stat.getBlockSize() * ((long)stat.getAvailableBlocks() - 4) < length) {
            if (D) Log.d(Constants.TAG, "Receive File aborted - not enough free space");
            return new BluetoothOppReceiveFileInfo(BluetoothShare.STATUS_ERROR_SDCARD_FULL);
        }

        filename = choosefilename(hint);
        if (filename == null) {
            // should not happen. It must be pre-rejected
            return new BluetoothOppReceiveFileInfo(BluetoothShare.STATUS_FILE_ERROR);
        }
        String extension = null;
        int dotIndex = filename.lastIndexOf(".");
        if (dotIndex < 0) {
            if (mimeType == null) {
                // should not happen. It must be pre-rejected
                return new BluetoothOppReceiveFileInfo(BluetoothShare.STATUS_FILE_ERROR);
            } else {
                extension = "";
            }
        } else {
            extension = filename.substring(dotIndex);
            filename = filename.substring(0, dotIndex);
        }

        if ((filename != null) && (filename.getBytes().length > OPP_LENGTH_OF_FILE_NAME)) {
          /* Including extn of the file, Linux supports 255 character as a maximum length of the
           * file name to be created. Hence, Instead of sending OBEX_HTTP_INTERNAL_ERROR,
           * as a response, truncate the length of the file name and save it. This check majorly
           * helps in the case of vcard, where Phone book app supports contact name to be saved
           * more than 255 characters, But the server rejects the card just because the length of
           * vcf file name received exceeds 255 Characters.
           */
          try {
              byte[] oldfilename = filename.getBytes("UTF-8");
              byte[] newfilename = new byte[OPP_LENGTH_OF_FILE_NAME];
              System.arraycopy(oldfilename, 0, newfilename, 0, OPP_LENGTH_OF_FILE_NAME);
              filename = new String(newfilename, "UTF-8");
          } catch (UnsupportedEncodingException e) {
              Log.e(Constants.TAG, "Exception: " + e);
          }
          if (D) Log.d(Constants.TAG, "File name is too long. Name is truncated as: " + filename);
        }

        filename = base.getPath() + File.separator + filename;
        // Generate a unique filename, create the file, return it.
        String fullfilename = chooseUniquefilename(filename, extension);

        if (!safeCanonicalPath(fullfilename)) {
            // If this second check fails, then we better reject the transfer
            return new BluetoothOppReceiveFileInfo(BluetoothShare.STATUS_FILE_ERROR);
        }
        if (V) Log.v(Constants.TAG, "Generated received filename " + fullfilename);

        if (fullfilename != null) {
            try {
                new FileOutputStream(fullfilename).close();
                int index = fullfilename.lastIndexOf('/') + 1;
                // update display name
                if (index > 0) {
                    String displayName = fullfilename.substring(index);
                    if (V) Log.v(Constants.TAG, "New display name " + displayName);
                    ContentValues updateValues = new ContentValues();
                    updateValues.put(BluetoothShare.FILENAME_HINT, displayName);
                    context.getContentResolver().update(contentUri, updateValues, null, null);

                }
                return new BluetoothOppReceiveFileInfo(fullfilename, length, new FileOutputStream(
                        fullfilename), 0);
            } catch (IOException e) {
                if (D) Log.e(Constants.TAG, "Error when creating file " + fullfilename);
                return new BluetoothOppReceiveFileInfo(BluetoothShare.STATUS_FILE_ERROR);
            }
        } else {
            return new BluetoothOppReceiveFileInfo(BluetoothShare.STATUS_FILE_ERROR);
        }

    }

    private static boolean safeCanonicalPath(String uniqueFileName) {
        try {
            File receiveFile = new File(uniqueFileName);
            if (sDesiredStoragePath == null) {
                sDesiredStoragePath = Environment.getExternalStorageDirectory().getPath() +
                    Constants.DEFAULT_STORE_SUBDIR;
            }
            String canonicalPath = receiveFile.getCanonicalPath();

            // Check if canonical path is complete - case sensitive-wise
            if (!canonicalPath.startsWith(sDesiredStoragePath)) {
                return false;
            }

	    	return true;
        } catch (IOException ioe) {
            // If an exception is thrown, there might be something wrong with the file.
            return false;
        }
    }

修改方法:

root 就是存储的根目录。

如果需要将其修改之外部存储,修改此处的赋值即可。

如果需要修改子目录,修改base的拼接赋值即可。

此处修改需要注意,如果修改root或者base,则需要给sDesiredStoragePath重新赋值,使其一致,否则会导致safeCanonicalPath()判断会失败。

需要使完整的路径合法,否则无法接收文件。

时间: 2025-01-02 05:45:38

Android Bluetooth 文件接收路径修改方法的相关文章

Android获取文件夹路径 /data/data/

首先内部存储路径为/data/data/youPackageName/,下面讲解的各路径都是基于你自己的应用的内部存储路径下.所有内部存储中保存的文件在用户卸载应用的时候会被删除. 一. files1. Context.getFilesDir(),该方法返回/data/data/youPackageName/files的File对象.2. Context.openFileInput()与Context.openFileOutput(),只能读取和写入files下的文件,返回的是FileInput

asp.net 客户端上传文件全路径获取方法

asp.net  获取客户端上传文件全路径方法: eg:F:\test\1.doc 基于浏览器安全问题,浏览器将屏蔽获取客户端文件全路径的方法,只能获取到文件的文件名,如果需要获取全路径则需要另想其他方法 如下提供两种方法: 方法1:工具 -> Internet选项 -> 安全 -> 自定义级别 -> 找到“其他”中的“将本地文件上载至服务器时包含本地目录路径”,选中“启用”即可. 方法2: function getPath() { //获取file 控件对象 var obj =

VC 获取指定文件夹路径的方法小结

VC获取指定文件夹路径 flyfish  2010-3-5 一 使用Shell函数 1 获取应用程序的安装路径 TCHAR buf[_MAX_PATH];SHGetSpecialFolderPath(NULL,buf,CSIDL_PROGRAM_FILES,NULL);AfxMessageBox(buf); 2 获取应用程序数据路径的文件夹 TCHAR bufApplicateData[_MAX_PATH];SHGetSpecialFolderPath(NULL,bufApplicateData

Xcode增加头文件搜索路径的方法

Xcode增加头文件搜索路径的方法 以C++工程为例: 在Build Settings 页面中的Search Paths一节就是用来设置头文件路径. 相关的配置项用红框框起来了,共有三个配置项: Header Search Paths User Header Search Paths Always Search User Paths xcode的头文件路径有两种设置,一种是Header Search Paths,另一种是User Header Search Paths.两者对应两个include

Oculus Store游戏下载默认路径修改方法

最近在测试一款VR游戏,所以在硬件设备上选择了HTC Vive和Oculus两款眼镜.相对而言,HTC安装比较人性化:支持自定义安装路径,而且可在界面更改应用程序下载位置,如图所示: 这下替我节省了不少系统盘空间!但是Oculus安装个人感觉有点恶心了,默认安装在C盘而且不能修改.可能之前已经装了SteamVR,所以直接用ModuoVR.exe安装时中途各种问题,迫不得已干脆用OculusSetup.exe进行在线安装(这个过程有点痛苦),装好后还是在C盘,关键Store中的设置选项没有找到下载

visual studio C++ 手工管理头文件包含路径的方法

这里以VS2010为例,说明如何通过自定义项目属性来手工管理VC++目录. 第一步:打开一个VC++工程. 第二步: 选择视图菜单下的属性管理器. 第三步:右键点击我们的工程,选择"添加新项目属性表". 第四步:输入自己想好的名字,注意目录不要修改,建议放到自己的工程目录下,这个是默认的. 第五步:点击添加,回到我们的工程目录,应该能找到bt.props这个文件. 第六步:用编辑工具打开这个文件,它是一个xml文件,可以自己选择好用的编辑工具. <?xml version=&qu

Office 2016安装路径修改方法

Office 2016安装程序不仅不能选择要安装的组件,而且连安装路径都不能选,只能默认安装到C盘,根本就不能选择安装到D盘.E盘什么的,真是好霸道的总裁.不过这难不懂爱折腾的大神们,下面下载吧给出一个Office 2016自定义位置安装方法. Office 2016安装路径修改步骤 1.安装前,按Ctrl+R键打开注册表编辑器,然后定位到如下位置: HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersion 修改为你希望的安装路径. Pro

MySQL参数文件及参数修改方法

MySQL参数文件: MySQL数据库初始化参数由参数文件来设置,如果没有设置参数文件,mysql就按照系统中参数的默认值来启动. 在windows和linux上,参数文件可以被放在多个位置,数据库启动时按照不同的顺序来搜索,如果多个位置都有参数文件,则搜索顺序靠后的参数文件中的参数将覆盖前的参数. Windows上参数文件读取顺序 Linux上参数文件读取顺序 修改mysql参数的方法:

android 当文件夹路径从n层按back键退回到n-19层的时候,file manager自动退出

当文件夹路径从n层按back键退回到n-19层的时候,file manager自动退出,比如在63层按back 键退回到44层的时候,file manager自动退出. 1.FileManager默认设计, FileManager种只记录最多20条操作路径的记录, 如果超出就会把最早加入的记录删除. 贵司可以参考alps/mediatek/packages/apps/FileManager/src/com/mediatek/filemanager/FileInfoManager.java中这部分