文档章节

通过ContentProvider访问应用的data区files的文件

秋烟还在
 秋烟还在
发布于 2015/01/24 16:35
字数 878
阅读 2829
收藏 21

    工作中遇到需要将一张超过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方法应该也不行。

如果某位大神知道,还请指导下,谢谢。

 

 

© 著作权归作者所有

秋烟还在
粉丝 0
博文 2
码字总数 1076
作品 0
南京
私信 提问
加载中

评论(2)

秋烟还在
秋烟还在 博主

引用来自“linin630”的评论

其实可以把图片存到sd卡,然后只传个地址过去另一个应用不是更简单么?
如果sd卡处于unmount状态的话,sd不可用,无法保存成功的话,另外一个应用会得不到这个数据的。
linin630
linin630
其实可以把图片存到sd卡,然后只传个地址过去另一个应用不是更简单么?
Android 的数据存储方式

Android 提供了5种方式存储数据: --使用SharedPreferences存储数据; --文件存储数据; --SQLite数据库存储数据; --使用ContentProvider存储数据; --网络存储数据; 先说下,Preference,...

等待流星
2014/03/13
149
0
Android 数据持久化方式

1、 通过Context.getSharedPreferences(String fileName,int mode)方法,可以打开一个xml文件,文件的位置在/data/data/packagename/sharedprefs/fileName.xml,如果不存在,则会自动创建。可...

太浪
2013/02/26
3.7K
0
Android四大组件之ContentProvide(内容提供者)

访问私有数据库 创建一个项目,在项目中利用SQLiteOpenHelper创建一个名称为account的数据库,并在数据库中创建一张名为info的表。 在MainActivity中需要调用以下代码才能创建数据库: 运行程...

早早的太阳
2016/09/25
33
0
Android-ContentProvider数据库操作

在实际的开发过程中,Android提供了5种方式存储数据: 1.文件存储数据 2.使用 Sharedpreferences 存储数据 3.SQLite数据库存储数据 4.使用ContentProvider存储数据 5.网络存储数据 首先我们先...

zhoulc
2013/11/01
8.9K
0
四大组件之ContentProvider(二)-轻轻松松自定义ContentProvider

版权声明:本文为博主原创文章,禁止转载,违者必究。 https://blog.csdn.net/anddlecn/article/details/51699068 第3节 自定义ContentProvider 自定义一个,需要 继承重新创建一个类,并实现...

anddlecn
2016/06/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

MySQL左连接问题,右表做筛选,左表列依然在

两张表,一张user表,一张user_log表 CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFA......

bengozhong
23分钟前
5
0
重新开始学Java——多线程基础

多线程 进程 主流计算机操作系统都支持同时运行多个任务 , 每个任务通常就是一个程序 , 每个运行中的程序就是一个进程或者多个进程 。 进程的特点 独立性 进程是系统中独立存在的实体 可以...

大家都是低调来的
24分钟前
7
0
注解在Java中是如何工作的?

> 来一点咖啡,准备好进入注解的世界。 注解一直是 Java 的一个非常重要的部分,它从 J2SE 5.0 开始就已经存在了。在我们的应用程序代码中,经常看到 @Override 和 @Deprecated 这样的注解。...

liululee
26分钟前
17
0
Docker 容器连接

Docker 容器连接 容器间的链接有两种方法,你选择其一即可 网络端口映射 docker run -d -P docker run -d -p-P :是容器内部端口随机映射到主机的高端口。-p : 是容器内部端口绑定到指定...

测者陈磊
29分钟前
8
0
车载导航应用中基于Sketch UI主题定制方案的实现

1.导读 关于应用的主题定制,相信大家或多或少都有接触,基本上,实现思路可以分为两类: 内置主题(应用内自定义style) 外部加载方式(资源apk形式、压缩资源、插件等) 其实,针对不同的主题...

阿里云官方博客
35分钟前
11
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部