android4.4及之后写文件到sdcard

/*
* Copyright (C) 2014 NextApp, Inc.
* 
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* 
* http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/ 
 
package nextapp.mediafile; 
 
import java.io.File; 
import java.io.IOException; 
import java.io.OutputStream; 
 
import android.content.ContentResolver; 
import android.content.ContentValues; 
import android.net.Uri; 
import android.provider.MediaStore; 
 
/**
* Wrapper for manipulating files via the Android Media Content Provider. As of Android 4.4 KitKat, applications can no longer write
* to the "secondary storage" of a device. Write operations using the java.io.File API will thus fail. This class restores access to
* those write operations by way of the Media Content Provider.
* 
* Note that this class relies on the internal operational characteristics of the media content provider API, and as such is not
* guaranteed to be future-proof. Then again, we did all think the java.io.File API was going to be future-proof for media card
* access, so all bets are off.
* 
* If you're forced to use this class, it's because Google/AOSP made a very poor API decision in Android 4.4 KitKat.
* Read more at https://plus.google.com/+TodLiebeck/posts/gjnmuaDM8sn
*
* Your application must declare the permission "android.permission.WRITE_EXTERNAL_STORAGE".
*/ 
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(); 
    } 
 
    /**
     * 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); 
    } 
}  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值