修改文件:
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()判断会失败。
需要使完整的路径合法,否则无法接收文件。