基于SQLite的ContentProvider我们见得多了,但是我们在做Android应用时,有时候程序需要下载网络上的图片,这时候我们希望能够把图片缓存到客户端本地,下次再要显示该图片时就不用再从网络上下载了,直接从本地缓存读取,这就需要用到存储文件的ContentProvider 。
这里只关注如何通过ContentProvider缓存图片,对Android本地文件操作不熟悉的同学可以参考Android文件存储,其他内容就不介绍了。
在Mainfest文件中,我们定义的ContentProvider名称为FileProvider,最后别忘了添加权限android.permission.WRITE_EXTERNAL_STORAGE
FileContentProvider代码如下,其中openFile是必须实现的方法,已经对关键的代码给出了注释
下面是如何在Activity中该ContentProvider,其中Activity的布局文件我就不贴了,就一个ImageView
这里只关注如何通过ContentProvider缓存图片,对Android本地文件操作不熟悉的同学可以参考Android文件存储,其他内容就不介绍了。
在Mainfest文件中,我们定义的ContentProvider名称为FileProvider,最后别忘了添加权限android.permission.WRITE_EXTERNAL_STORAGE
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.ipjmc.demo.fileprovider"
- android:versionCode="1"
- android:versionName="1.0" >
- <uses-sdk android:minSdkVersion="8" />
- <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" >
- <activity android:label="@string/app_name" android:name=".FileProviderActivity" >
- <intent-filter >
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <provider android:name=".FileProvider" android:authorities="com.ipjmc.demo.fileprovider" />
- </application>
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- </manifest>
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.ipjmc.demo.fileprovider" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:label="@string/app_name" android:name=".FileProviderActivity" > <intent-filter > <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <provider android:name=".FileProvider" android:authorities="com.ipjmc.demo.fileprovider" /> </application> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> </manifest>
FileContentProvider代码如下,其中openFile是必须实现的方法,已经对关键的代码给出了注释
- package com.ipjmc.demo.fileprovider;
- import java.io.BufferedOutputStream;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import android.content.ContentProvider;
- import android.content.ContentValues;
- import android.content.res.AssetManager;
- import android.database.Cursor;
- import android.net.Uri;
- import android.os.ParcelFileDescriptor;
- public class FileProvider extends ContentProvider {
- /*
- * 为了简单起见,这里直接将asset/pic.png拷贝到了程序的ExternalFilesDir,实际中应该是从网络上下载图片到ExternalFilesDir。
- */
- @Override
- public boolean onCreate() {
- File file = new File(getContext().getExternalFilesDir(null), "pic.png");
- if (!file.exists()) {
- AssetManager assetManager = getContext().getAssets();
- try {
- InputStream is = assetManager.open("pic.png");
- OutputStream os = new BufferedOutputStream(new FileOutputStream(file));
- byte [] buf = new byte[1024];
- int len = 0;
- while ((len = is.read(buf)) > 0) {
- os.write(buf, 0, len);
- }
- is.close();
- os.close();
- } catch (IOException e) {
- e.printStackTrace();
- return false;
- }
- }
- return true;
- }
- @Override
- public Cursor query(Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
- // TODO Auto-generated method stub
- return null;
- }
- @Override
- public String getType(Uri uri) {
- if (uri.toString().endsWith(".png")) {
- return "image/png";
- }
- return null;
- }
- /*
- * 就是做一次映射,返回uri指定的文件的文件描述符
- */
- @Override
- public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
- if ("image/png".equals(getType(uri))) {
- File file = new File(getContext().getExternalFilesDir(null), uri.getPath());
- if (file.exists()) {
- return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
- }
- }
- throw new FileNotFoundException(uri.getPath());
- }
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- // TODO Auto-generated method stub
- return null;
- }
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- // TODO Auto-generated method stub
- return 0;
- }
- @Override
- public int update(Uri uri, ContentValues values, String selection,
- String[] selectionArgs) {
- // TODO Auto-generated method stub
- return 0;
- }
- }
package com.ipjmc.demo.fileprovider;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.res.AssetManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
public class FileProvider extends ContentProvider {
/*
* 为了简单起见,这里直接将asset/pic.png拷贝到了程序的ExternalFilesDir,实际中应该是从网络上下载图片到ExternalFilesDir。
*/
@Override
public boolean onCreate() {
File file = new File(getContext().getExternalFilesDir(null), "pic.png");
if (!file.exists()) {
AssetManager assetManager = getContext().getAssets();
try {
InputStream is = assetManager.open("pic.png");
OutputStream os = new BufferedOutputStream(new FileOutputStream(file));
byte [] buf = new byte[1024];
int len = 0;
while ((len = is.read(buf)) > 0) {
os.write(buf, 0, len);
}
is.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// TODO Auto-generated method stub
return null;
}
@Override
public String getType(Uri uri) {
if (uri.toString().endsWith(".png")) {
return "image/png";
}
return null;
}
/*
* 就是做一次映射,返回uri指定的文件的文件描述符
*/
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
if ("image/png".equals(getType(uri))) {
File file = new File(getContext().getExternalFilesDir(null), uri.getPath());
if (file.exists()) {
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
}
}
throw new FileNotFoundException(uri.getPath());
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
}
下面是如何在Activity中该ContentProvider,其中Activity的布局文件我就不贴了,就一个ImageView
- package com.ipjmc.demo.fileprovider;
- import java.io.FileNotFoundException;
- import java.io.InputStream;
- import android.app.Activity;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.net.Uri;
- import android.os.Bundle;
- import android.widget.ImageView;
- public class FileProviderActivity extends Activity {
- public static final Uri URI = Uri.parse("content://com.ipjmc.demo.fileprovider/pic.png");
- ImageView mImageView;
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- mImageView = (ImageView) findViewById(R.id.image);
- try {
- //通过ContentResolver获取图片的输入流,再转化为Bitmap
- InputStream is = getContentResolver().openInputStream(URI);
- Bitmap bitmap = BitmapFactory.decodeStream(is);
- mImageView.setImageBitmap(bitmap);
- } catch (FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }