工作中遇到需要将一张超过2M的图传递给另外一个应用使用。
之前是通过Intent中放Bundle对象,通过bundle对象存二进制数组,通过广播的形式发送给另外一个应用,另外一个应用根据key值来获取数组,将数组转成Bitmap。
Bundle b = new Bundle();
b.putByteArray(key_byte, flattenBitmap(bitmap));
intent.putExtra(key_bundle, b);
sendBroadcast(intent);
public static byte[] flattenBitmap(Bitmap bitmap) {
// Try go guesstimate how much space the icon will take when serialized
// to avoid unnecessary allocations/copies during the write.
int size = bitmap.getWidth() * bitmap.getHeight() * 4;
ByteArrayOutputStream out = new ByteArrayOutputStream(size);
try {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
return out.toByteArray();
} catch (IOException e) {
Log.w("Favorite", "Could not write icon");
return null;
}
}
另外一个应用 只要通过intent 得到bundle:
Bundle b = intent.getBundleExtra(key_bundle);
byte [] bd = null;
if(b != null)
bd = (byte[]) b.get(key_byte);
得到这个数组就可以得到这个张bitmap了。
由于这种方式 传递的图是有大小限制的,如果传入的Bitmap超过一定的大小,就会无法传递过去,抛出异常。
现在改成通过ContentProvider的方式。
一开始的时候,写sqlite,然后再写provider共享出去,结果sqlite中存bitmap也是有限制的。
放弃之。
现在的方式:
ContentProvider中重新ParcelFileDescriptor openFile(Uri uri, String mode)这个方法。
package com.android.launcher2;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
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.Context;
import android.content.Intent;
import android.content.UriMatcher;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.ParcelFileDescriptor;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.WindowManager;
public class LockscreenWallpaperProvider extends ContentProvider {
private static final String TAG = "LockscreenWallpaperProvider";
public static final Uri CONTENT_URI = Uri
.parse("content://com.android.launcher.lockscreenwallpaper/");
private final static String AUTHORITY = "com.android.launcher.lockscreenwallpaper";
private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
private static final int LOCKSCREEN_WALLPAPER = 1;
static {
MATCHER.addURI(AUTHORITY, "lockscreen_wallpaper.png", LOCKSCREEN_WALLPAPER);
}
private static final String LOCKSCREEN_WALLPAPER_UPDATE = "com.ape.launcher.wallpaper.CROP_ACTION";
@Override
public boolean onCreate() {
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
return null;
}
@Override
public String getType(Uri uri) {
if (uri.toString().endsWith(".png")) {
return "image/png";
}
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
Log.d(TAG, "insert---->uri = "+uri);
Log.d(TAG, "MATCHER.match(uri) = "+MATCHER.match(uri));
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
return 0;
}
@Override
public AssetFileDescriptor openAssetFile(Uri uri, String mode)
throws FileNotFoundException {
// TODO Auto-generated method stub
Log.d(TAG, "openAssetFile");
return super.openAssetFile(uri, mode);
}
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException {
Log.d(TAG, "openFile::::::::getType(uri) = "+getType(uri));
Log.d(TAG, "uri = "+uri);
Log.d(TAG, "uri.getPath() = "+uri.getPath());
if ("image/png".equals(getType(uri))) {
Log.d(TAG, "openFile");
File file = new File(getContext().getFilesDir(),
uri.getPath());
if (file.exists()) {
Log.d(TAG, "file = exist");
return ParcelFileDescriptor.open(file,
ParcelFileDescriptor.MODE_READ_ONLY);
}else {
Log.d(TAG, "file != exist");
}
}
throw new FileNotFoundException(uri.getPath());
}
}
Androidmanifest.xml 写上
<provider
android:name="com.android.launcher2.LockscreenWallpaperProvider"
android:authorities="com.android.launcher.lockscreenwallpaper"
android:exported="true" >
</provider>
这样就可以被别的应用访问了。
package com.example.lockscreenwallpaperdemo;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
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.app.Activity;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
public class MainActivity extends Activity {
private ImageView mImageView;
private Button button;
public static final Uri URI_LOCKSCREEN_WALLPAPER = Uri.parse("content://com.android.launcher.lockscreenwallpaper/lockscreen_wallpaper.png");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pic);
mImageView = (ImageView)this.findViewById(R.id.image);
startLoadImageTask();
}
void startLoadImageTask() {
if (mLoadImageTask != null && mLoadImageTask.getStatus() != LoadImageAsyncTask.Status.FINISHED) {
mLoadImageTask.cancel();
}
mLoadImageTask = (LoadImageAsyncTask)new LoadImageAsyncTask().execute();
}
LoadImageAsyncTask mLoadImageTask;
class LoadImageAsyncTask extends AsyncTask<String, Void, Bitmap> {
protected Bitmap doInBackground(String... params) {
Bitmap bmpout = null;
try {
//通过ContentResolver获取图片的输入流,再转化为Bitmap
InputStream is = getContentResolver().openInputStream(URI_LOCKSCREEN_WALLPAPER);
bmpout = BitmapFactory.decodeStream(is);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block 32.e.printStackTrace();
Log.e(TAG, "FileNotFoundException----->33333");
}
return bmpout;
}
protected void onPostExecute(Bitmap result) {
if (result == null) {
return;
}
if (!isCancelled()) {
mImageView.setImageBitmap(result);
}else {
result.recycle();
}
}
void cancel() {
super.cancel(true);
}
}
}
这个方法解决访问的问题。
如果这个应用要去修改provider出来的数据,好像没有别的方法。insert 和update方法应该也不行。
如果某位大神知道,还请指导下,谢谢。