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