工做中遇到須要將一張超過2M的圖傳遞給另一個應用使用。java
以前是經過Intent中放Bundle對象,經過bundle對象存二進制數組,經過廣播的形式發送給另一個應用,另一個應用根據key值來獲取數組,將數組轉成Bitmap。android
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:sql
Bundle b = intent.getBundleExtra(key_bundle);數組
byte [] bd = null;app
if(b != null)ide
bd = (byte[]) b.get(key_byte);this
獲得這個數組就能夠獲得這個張bitmap了。spa
因爲這種方式 傳遞的圖是有大小限制的,若是傳入的Bitmap超過必定的大小,就會沒法傳遞過去,拋出異常。.net
如今改爲經過ContentProvider的方式。code
一開始的時候,寫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方法應該也不行。
若是某位大神知道,還請指導下,謝謝。