Android 友盟社会化分享的集成与封装

Android 友盟社会化分享的集成与封装

分享是APP中很是高频的操做之一,在Android的开发环境中,第三方分享框架也有不少。比较流行的包括 极光社会化分享(sharesdk)、友盟社会化分享(Ushare)、Mob社会化分享以及在githut上比较流行的 ShareSDKShareUtilBiliShareShareLoginLib等等。 本篇文章基于友盟ShareSDK,介绍了其集成过程并对其进行模块化封装,以便在项目中更快捷的集成和使用。java

集成前准备

  1. 获取友盟Appkeyandroid

    在【友盟+】官网注册而且添加新应用,得到Appkey。友盟后台的应用名与实际应用名和包名无关,建议命名为应用名+平台(iOS/Android),Android和IOS两个平台不能进行共用,须要进行分开。 建议使用企业邮箱注册,避免使用我的邮箱注册。git

    获取友盟Appkey

  2. 三方帐号申请github

    由于涉及到和各个分享平台的交互,因此在集成前须要在各个平台建立应用并提交审核。建立应用后,分享、登陆操做时显示的应用icon、名称和对应开放平台设置有关,必需要建立应用的平台为:微信、新浪、QQ、Facebook、Kakao、LinkeIn、Twitter、钉钉。web

    目前集成的内容只包含微信、新浪、QQ三个平台,申请渠道以下:小程序

    平台 申请地址
    微信开放平台 open.weixin.qq.com/
    QQ互联平台 connect.qq.com/
    微博开放平台 open.weibo.com

    注1:申请QQ登陆必定要在QQ互联平台,不是在QQ开放平台(open.qq.com微信小程序

    注2:申请过程当中可能须要企业相关资质,如法人身份证、营业执照、税务登记证等,须要提早准备好。api

    注3:提交应用申请时,须要提交应用相关的信息(应用名称、介绍、图标、截图、受权回调域等),微信还须要提交《微信开放平台网站信息登记表》。微信

    注4: 建议你们用企业帐号申请第三方开放平台,不要使用我的的QQ、微信、微博和邮箱进行申请,这样能够避免申请人在职位变更或者离职后,致使帐号管理的风险和交接麻烦。网络

    注5:开放平台申请多数须要审核流程,所以在项目开始时,建议首先申请开放平台帐号和建立应用,以避免申请时间长影响开发进度。

    申请很复杂,因此通常直接找产品经历要就好啦(#笑)。若是是练习用的话,能够直接用官方Demo的包名com.umeng.soexample建立一个示例项目,沿用签名文件、Appkey以及各个三方的Appkey就行了。

集成友盟sdk

在后期模块化后,直接引入封装好的模块便可集成,这里先介绍一下经过添加sdk的方式集成,以及其中我遇到过的问题。

  1. 下载SDK

    最新SDK地址,能够看到友盟的分享包含不少平台,这里咱们只用到了微博微信QQ的分享和登陆功能,不包含支付等,因此选择默认下载的三个精简版便可。若有需求能够参考官方开发文档添加使用。

  2. 添加SDK

    解压下载的sdk压缩包,咱们须要用到其中common和share文件夹下的内容。res顾名思义都是资源文件,复制到项目的res目录中,其余全部jar文件复制到项目的app/libs目录下,并确保在app的gradle依赖中包含implementation fileTree(include: ['*.jar'], dir: 'libs') ,将这个文件夹中全部jar包导入到项目里。

  3. 添加回调Activity

    用到的三个平台中,只有微信须要手动添加Activity。具体作法是,在包名目录下建立wxapi文件夹,新建一个名为WXEntryActivity的Activity继承WXCallbackActivity ,内容为空便可。

  4. 配置Android Manifest XML

    在项目的Manifest中添加各个回调Activity:

    <activity
        android:name=".wxapi.WXEntryActivity"
        android:configChanges="keyboardHidden|orientation|screenSize"
        android:exported="true"
        android:theme="@android:style/Theme.Translucent.NoTitleBar" />
    <activity
        android:name="com.umeng.socialize.media.WBShareCallBackActivity"
        android:configChanges="keyboardHidden|orientation"
        android:exported="false"
        android:theme="@android:style/Theme.Translucent.NoTitleBar"></activity>
    <activity
        android:name="com.sina.weibo.sdk.web.WeiboSdkWebActivity"
        android:configChanges="keyboardHidden|orientation"
        android:exported="false"
        android:windowSoftInputMode="adjustResize"></activity>
    <activity
        android:name="com.sina.weibo.sdk.share.WbShareTransActivity"
        android:launchMode="singleTask"
        android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen">
        <intent-filter>
            <action android:name="com.sina.weibo.sdk.action.ACTION_SDK_REQ_ACTIVITY" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    
    </activity>
    <activity
        android:name="com.tencent.tauth.AuthActivity"
        android:launchMode="singleTask"
        android:noHistory="true">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="tencent100424468" />
        </intent-filter>
    </activity>
    <activity
        android:name="com.tencent.connect.common.AssistActivity"
        android:configChanges="orientation|keyboardHidden|screenSize"
        android:theme="@android:style/Theme.Translucent.NoTitleBar" />
    复制代码

    其中qq的appkey须要替换成本身申请的appkey,这里用的是友盟官方demo的以做测试用。

  5. 添加权限

    在AndroidManifest中添加如下权限:

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
    复制代码

    若是项目的目标sdk版本高于Android6.0,即 targetSdkVersion >= 23 ,还须要在项目中添加权限的动态申请:

    if (Build.VERSION.SDK_INT >= 23) {
        String[] mPermissionList = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CALL_PHONE, Manifest.permission.READ_LOGS, Manifest.permission.READ_PHONE_STATE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.SET_DEBUG_APP, Manifest.permission.SYSTEM_ALERT_WINDOW, Manifest.permission.GET_ACCOUNTS, Manifest.permission.WRITE_APN_SETTINGS};
        ActivityCompat.requestPermissions(this, mPermissionList, 123);
    }
    复制代码
  6. 初始化设置

    将前面的都集成以后,接下来就能够正式进入到代码层面的操做啦。在Application中调用友盟的初始化接口,以及设置各个平台的appkey,这里所有用的是官方demo测试用的appkey。

    public class App extends Application {
        @Override
        public void onCreate() {
            super.onCreate();
            //初始化组件化基础库, 统计SDK/推送SDK/分享SDK都必须调用此初始化接口
            UMConfigure.init(this, "5bed13e1f1f5564655000404", "Umeng", UMConfigure.DEVICE_TYPE_PHONE,
                    "d9352161be267fb40fb12ad5eb04edf9");
            UMShareAPI.get(this);
        }
    
        //各个平台的配置
        {
            //微信
            PlatformConfig.setWeixin("wxdc1e388c3822c80b", "3baf1193c85774b3fd9d18447d76cab0");
            //新浪微博(第三个参数为回调地址)
            PlatformConfig.setSinaWeibo("3921700954", "04b48b094faeb16683c32669824ebdad", "http://sns.whalecloud.com");
            //QQ
            PlatformConfig.setQQZone("100424468", "c7394704798a158208a74ab60104f0ba");
            PlatformConfig.setYixin("yxc0614e80c9304c11b0391514d09f13bf");
            PlatformConfig.setTwitter("3aIN7fuF685MuZ7jtXkQxalyi", "MK6FEYG63eWcpDFgRYw4w9puJhzDl0tyuqWjZ3M7XJuuG7mMbO");
            PlatformConfig.setAlipay("2015111700822536");
            PlatformConfig.setLaiwang("laiwangd497e70d4", "d497e70d4c3e4efeab1381476bac4c5e");
            PlatformConfig.setPinterest("1439206");
            PlatformConfig.setKakao("e4f60e065048eb031e235c806b31c70f");
            PlatformConfig.setDing("dingoalmlnohc0wggfedpk");
            PlatformConfig.setVKontakte("5764965", "5My6SNliAaLxEm3Lyd9J");
            PlatformConfig.setDropbox("oz8v5apet3arcdy", "h7p2pjbzkkxt02a");
    
        }
    }
    复制代码
  7. 添加签名文件

    部分平台在申请appkey的时候就须要项目的签名文件,若是没有的话会影响受权。常规项目只要正常申请好签名就能够了,这里讲一下做为测试用例如何添加签名。

    将官方demo中app目录下的debug.keystore复制到本身的练习项目app目录下

    在项目的app.gradle依赖中android条目下添加以下代码:

    buildTypes {
        release {
            // 是否进行混淆
            minifyEnabled false
            // 签名文件
            signingConfig signingConfigs.debug
            // 混淆文件的位置
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug {
            minifyEnabled false
            signingConfig signingConfigs.debug
            proguardFiles 'proguard-rules.pro'
        }
    }
    signingConfigs {
        debug {
            storeFile file('debug.keystore') storePassword "android" keyAlias "androiddebugkey" keyPassword "android" } } 复制代码

开始分享

终于到了分享的步骤,是骡子是马要牵出来溜溜看看能不能走了,先介绍一下友盟分享的两种形式:

  • 使用分享面板的分享,用户能够调用咱们的打开分享面板的方法,点击分享面板的对应平台进行分享。

  • 不使用分享面板的分享,用户能够本身写分享按钮,或者触发事件,而后调用咱们的分享方法,进行分享。简而言之,直接分享就是在用户本身的界面组件中插入分享行为,分享面板是打开咱们写好的一个界面组件,根据点击事件进行分享。

    可分享的内容包括:

平台 受权 可分享内容 用户信息
qq 文本 图片 连接 视频 音乐
qq空间 同qq 文字(说说) 图片(说说) 连接 视频 音乐 同qq
微信 文本 图片 连接 视频 音乐
微信朋友圈 同微信 文本 图片 连接 视频 音乐 (分享连接不显示描述) 同微信
微信收藏 同微信 文本 图片 连接 视频 音乐 文件 同微信
新浪微博 文本 图片 连接 视频 音乐 文件

下面以直接分享一个网站到微信平台为例,看一下具体的代码实现:

UMWeb web = new UMWeb("https://gank.io/");//建立要分享的Web对象,传入分享的url地址
  web.setTitle("测试分享标题");//设置标题
  web.setThumb(new UMImage(this, R.drawable.thumb));//设置传入显示的缩略图
  web.setDescription("测试分享内容测试分享内容测试分享内容测试分享内容测试分享内容");//设置描述
  new ShareAction(ShareDetailActivity.this)//开启分享
                  .withMedia(web) //填入建立好的分享内容
                  .setPlatform(SHARE_MEDIA.WEIXIN)//选择分享平台
                  .setCallback(shareListener)//设置对分享返回结果的监听
                  .share();//启动分享操做
复制代码

实现效果以下:

以面板的形式分享这个网站:

ShareBoardlistener boardListener = new ShareBoardlistener() { //建立面板的监听器
      @Override
      public void onclick(SnsPlatform snsPlatform, SHARE_MEDIA platform) {
          new ShareAction(mActivity)//开启分享
                  .withMedia(web) //填入建立好的分享内容
                  .setPlatform(platform)//填入选择的平台
                  .setCallback(shareListener)//设置对分享返回结果的监听
                  .share();//启动分享操做
      }
  };
  new ShareAction(mActivity)
          .setDisplayList(SHARE_MEDIA.WEIXIN, SHARE_MEDIA.WEIXIN_CIRCLE, SHARE_MEDIA.WEIXIN_FAVORITE,
                  SHARE_MEDIA.SINA, SHARE_MEDIA.QQ, SHARE_MEDIA.QZONE)//设置分享面板显示的平台
          .setShareboardclickCallback(boardListener)//添加以前建立的面板监听器
          .open(config);//开启分享面板 其中可传入能对面板样式进行自定义操做的config对象 
  		//好比设置面板在底部仍是中部显示、是否有取消按钮、图标形状、字体大小和背景颜色等等
复制代码

默认居中的面板效果以下:

最后不要忘记在调用分享的Activity中,添加以下代码,关闭监听,防止内存泄露等问题。

@Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      super.onActivityResult(requestCode, resultCode, data);
      UMShareAPI.get(this).onActivityResult(requestCode, resultCode, data);
  }
  @Override
      protected void onDestroy() {
          super.onDestroy();
          UMShareAPI.get(this).release();
      }
复制代码

对友盟分享的模块化和代码封装

在前面的内容里,咱们完整的体验了友盟社会化分享的准备、集成和使用,虽然看起来比较简单明了,但对于初次接触的人仍是比较容易碰到问题的,在项目中屡次集成也比较繁琐。因此接下来到了本文的重点内容,对友盟的分享进行模块化,在须要时直接导入模块便可使用,并将主要方法进行封装处理,在开发时提升效率,减小代码量。

下面记录一下封装过程当中的思路和过程,以及封装后的使用方法。

  • 封装过程

    在前面的使用介绍中,能够看到每一次分享,都须要提早建立好待分享的内容,须要传入的数据越多,代码行数越多,因此首先对待建立的对象进行封装。

    根据分享的类型,分了8个类:

    分享类型 枚举参数
    仅文本 SHARE_TYPE_TEXT
    仅图片 SHARE_TYPE_IMAGE
    图文 SHARE_TYPE_TEXTANDIMG
    网址 SHARE_TYPE_WEB
    网络视频 SHARE_TYPE_VIDEO
    网络音乐 SHARE_TYPE_MUSIC
    GIF表情 SHARE_TYPE_EMOJI
    微信小程序 SHARE_TYPE_MINAPP

    其中图片能够经过资源文件id、File文件、网络地址、Bitmap对象、还有byte[]这些方式来建立,其余不少类型虽然不须要图片,但不少须要缩略图,而缩略图的本质也是图片,因此能够将缩略图独立出来:

    private static UMImage mThumb;
    //建立待分享所用的缩略图
    public static void createThumbImage(int thumbResId) {
        mThumb = new UMImage(mActivity, thumbResId);
    }
    
    public static void createThumbImage(File thumbFile) {
        mThumb = new UMImage(mActivity, thumbFile);
    }
    
    public static void createThumbImage(String thumbImageUrl) {
        mThumb = new UMImage(mActivity, thumbImageUrl);
    }
    
    public static void createThumbImage(Bitmap thumbBitmap) {
        mThumb = new UMImage(mActivity, thumbBitmap);
    }
    
    public static void createThumbImage(byte[] thumbBytes) {
        mThumb = new UMImage(mActivity, thumbBytes);
    }
    复制代码

    接下来以建立待分享的网址为例,须要传入的数据包括视频地址、标题、描述、缩略图最少4个内容,前三个都是String对象,最复杂的缩略图已经经过上面的方法建立好了,因此只须要添加前三个内容就够了:

    private static UMWeb mWeb;
    //建立待分享的连接 须要缩略图
    public static void createUrl(String url, String title, String description) {
        mWeb = new UMWeb(url);
        mWeb.setTitle(title);
        mWeb.setDescription(description);
        mWeb.setThumb(mThumb);//传入建立好的缩略图
    }
    复制代码

    到此咱们已经建立好了须要分享的网址对象,接下来天然而然就是分享了。实现很是简单粗暴,直接传入须要分享的平台和类型对应的枚举名便可:

    public static void share(SHARE_MEDIA platform, SHARE_TYPE shareType) {
        ShareAction action = new ShareAction(mActivity)
                .setPlatform(platform).setCallback(mListener);
        switch (shareType) {
            case SHARE_TYPE_TEXT:
                action.withText(mText).share();
                break;
            case SHARE_TYPE_IMAGE:
                action.withMedia(mImage).share();
                break;
            case SHARE_TYPE_TEXTANDIMG:
                action.withText(mText).withMedia(mImage).share();
                break;
            case SHARE_TYPE_WEB:
                action.withMedia(mWeb).share();
                break;
            case SHARE_TYPE_VIDEO:
                action.withMedia(mVideo).share();
                break;
            case SHARE_TYPE_MUSIC:
                action.withMedia(mMusic).share();
                break;
            case SHARE_TYPE_EMOJI:
                action.withMedia(mEmoji).share();
                break;
            case SHARE_TYPE_MINAPP:
                action.withMedia(mMinAPP).share();
                break;
        }
    }
    复制代码

    到这里基本将直接分享的内容进行了封装,那么若是用户不须要咱们已经设好的分享callback,想要自定义呢?因此须要构建一个方法让用户传入自定义的监听器:

    //设置分享监听 传入自定义的监听方式
    public static void setShareListener(UMShareListener listener) {
        mListener = listener;
    }
    复制代码

    除了直接分享,还有面板形式的分享,在这里提供了三种形式的封装:

    1. 直接在中间显示分享面板

      public static void shareBoardAtCenter(SHARE_TYPE shareType) {
          ShareBoardConfig config = new ShareBoardConfig();
          config.setShareboardPostion(ShareBoardConfig.SHAREBOARD_POSITION_CENTER);
          config.setCancelButtonVisibility(true);
          shareBoard(config, shareType);
      }
      复制代码
    2. 在底部显示分享面板

      public static void shareBoardAtBottom(SHARE_TYPE shareType) {
          ShareBoardConfig config = new ShareBoardConfig();
          config.setShareboardPostion(ShareBoardConfig.SHAREBOARD_POSITION_BOTTOM);
          config.setCancelButtonVisibility(true);
          shareBoard(config, shareType);
      }
      复制代码
    3. 用户自定义分享面板

      public static void setBoardWithConfig(ShareBoardConfig config, SHARE_TYPE shareType) {
          shareBoard(config, shareType);
      }
      复制代码

    三种方式,最终都是将面板定义 config 以及要分享的类型 shareType 传入 shareBoard() 方法中,config的具体自定义方法见官方文档,下面贴出 shareBoard() 方法:

    private static void shareBoard(ShareBoardConfig config, final SHARE_TYPE shareType) {
        ShareBoardlistener boardListener = new ShareBoardlistener() {
            @Override
            public void onclick(SnsPlatform snsPlatform, SHARE_MEDIA platform) {
                share(platform, shareType);
            }
        };
        new ShareAction(mActivity)
                .setDisplayList(SHARE_MEDIA.WEIXIN, SHARE_MEDIA.WEIXIN_CIRCLE, SHARE_MEDIA.WEIXIN_FAVORITE,
                        SHARE_MEDIA.SINA, SHARE_MEDIA.QQ, SHARE_MEDIA.QZONE)
                .setShareboardclickCallback(boardListener)
                .open(config);
    }
    复制代码

    能够看出在选择平台后,具体分享的实现方法又跳转到了share()中,实现了代码的复用,对于用户须要自定义面板分享哪些平台,一样能够经过setPlatforms()方法实现:

    //设置分享面板要分享的内容
    public static void setBoardPlatforms(SHARE_MEDIA[] platforms) {
        mPlatforms = platforms;
    }
    复制代码
  • 使用方法

    总体的使用比较简单明了,不过须要注意的是,除了分享文本图片,其余类型都要记得先建立缩略图。

    下面以分享一个网址或者视频为例:

    //首先须要初始化
    UShareUtils.init(this);
    //建立缩略图
    UShareUtils.createThumbImage(R.drawable.cat80);
    //建立待分享的网址,传入网址、标题和描述
    UShareUtils.createUrl("https://gank.io/", "分享标题", "分享描述");
    //建立待分享的视频,传入视频地址、标题和描述
    UShareUtils.createVideo("http://vfx.mtime.cn/Video/2018/10/26/mp4/181026140242572417.mp4", "《驯龙高手3》中文预告", "《驯龙高手3 》由梦工场动画出品,驯龙高手是影史上最受欢迎的动画系列之一,而这部备受期待的新片是该系列的第三部。 ");
    //点击分享
    @OnClick({R.id.tv_share_web, R.id.tv_share_video, R.id.tv_share_board, R.id.tv_share_center})
      	public void onViewClicked(View view) {
                switch (view.getId()) {
                    case R.id.tv_share_web:
                        //分享WEB到QQ
                        UShareUtils.share(SHARE_MEDIA.QQ, SHARE_TYPE.SHARE_TYPE_WEB);
                        break;
                    case R.id.tv_share_video:
                        //分享视频到微信
                        UShareUtils.share(SHARE_MEDIA.WEIXIN, SHARE_TYPE.SHARE_TYPE_VIDEO);
                        break;
        		   case R.id.tv_board_board:
                        //打开底部分享面板 分享WEB
                        UShareUtils.shareBoardAtBottom(SHARE_TYPE.SHARE_TYPE_WEB);
                        break;
                    case R.id.tv_board_center:
                        //打开中部分享面板 分享视频
                        UShareUtils.shareBoardAtBottom(SHARE_TYPE.SHARE_TYPE_VIDEO);
                        break;
                }
        }
    复制代码