最近有人问我微信发送截屏图像的功能,有人问我怎么实现,这里记录分享下。
我的做法就是用FileObserver。先摘一段FileOberver的介绍:
FileObserver类是一个用于监听文件访问、创建、修改、删除、移动等操作的监听器,基于linux的inotify。
FileObserver 是个抽象类,必须继承它才能使用。每个FileObserver对象监听一个单独的文件或者文件夹,如果监视的是一个文件夹,那么文件夹下所有的文件和级联子目录的改变都会触发监听的事件。其实不然,经过测试并不支持递归,对于监听目录的子目录中的文件改动,FileObserver 对象是无法收到事件回调的,不仅这样,监听目录的子目录本身的变动也收不到事件回调。原因是由 linux 的 inotify 机制本身决定的,基于 inotify 实现的 FileObserver 自然也不支持递归监听。
FileObserver 是个抽象类,必须继承它才能使用
可以监听的事件类型:
ACCESS : 即文件被访问
MODIFY : 文件被修改
ATTRIB : 文件属性被修改,如 chmod、chown、touch 等
CLOSE_WRITE : 可写文件被 close
CLOSE_NOWRITE : 不可写文件被 close
OPEN : 文件被 open
MOVED_FROM : 文件被移走,如 mv
MOVED_TO : 文件被移来,如 mv、cp
CREATE : 创建新文件
DELETE : 文件被删除,如 rm
DELETE_SELF : 自删除,即一个可执行文件在执行时删除自己
MOVE_SELF : 自移动,即一个可执行文件在执行时移动自己
CLOSE : 文件被关闭,等同于(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
ALL_EVENTS : 包括上面的所有事件
接下来我们自定义自己的FileObserver来实现截屏文件存储好之后的监听。
public class ScreenshotObserver extends FileObserver {
private static final String TAG = "ScreenshotObserver";
private static final String PATH = Environment.getExternalStorageDirectory().toString() + "/Pictures/Screenshots/";
private OnScreenshotTakenListener listener;
private String lastTakenPath;
public ScreenshotObserver(OnScreenshotTakenListener listener) {
super(PATH, FileObserver.CLOSE_WRITE);
this.listener = listener;
}
@Override
public void onEvent(int event, String path) {
if (path==null || event!=FileObserver.CLOSE_WRITE){
//dont care
}
else if (lastTakenPath!=null && path.equalsIgnoreCase(lastTakenPath)){
//had observer,ignore this
}
else {
lastTakenPath = path;
File file = new File(PATH+path);
listener.onScreenshotTaken(Uri.fromFile(file));
Log.i(TAG, "Send event to listener.");
}
}
public void start() {
super.startWatching();
}
public void stop() {
super.stopWatching();
}
}
OnScreenshotTakenListener的代码很简单,就是一个接口:
public interface OnScreenshotTakenListener {
void onScreenshotTaken(Uri uri);
}
下面贴出测试的Activity代码:
public class TestScreenShotActivity extends Activity implements OnScreenshotTakenListener{
private ImageView image;
private ScreenshotObserver screenShotObserver;
private static final int DEFAULT_WIDTH = 512;
private static final int DEFAULT_HEIGHT = 384;
private int width ;
private int height;
private int sampleSize = 1;
private ContentResolver contentResolver ;
private Handler hanlder = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen_shot);
image = (ImageView)findViewById(R.id.imageview);
contentResolver = getContentResolver();
screenShotObserver = new ScreenshotObserver(this);
screenShotObserver.start();
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
screenShotObserver.stop();
}
@Override
public void onScreenshotTaken(Uri uri) {//not UI Thread
// TODO Auto-generated method stub
getBitmapSize(uri);
final Bitmap bitmap = getBitmap(uri);
if(bitmap != null){
hanlder.post(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
image.setImageBitmap(bitmap);
}
});
}
}
private void getBitmapSize(Uri uri){//get bitmap size before draw
InputStream is = null;
try {
is = getInputStream(uri);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is, null, options);
width = options.outWidth;
height = options.outHeight;
}catch(IOException e) {
e.printStackTrace();
}finally {
if (is != null) {
try {
is.close();
} catch (IOException ignored) {
}
}
}
}
private Bitmap getBitmap(Uri uri){
Bitmap bitmap = null;
InputStream is = null;
try {
try {
is = getInputStream(uri);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while ((width / sampleSize > DEFAULT_WIDTH * 2) || (height / sampleSize > DEFAULT_HEIGHT * 2)) {
sampleSize *= 2;
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = sampleSize;
bitmap = BitmapFactory.decodeStream(is, null, options);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException ignored) {
}
}
}
return bitmap;
}
private InputStream getInputStream(Uri mUri) throws IOException{
try {
if (mUri.getScheme().equals("file")) {
return new java.io.FileInputStream(mUri.getPath());
} else {//from database
return contentResolver.openInputStream(mUri);
}
} catch (FileNotFoundException ex) {
return null;
}
}
}
Note:别忘了加读写存储的权限,layout很简单,就一个imageview。
有问题交流~