Android 友盟社会化分享的集成与封装
Android 友盟社会化分享的集成与封装
分享是APP中非常高频的操作之一,在Android的开发环境中,第三方分享框架也有很多。比较流行的包括 极光社会化分享(sharesdk)、友盟社会化分享(Ushare)、Mob社会化分享以及在githut上比较流行的 ShareSDK、ShareUtil、BiliShare、ShareLoginLib等等。 本篇文章基于友盟ShareSDK,介绍了其集成过程并对其进行模块化封装,以便在项目中更快捷的集成和使用。
集成前准备
获取友盟Appkey
在【友盟+】官网注册并且添加新应用,获得Appkey。友盟后台的应用名与实际应用名和包名无关,建议命名为应用名+平台(iOS/Android),Android和IOS两个平台不能进行共用,需要进行分开。 建议使用企业邮箱注册,避免使用个人邮箱注册。
三方账号申请
因为涉及到和各个分享平台的交互,所以在集成前需要在各个平台创建应用并提交审核。创建应用后,分享、登录操作时显示的应用icon、名称和对应开放平台设置有关,必须要创建应用的平台为:微信、新浪、QQ、Facebook、Kakao、LinkeIn、Twitter、钉钉。
目前集成的内容只包含微信、新浪、QQ三个平台,申请渠道如下:
平台 申请地址 微信开放平台 open.weixin.qq.com/ QQ互联平台 connect.qq.com/ 微博开放平台 open.weibo.com 注1:申请QQ登录一定要在QQ互联平台,不是在QQ开放平台(open.qq.com)
注2:申请过程中可能需要企业相关资质,如法人身份证、营业执照、税务登记证等,需要提前准备好。
注3:提交应用申请时,需要提交应用相关的信息(应用名称、介绍、图标、截图、授权回调域等),微信还需要提交《微信开放平台网站信息登记表》。
注4: 建议大家用企业账号申请第三方开放平台,不要使用个人的QQ、微信、微博和邮箱进行申请,这样可以避免申请人在职位变动或者离职后,导致账号管理的风险和交接麻烦。
注5:开放平台申请多数需要审核流程,因此在项目开始时,建议首先申请开放平台账号和创建应用,以免申请时间长影响开发进度。
申请很复杂,所以一般直接找产品经历要就好啦(#笑)。如果是练习用的话,可以直接用官方Demo的包名com.umeng.soexample创建一个示例项目,沿用签名文件、Appkey以及各个三方的Appkey就好了。
集成友盟sdk
在后期模块化后,直接引入封装好的模块即可集成,这里先介绍一下通过添加sdk的方式集成,以及其中我遇到过的问题。
下载SDK
最新SDK地址,可以看到友盟的分享包含很多平台,这里我们只用到了微博微信QQ的分享和登录功能,不包含支付等,所以选择默认下载的三个精简版即可。如有需求可以参考官方开发文档添加使用。
添加SDK
解压下载的sdk压缩包,我们需要用到其中common和share文件夹下的内容。res顾名思义都是资源文件,复制到项目的res目录中,其他所有jar文件复制到项目的app/libs目录下,并确保在app的gradle依赖中包含implementation fileTree(include: ['*.jar'], dir: 'libs') ,将这个文件夹中所有jar包导入到项目里。
添加回调Activity
用到的三个平台中,只有微信需要手动添加Activity。具体做法是,在包名目录下创建wxapi文件夹,新建一个名为
WXEntryActivity
的Activity继承WXCallbackActivity
,内容为空即可。配置Android Manifest XML
在项目的Manifest中添加各个回调Activity:
<activityandroid:name=".wxapi.WXEntryActivity"android:configChanges="keyboardHidden|orientation|screenSize"android:exported="true"android:theme="@android:style/Theme.Translucent.NoTitleBar" /> <activityandroid:name="com.umeng.socialize.media.WBShareCallBackActivity"android:configChanges="keyboardHidden|orientation"android:exported="false"android:theme="@android:style/Theme.Translucent.NoTitleBar"></activity> <activityandroid:name="com.sina.weibo.sdk.web.WeiboSdkWebActivity"android:configChanges="keyboardHidden|orientation"android:exported="false"android:windowSoftInputMode="adjustResize"></activity> <activityandroid: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> <activityandroid: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> <activityandroid:name="com.tencent.connect.common.AssistActivity"android:configChanges="orientation|keyboardHidden|screenSize"android:theme="@android:style/Theme.Translucent.NoTitleBar" /> 复制代码
其中qq的appkey需要替换成自己申请的appkey,这里用的是友盟官方demo的以作测试用。
添加权限
在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); } 复制代码
初始化设置
将前面的都集成之后,接下来就可以正式进入到代码层面的操作啦。在Application中调用友盟的初始化接口,以及设置各个平台的appkey,这里全部用的是官方demo测试用的appkey。
public class App extends Application {@Overridepublic 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");//QQPlatformConfig.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");} } 复制代码
添加签名文件
部分平台在申请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 falsesigningConfig signingConfigs.debugproguardFiles 'proguard-rules.pro'} } signingConfigs {debug {storeFile file('debug.keystore')storePassword "android"keyAlias "androiddebugkey"keyPassword "android"} } 复制代码
开始分享
终于到了分享的步骤,是骡子是马要牵出来溜溜看看能不能走了,先介绍一下友盟分享的两种形式:
使用分享面板的分享,用户可以调用我们的打开分享面板的方法,点击分享面板的对应平台进行分享。
不使用分享面板的分享,用户可以自己写分享按钮,或者触发事件,然后调用我们的分享方法,进行分享。简而言之,直接分享就是在用户自己的界面组件中插入分享行为,分享面板是打开我们写好的一个界面组件,根据点击事件进行分享。
可分享的内容包括:
平台 | 授权 | 可分享内容 | 用户信息 |
---|---|---|---|
是 | 文本 图片 链接 视频 音乐 | 是 | |
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() { //创建面板的监听器@Overridepublic 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中,添加如下代码,关闭监听,防止内存泄露等问题。
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);UMShareAPI.get(this).onActivityResult(requestCode, resultCode, data);}@Overrideprotected 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; } 复制代码
除了直接分享,还有面板形式的分享,在这里提供了三种形式的封装:
直接在中间显示分享面板
public static void shareBoardAtCenter(SHARE_TYPE shareType) {ShareBoardConfig config = new ShareBoardConfig();config.setShareboardPostion(ShareBoardConfig.SHAREBOARD_POSITION_CENTER);config.setCancelButtonVisibility(true);shareBoard(config, shareType); } 复制代码
在底部显示分享面板
public static void shareBoardAtBottom(SHARE_TYPE shareType) {ShareBoardConfig config = new ShareBoardConfig();config.setShareboardPostion(ShareBoardConfig.SHAREBOARD_POSITION_BOTTOM);config.setCancelButtonVisibility(true);shareBoard(config, shareType); } 复制代码
用户自定义分享面板
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() {@Overridepublic 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到QQUShareUtils.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://打开底部分享面板 分享WEBUShareUtils.shareBoardAtBottom(SHARE_TYPE.SHARE_TYPE_WEB);break;case R.id.tv_board_center://打开中部分享面板 分享视频UShareUtils.shareBoardAtBottom(SHARE_TYPE.SHARE_TYPE_VIDEO);break;}} 复制代码
Android 友盟社会化分享的集成与封装相关推荐
- Android集成友盟社会化分享
现在社会化分享组件有很多友推.Mob的ShareSDK.友盟社会化分享组件等,前面两种以前在做项目的时候用到过,最近的项目需要实现分享视频到各社交平台,对比了这三种组件觉得友盟社会化分享组件更适合这个 ...
- Android应用开发-小巫CSDN博客客户端之集成友盟社会化分享组件
Android应用开发-小巫CSDN博客客户端之集成友盟社会化分享组件 上一篇博客给大家介绍了如何分析网页并且使用jsoup这个库对html代码进行解析,本篇博客继续给大家介绍如何集成友盟社会化组件, ...
- Android开发——集成友盟社会化分享遇到的坑(二)
前言 从工作到现在遇到了集成友盟社会化分享第二个坑,集成最新的版的友盟社会化分享SDK遇见了一个之前没有遇到过的程序错误 java.lang.NoClassDeFoundError:Failed re ...
- 微信5.0登录提示服务器繁忙,iOS集成友盟社会化分享微信无法登录?
iOS集成友盟社会化分享SDK-5.0 点击微信登录的时候出现无法获取accessToken的现象,其他如QQ.微博都可以正常登录使用.另外QQ.微博和微信分享都可以正常使用. 望各位早日帮我解决或者 ...
- IOS友盟 社会化分享 社会化iOS组件 分享集成
由于苹果审核政策需求,建议大家对未安装客户端平台进行隐藏,在设置QQ.微信AppID之后调用下面的方法,[UMSocialConfig hiddenNotInstallPlatforms:@[UMSh ...
- 使用友盟社会化分享IOS版SDK分享纯图片到微信
本文和上一篇友盟社会化分享Android版是兄弟篇.其实本人用的是友盟Cocos2d-x的IOS版.对于普通IOS版如何分享纯图片到微信朋友圈,官网文档中已经说明的比较清楚,但是在Cocos2d-x版 ...
- Android应用开发-小巫CSDN博客客户端之集成友盟社会化分享组件,2021最新Android框架体系架构面试题
下面是详细的集成过程: 首先来到官网:http://www.umeng.com/ 选择社会化分享,进入查看这个产品的介绍,下载对应平台的SDK,笔者这里自然是选择Android平台: 笔者集成友盟社会 ...
- 友盟社会化分享之自定义内容分享到微信,微博,豆瓣
以前移动端要做分享的时候一般是两种方法,要么使用Intent调用安卓系统自带的分享功能接口,这是最简单快捷的方法, 要么就自己去QQ微信和各个微博等社交网站申请开发者ID和key,然后在看他们的官方文 ...
- 友盟社会化分享+第三方登录 2022.03.28 最新版
主要通过集成友盟SDK+QQ/微信/新浪SDK实现分享和微信登录功能 1.build.gradle 配置 2.app 文件夹下build.gradle添加以下内容 3.androidManifest. ...
最新文章
- EasyUI 之datagrid 使用 【DataGrid属性解释】
- visionpro定位不跟随图像_机器视觉应用越来越多!不懂怎么办?在线公开课免费学...
- linux内核之旅ppt_一起玩转 Linux 内核之旅开源社区吧
- 很好用的ISO制作软件
- 计算机科学与技术科研论文,计算机科学与技术学院2007年度科研论文一览表
- 递归javascript_JavaScript中的递归
- windows7正版验证_Windows7 寿终正寝:那些一并消逝的软件你知多少?
- 【昇腾学院】昇腾AI处理器软件栈--框架管理器(Framework)离线模型生成
- JavaScript初学者系列一:JavaScript基础(上)
- 如何批量查询ip地址归属地等信息?
- html— Meta— http-equiv属性
- 观张国荣的电影《霸王别姬》有感
- MapGIS应用操作题
- [原创] Photoshopt午简单的调出暗青色效果
- 微博登录界面的PHP代码,redis+php实现微博(一)注册与登录功能详解
- 一看就懂!任务提交的资源判断在Taier中的实践
- HTML5游戏开发–第10课
- 帝国CMS和PHPCMS对比随谈
- 基于FCM算法优化的图像分割研究(附源代码)
- Notification桌面提醒:HTML5新功能
热门文章
- UE4中实现鼠标拖动游戏中的物体
- 算法初级_Question3_打鱼还是晒网(java实现)
- 从来佳茗似佳人-很喜欢的一篇关于茶的文章
- 多功能起名查重工具微信小程序源码下载支持多种流量主模式
- python爬虫爬取图片代码_python爬虫-20行代码爬取王者荣耀所有英雄图片,小白也轻轻松松...
- RocketMQ配置全解(含ACL、Dashboard配置)
- 开启kali的Telnet
- Android存储、摄像头、录音权限检查,适配小米、vivo 、oppo、锤子、魅族、联想等机型和6.0以下系统
- Mac中Vscode总是报‘Linter pylint is not installed.’解决办法
- 咚咚咚————【封装驱动】MLX90614医用级红外温度传感器,分享交流自己编写的程序。