我已经花了很长时间才弄清楚如何在我的三星Galaxy上写入SDCard。我尝试过很多方法但它似乎仍然没有用。我已经跟踪了这段代码并且似乎执行了(无论SDCard是否插入手机中)。问题是我永远都找不到它应该写的文件。任何人都可以帮忙吗?
if (isExternalStorageWritable()) {
try {
File myFile = new File("/sdcard/WorkoutData.txt");
myFile.createNewFile();
FileOutputStream fOut = new FileOutputStream(myFile);
OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
for (WorkoutData iterator: workouts) {
myOutWriter.append(iterator.toString());
Log.d(TAG, iterator.toString());
}
myOutWriter.close();
fOut.close();
Toast.makeText(getBaseContext(),
"Done writing SD 'WorkoutData.txt'",
Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(getBaseContext(), e.getMessage(),
Toast.LENGTH_LONG).show();
}
}
答案 0 :(得分:0)
我的三星Galaxy S4遇到了同样的问题。我已经检查过,外部存储是可用的和可写的。但无法创建文件夹或文件。
然后我尝试使用下面的代码来创建/删除文件夹。没关系。但无法创建文件,EACCES(Permission denied)发生了。希望这段代码可以帮到你。
package com.example.truongphuquoc;
public class MediaFile {
private final File file;
private final ContentResolver contentResolver;
private final Uri filesUri;
private final Uri imagesUri;
public MediaFile(ContentResolver contentResolver, File file) {
this.file = file;
this.contentResolver = contentResolver;
filesUri = MediaStore.Files.getContentUri("external");
imagesUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
}
/**
* Deletes the file. Returns true if the file has been successfully deleted or otherwise does not exist. This operation is not
* recursive.
*/
public boolean delete()
throws IOException {
if (!file.exists()) {
return true;
}
boolean directory = file.isDirectory();
if (directory) {
// Verify directory does not contain any files/directories within it.
String[] files = file.list();
if (files != null && files.length > 0) {
return false;
}
}
String where = MediaStore.MediaColumns.DATA + "=?";
String[] selectionArgs = new String[] { file.getAbsolutePath() };
// Delete the entry from the media database. This will actually delete media files (images, audio, and video).
contentResolver.delete(filesUri, where, selectionArgs);
if (file.exists()) {
// If the file is not a media file, create a new entry suggesting that this location is an image, even
// though it is not.
ContentValues values = new ContentValues();
values.put(MediaStore.Files.FileColumns.DATA, file.getAbsolutePath());
contentResolver.insert(imagesUri, values);
// Delete the created entry, such that content provider will delete the file.
contentResolver.delete(filesUri, where, selectionArgs);
}
return !file.exists();
}
public File getFile() {
return file;
}
/**
* Creates a new directory. Returns true if the directory was successfully created or exists.
*/
public boolean mkdir()
throws IOException {
if (file.exists()) {
return file.isDirectory();
}
ContentValues values;
Uri uri;
// Create a media database entry for the directory. This step will not actually cause the directory to be created.
values = new ContentValues();
values.put(MediaStore.Files.FileColumns.DATA, file.getAbsolutePath());
contentResolver.insert(filesUri, values);
// Create an entry for a temporary image file within the created directory.
// This step actually causes the creation of the directory.
values = new ContentValues();
values.put(MediaStore.Files.FileColumns.DATA, file.getAbsolutePath() + "/temp.jpg");
uri = contentResolver.insert(imagesUri, values);
// Delete the temporary entry.
contentResolver.delete(uri, null, null);
return file.exists();
}
public boolean mkFile(){
if (file.exists() || file.isDirectory()) {
return false;
}
ContentValues values;
// Create a media database entry for the directory. This step will not actually cause the directory to be created.
values = new ContentValues();
values.put(MediaStore.Files.FileColumns.DATA, file.getAbsolutePath());
contentResolver.insert(filesUri, values);
return file.exists();
}
/**
* Returns an OutputStream to write to the file. The file will be truncated immediately.
*/
public OutputStream write()
throws IOException {
if (file.exists() && file.isDirectory()) {
throw new IOException("File exists and is a directory.");
}
// Delete any existing entry from the media database.
// This may also delete the file (for media types), but that is irrelevant as it will be truncated momentarily in any case.
String where = MediaStore.MediaColumns.DATA + "=?";
String[] selectionArgs = new String[] { file.getAbsolutePath() };
contentResolver.delete(filesUri, where, selectionArgs);
ContentValues values = new ContentValues();
values.put(MediaStore.Files.FileColumns.DATA, file.getAbsolutePath());
Uri uri = contentResolver.insert(filesUri, values);
if (uri == null) {
// Should not occur.
throw new IOException("Internal error.");
}
return contentResolver.openOutputStream(uri);
}
}
答案 1 :(得分:0)
可能,这是由于“外部”存储隔离......
在AndroidManifest.xml
中,包括:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
例如,在MyApp.java
中的某个位置,您想要提取其日志并将其保存到默认外部SD卡上的“file.log”中:
String PACKAGE_NAME = MyApp.class.getPackage().getName();
String KEY_DIRECTORY_SELECTED = PACKAGE_NAME + ".DIRECTORY_SELECTED";
SharedPreference preferences = getSharedPreferences(PACKAGE_NAME, Context.MODE_PRIVATE);
private String extractLogToFile()
{
final String defaultFolder = preferences.getString(KEY_DIRECTORY_SELECTED,
Environment.getExternalStorageDirectory().toString()) +
System.getProperty("file.separator");
final String FILENAME = defaultFolder + "file.log";
PackageManager manager = this.getPackageManager();
PackageInfo info = null;
try {
info = manager.getPackageInfo (this.getPackageName(), 0);
} catch (NameNotFoundException e2) {
}
String model = Build.MODEL;
if (!model.startsWith(Build.MANUFACTURER))
model = Build.MANUFACTURER + " " + model;
// Make file name - file must be saved to external storage or it wont be readable by
// the email app.
//String path = defaultFolder;
String fullName = FILENAME;
// Extract to file.
File file = new File (fullName);
InputStreamReader reader = null;
FileWriter writer = null;
try
{
// For Android 4.0 and earlier, you will get all app's log output, so filter it to
// mostly limit it to your app's output. In later versions, the filtering isn't needed.
String cmd = (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) ?
"logcat -d -v time MyApp:v dalvikvm:v System.err:v *:s" :
"logcat -d -v time";
// get input stream
Process process = Runtime.getRuntime().exec(cmd);
reader = new InputStreamReader (process.getInputStream());
// write output stream
writer = new FileWriter (file);
writer.write ("Android version: " + Build.VERSION.SDK_INT + "\n");
writer.write ("Device: " + model + " (S/N: "+ Tools.getDeviceSerialNumber()+")" + "\n");
writer.write ("App version: " + (info == null ? "(null)" : info.versionName) + "\n");
char[] buffer = new char[10000];
do
{
int n = reader.read (buffer, 0, buffer.length);
if (n == -1)
break;
writer.write (buffer, 0, n);
} while (true);
reader.close();
writer.close();
}
catch (IOException e)
{
if (writer != null)
try {
writer.close();
} catch (IOException e1) {
}
if (reader != null)
try {
reader.close();
} catch (IOException e1) {
}
// You might want to write a failure message to the log here.
return null;
}
return fullName;
}