APP分享多张图片到微信和朋友圈
产品需求:
微信分享多图至好友,朋友圈。由于微信禁用了分享9图至朋友圈功能,这里分享微信只是将图片保存至本地,具体让用户手动分享。
问题分析:
微信没有提供分享多图的SDK,因此我们实现调用系统自带的分享功能。将分享的图片保存至本地,再调用系统本地的分享实现分享多图操作。
具体实现:
这里保存图片实现用了两种方式:
- 使用网络请求下载图片。
- 使用Glide加载图片。
2.1 将请求网络的图片转化成bitmap,再将bitmap图片保存至本地相册。
2.2 获取缓存至本地的文件,再将文件保存至指定目录,更新相册。
注意:保存图片至系统相册目录时,只能在主线程实现。推断里面使用了IO流的原因。
一、分享多图至微信
AtomicInteger count = new AtomicInteger();
ArrayList<Observable<File>> observables = new ArrayList<>();
List<Uri> imageUris = new ArrayList<Uri>();
mCommitDialog = WeiboDialogUtils.createLoadingDialog(this, "正在加载...");
observables.add(Observable.fromIterable(imageList).flatMap(new Function<String, ObservableSource<File>>() {
@Override
public ObservableSource<File> apply(String imagePath) throws Exception {
return Observable.create(new ObservableOnSubscribe<File>() {
@Override
public void subscribe(ObservableEmitter<File> emitter) throws Exception {
File file = PhotoUtils.saveImageToSdCard(getActivity(), imagePath);
emitter.onNext(file);
}
});
}
}).subscribeOn(Schedulers.io()));
Observable.merge(observables).map(new Function<File, Boolean>() {
@Override
public Boolean apply(File f) throws Exception {
File file = new File(f.getAbsolutePath());
if(file.exists()) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {//android 7.0以下
imageUris.add(Uri.fromFile(file));
} else {//android 7.0及以上
Uri uri = Uri.parse(android.provider.MediaStore.Images.Media.insertImage(getContentResolver(), file.getAbsolutePath(), file.getName(), null));
imageUris.add(uri);
}
return true;
}
return false;
}}).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Boolean>() {
@Override
public void accept(Boolean a) throws Exception {
if(a) count.addAndGet(1);
if(imageList.size() == count.get()){
mCommitDialog.dismiss();
// showMessage(R.string.text_share_success );
//分享到微信好友
Intent intent = new Intent();
ComponentName componentName = new ComponentName("com.tencent.mm", "com.tencent.mm.ui.tools.ShareImgUI");
if (imageUris.size() == 0) return;
intent.setComponent(componentName);
intent.setAction(Intent.ACTION_SEND_MULTIPLE);
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_STREAM, (Serializable) imageUris);
startActivity(intent);
}
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
mCommitDialog.dismiss();
showMessage(R.string.text_save_failed);
}
}, new Action() {
@Override
public void run() throws Exception {
}
})
;
saveImageToSdCard方法如下。
//根据网络图片url路径保存到本地
public static final File saveImageToSdCard(Context context, String image) {
boolean success = false;
File file = null;
try {
file = createStableImageFile(context);
Bitmap bitmap = null;
URL url = new URL(image);
HttpURLConnection conn = null;
conn = (HttpURLConnection) url.openConnection();
InputStream is = null;
is = conn.getInputStream();
bitmap = BitmapFactory.decodeStream(is);
FileOutputStream outStream;
outStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.flush();
outStream.close();
success = true;
} catch (Exception e) {
e.printStackTrace();
}
if (success) {
return file;
} else {
return null;
}
}
二、保存多图至本地。
1.Glide加载图片生成Bitmap对象。
AtomicInteger count = new AtomicInteger(); ArrayList<Observable<Boolean>> observables = new ArrayList<>(); for (String imagePath : imageList) { observables.add(Observable.create(new ObservableOnSubscribe<Boolean>() { @Override public void subscribe(ObservableEmitter<Boolean> emitter) throws Exception { SimpleTarget<Bitmap> into = Glide.with(getActivity()) .asBitmap() .load(imagePath) .into(new SimpleTarget<Bitmap>() { @Override public void onResourceReady( Bitmap bitmap, @Nullable Transition<? super Bitmap> transition) { if (bitmap != null) { //图片信息不为空时才保存 emitter.onNext( PhotoUtils.savePhoto(getActivity(), DateUtils.formatDate(getActivity(), System.currentTimeMillis()) + UUID.randomUUID() + ".png", bitmap)); } } }); } }).subscribeOn(AndroidSchedulers.mainThread()));} Observable.merge(observables).observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<Boolean>() { @Override public void accept(Boolean b) throws Exception { if (b) { count.addAndGet(1); } if(imageList.size() == count.get()){ showHintDialog(); // showMessage(R.string.text_save_pic_success ); } } }, new Consumer<Throwable>() { @Override public void accept(Throwable throwable) throws Exception { showMessage(R.string.text_save_pic_failed); } }, new Action() { @Override public void run() throws Exception { } });
2.Glide加载图片,得到文件形式。
File file = Glide.with(context)
.load(images[i])
.downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.get()
savePhoto方法如下:
/** * 保存图片 */ public static boolean savePhoto(Context context, String fileName, Bitmap bitmap) { //系统相册目录 String galleryPath = Environment.getExternalStorageDirectory() + File.separator + Environment.DIRECTORY_DCIM + File.separator + "Camera" + File.separator; File imagePath = new File(galleryPath); if (!imagePath.exists()) { imagePath.mkdirs(); } File fileUri = new File(imagePath + File.separator + fileName); if (!fileUri.exists()) { try { fileUri.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } Uri imgUri = Uri.fromFile(fileUri); try { FileOutputStream out = new FileOutputStream(fileUri); bitmap.compress(Bitmap.CompressFormat.PNG, 100, out); out.flush(); out.close(); Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); intent.setData(imgUri); context.sendBroadcast(intent); return true; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return false; }
注意:这里要申请权限。
参考博客: