首先说一下我们的需求: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>


好了大功告成了,现在可以了。如有不对的地方还请各位看客提出意见建议。