安卓6.0通过URI进行图片分享问题总结
2017-04-15 16:00
471 查看
首先说一下我们的需求:xml文件定义的界面,生成图片然后分享到微信朋友或者朋友圈
遇到的问题:
1.xml文件如何在后台默默的生成一张图片?
2.如何直接分享到微信朋友圈?
3.安卓6.0及以上版本适配,也就是通过URI分享的问题
一。xml文件生成图片
其实如果一个页面我们生成一个bitmap是非常简单的,重新定义一个画布然后调用跟布局的draw方法,接收一下就可以了,但是现在的情况是我们的界面不能在界面上显示,而是需要在背后默默的生成一张图片,上面的方法就不管用了,问题是为什么呢?我们先来分析一下,界面显示出来调用的顺序的解析加在布局、测量、布局、绘制然后显示出来了,那么我们不显示只是加在布局呢?只有解析加在布局这一个过程走了,其他都没有走,所以我们需要手动调用测量、布局工作,然后再按照传统的方法调用绘制接收结果。好了,思路有了,直接上代码:
1.xml文件如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<Button
android:onClick="openBlue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="打开蓝牙开始聊天"/>
<ImageView
android:id="@+id/fl_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@mipmap/ic_launcher"/>
</LinearLayout> 2.解析加在布局:
View rankView = inflater.inflate(R.layout.activity_main, null); 3.然后我们需要手动测量、布局
/**
*
* @param v 布局view
* @param width 宽度 宽度高度需要我们手动告诉
* @param height 高度
*/
private void layoutView(View v, int width, int height) {
v.layout(0, 0, width, height);
int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.AT_MOST);
int measuredHeight = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);
v.measure(measuredWidth, measuredHeight);
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
} 4.现在可以接收最后生成的图片
/**
* 由布局生成图片 view的宽高一定要大于0
* @param view
*/
private void loadBitmapFromView(View view) {
int width = view.getWidth();
int height = view.getHeight();
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
} 好了,第一问题解决了,我们已经拿到了布局生成的图片了,下面就是如何直接分享到微信
二。bitmap分享到微信
由于图片大小我们首先说不是很确定,然后就是说6.0以后安卓已经不允许直接跨应用之间传递数据了,所以我们还是用最保险的思路,那就是先将图片保存到本地,然后再通过URI分享到微信
1.保存生成的图片到本地,并且通知本地图库扫描更新媒体库
String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) +"/hui/";
File f = new File(filePath);
if (!f.exists()) {
f.mkdirs();
}
File file = new File(f, getStringFromCalendar()+".png");
注意上面我们保存的位置很关键,因为下面我们6.0以上手机适配需要用的,图片名字随便,算了还是把方法贴出来吧:
/**
* 图片保存的名称
*根据日期生成对应的名称
* @return
*/
public String getStringFromCalendar() {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
int yearNow = calendar.get(Calendar.YEAR);
int monthNow = calendar.get(Calendar.MONTH) + 1;
int dayNow = calendar.get(Calendar.DAY_OF_MONTH);
int hourNow = calendar.get(Calendar.HOUR_OF_DAY);
int minuteNow = calendar.get(Calendar.MINUTE);
int secondNow = calendar.get(Calendar.SECOND);
int millisecond = calendar.get(Calendar.MILLISECOND);
String detailName = Integer.toString(yearNow) + Integer.toString(monthNow)
+ Integer.toString(dayNow) + "_" + Integer.toString(hourNow)
+ Integer.toString(minuteNow) + Integer.toString(secondNow)
+ Integer.toString(millisecond);
return detailName;
} 保存图片:
/**
* 保存位图到本地并且扫描媒体库
* @param bitmap
* @return void
*/
public void SavaImage(Bitmap bitmap, File file){
FileOutputStream fileOutputStream=null;
try {
fileOutputStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
fileOutputStream.close();
Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
scanIntent.setData(Uri.fromFile(file));
sendBroadcast(scanIntent);
} catch (Exception e) {
e.printStackTrace();
}
}
2.将文件开始分享到微信:
Uri parse = Uri.fromFile(file);
Intent intent = new Intent();
ComponentName comp;
String type = "1";
switch (type) {
case "1"://分享给好友
comp = new ComponentName("com.tencent.mm", "com.tencent.mm.ui.tools.ShareImgUI");
;
break;
default://分享到朋友圈
comp = new ComponentName("com.tencent.mm", "com.tencent.mm.ui.tools.ShareToTimeLineUI");
break;
}
intent.setComponent(comp);
intent.setAction(Intent.ACTION_SEND);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_STREAM, parse);//uri为你要分享的图片的uri
startActivity(intent);
分享到微信已经成功了一半了,然并卵6.0手机直接报无法找到资源文件????什么鬼?
三。开始进行6.0手机适配
1.首先说需要动态申请读写权限,如果没有权限,上面保存文件会失败的,随意本地没有保存的图片,分享必然会失败
2.最大的坑来了,URI进行适配处理
功能清单文件添加如下(和activity平级):
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="包名.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider> res文件夹下添加xml文件夹,并且添加filepaths文件,文件中内容如下:
<paths>
<external-path path="." name="external_storage_root" />
</paths> 好了大功告成了,现在可以了。如有不对的地方还请各位看客提出意见建议。
最后还是把demo上传到csdn了,如有需要可以下载。
遇到的问题:
1.xml文件如何在后台默默的生成一张图片?
2.如何直接分享到微信朋友圈?
3.安卓6.0及以上版本适配,也就是通过URI分享的问题
一。xml文件生成图片
其实如果一个页面我们生成一个bitmap是非常简单的,重新定义一个画布然后调用跟布局的draw方法,接收一下就可以了,但是现在的情况是我们的界面不能在界面上显示,而是需要在背后默默的生成一张图片,上面的方法就不管用了,问题是为什么呢?我们先来分析一下,界面显示出来调用的顺序的解析加在布局、测量、布局、绘制然后显示出来了,那么我们不显示只是加在布局呢?只有解析加在布局这一个过程走了,其他都没有走,所以我们需要手动调用测量、布局工作,然后再按照传统的方法调用绘制接收结果。好了,思路有了,直接上代码:
1.xml文件如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<Button
android:onClick="openBlue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="打开蓝牙开始聊天"/>
<ImageView
android:id="@+id/fl_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@mipmap/ic_launcher"/>
</LinearLayout> 2.解析加在布局:
View rankView = inflater.inflate(R.layout.activity_main, null); 3.然后我们需要手动测量、布局
/**
*
* @param v 布局view
* @param width 宽度 宽度高度需要我们手动告诉
* @param height 高度
*/
private void layoutView(View v, int width, int height) {
v.layout(0, 0, width, height);
int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.AT_MOST);
int measuredHeight = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);
v.measure(measuredWidth, measuredHeight);
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
} 4.现在可以接收最后生成的图片
/**
* 由布局生成图片 view的宽高一定要大于0
* @param view
*/
private void loadBitmapFromView(View view) {
int width = view.getWidth();
int height = view.getHeight();
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
} 好了,第一问题解决了,我们已经拿到了布局生成的图片了,下面就是如何直接分享到微信
二。bitmap分享到微信
由于图片大小我们首先说不是很确定,然后就是说6.0以后安卓已经不允许直接跨应用之间传递数据了,所以我们还是用最保险的思路,那就是先将图片保存到本地,然后再通过URI分享到微信
1.保存生成的图片到本地,并且通知本地图库扫描更新媒体库
String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) +"/hui/";
File f = new File(filePath);
if (!f.exists()) {
f.mkdirs();
}
File file = new File(f, getStringFromCalendar()+".png");
注意上面我们保存的位置很关键,因为下面我们6.0以上手机适配需要用的,图片名字随便,算了还是把方法贴出来吧:
/**
* 图片保存的名称
*根据日期生成对应的名称
* @return
*/
public String getStringFromCalendar() {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
int yearNow = calendar.get(Calendar.YEAR);
int monthNow = calendar.get(Calendar.MONTH) + 1;
int dayNow = calendar.get(Calendar.DAY_OF_MONTH);
int hourNow = calendar.get(Calendar.HOUR_OF_DAY);
int minuteNow = calendar.get(Calendar.MINUTE);
int secondNow = calendar.get(Calendar.SECOND);
int millisecond = calendar.get(Calendar.MILLISECOND);
String detailName = Integer.toString(yearNow) + Integer.toString(monthNow)
+ Integer.toString(dayNow) + "_" + Integer.toString(hourNow)
+ Integer.toString(minuteNow) + Integer.toString(secondNow)
+ Integer.toString(millisecond);
return detailName;
} 保存图片:
/**
* 保存位图到本地并且扫描媒体库
* @param bitmap
* @return void
*/
public void SavaImage(Bitmap bitmap, File file){
FileOutputStream fileOutputStream=null;
try {
fileOutputStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
fileOutputStream.close();
Intent scanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
scanIntent.setData(Uri.fromFile(file));
sendBroadcast(scanIntent);
} catch (Exception e) {
e.printStackTrace();
}
}
2.将文件开始分享到微信:
Uri parse = Uri.fromFile(file);
Intent intent = new Intent();
ComponentName comp;
String type = "1";
switch (type) {
case "1"://分享给好友
comp = new ComponentName("com.tencent.mm", "com.tencent.mm.ui.tools.ShareImgUI");
;
break;
default://分享到朋友圈
comp = new ComponentName("com.tencent.mm", "com.tencent.mm.ui.tools.ShareToTimeLineUI");
break;
}
intent.setComponent(comp);
intent.setAction(Intent.ACTION_SEND);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_STREAM, parse);//uri为你要分享的图片的uri
startActivity(intent);
分享到微信已经成功了一半了,然并卵6.0手机直接报无法找到资源文件????什么鬼?
三。开始进行6.0手机适配
1.首先说需要动态申请读写权限,如果没有权限,上面保存文件会失败的,随意本地没有保存的图片,分享必然会失败
2.最大的坑来了,URI进行适配处理
功能清单文件添加如下(和activity平级):
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="包名.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider> res文件夹下添加xml文件夹,并且添加filepaths文件,文件中内容如下:
<paths>
<external-path path="." name="external_storage_root" />
</paths> 好了大功告成了,现在可以了。如有不对的地方还请各位看客提出意见建议。
最后还是把demo上传到csdn了,如有需要可以下载。
相关文章推荐
- 通过 Socket 发送 Http协议 上传图片到速卖通服务器过程中遇到的一些小的问题 总结
- 通过gitlab的webhook进行项目的自动部署所遇问题总结
- 关于第三方应用(Android平台)通过微信分享文字、图片的问题研究。
- Android通过decodeResource图片内存溢出的问题总结
- 通过 Socket 发送 Http协议 上传图片到速卖通服务器过程中遇到的一些小的问题 总结
- 通过gitlab的webhook进行项目的自动部署所遇问题总结
- 通过Java Servlet进行文件下载时的IE缓存问题
- 通过这一项目进行的总结
- 关于COOKIES跨域总结(通过一个问题)
- 实验问题总结与分享之DFS(Distributed File System)
- 这是我们公司总结的一些关于中文乱码问题的一些解决方案和经验和大家分享!
- 关于通过Cookie进行网站自动登录的安全问题
- 通过TFS进行源代码管理的问题
- 这是我们公司总结的一些关于中文乱码问题的一些解决方案和经验和大家分享!
- 用iframe进行表单提交时的若干问题总结
- 超链接,图片等颜色渐变(通过hover进行控制)
- 解决通过Cookie进行网站自动登录的安全性问题
- [分享]Php部分常见问题总结
- 菜鸟的又一小小分享--关于用户控件中图片地址路径的问题