2014-10-09 146 views
0

我一直在尝试很长时间才弄清楚如何在我的Samsung Galaxy上写入SD卡。我已经尝试了很多方法,但它似乎仍然没有工作。我已经追踪了这段代码,它似乎可以执行(无论手机中是否插入了SDCard)。问题是我永远无法找到它应该写的文件。任何人都可以帮忙吗?写入SD卡

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

我觉得'isExternalStorageWritable()'在你的情况下返回'false'。 确保你在你的应用清单中包含了这个'android.permission.WRITE_EXTERNAL_STORAGE'。你可以发布logcat吗? – Kishore 2014-10-09 03:11:57

+0

在清单文件中设置权限 2014-10-09 03:30:23

+0

'文件extStorage = Environment.getExternalStorageDirectory(); File myFile = new File(extStorage,“WorkoutData.txt”);'看看是否有帮助 – Neo 2014-10-09 04:58:37

回答

0

我与我的三星Galaxy S4有同样的问题。我已检查,外部存储是可用和可写入的。但不能创建文件夹或文件。

然后我试着用下面的代码来创建/删除文件夹。没关系。但不能创建文件,EACCES(权限被拒绝)发生。希望这段代码能帮助你。

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); 
    } 
} 
+0

谢谢Truong。认为我的代码应该工作。在清单中我有适当的陈述。我想了解我的代码有什么问题。 – UFGator 2014-10-09 13:11:56

+0

**更新:**我找到了该文件,但它位于本机的根目录中,而不在SD卡上。关于如何在SDCard上获得它的任何想法? – UFGator 2014-10-09 13:47:33

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; 
} 

https://stackoverflow.com/a/23534713/980521

+0

谢谢eee。在清单中我有适当的陈述。'<使用权限 android:name =“android.permission.WRITE_EXTERNAL_STORAGE”/> <使用权限 android:name =“android.permission.READ_EXTERNAL_STORAGE”/>' – UFGator 2014-10-09 13:15:06

+0

**更新:**我找到了文件,但它位于本机的根目录中,而不在SDCard上。关于如何在SDCard上获得它的任何想法? – UFGator 2014-10-09 13:58:14

+0

@UFGator权限是一回事,但方法是您需要应用Context.MODE_PRIVATE模式:'文件创建模式:默认模式,创建的文件只能由调用应用程序访问(或共享相同用户的所有应用程序ID).' http://developer.android.com/reference/android/content/Context.html#MODE_PRIVATE – ecle 2014-10-09 22:46:13