Pik,一行代码集成主流SDK
关于Pik
Pik的出现,是为了将开发和SDK完全分开,开发只需要关注方法的调用和回调的处理,Pik充当一个中间人和劳动者的角色,完成SDK的集成。
Pik到底方便在哪里
开发背景
app集成QQ登录
常规做法
我们通常要去腾讯开放平台下载官方SDK,参考文档先是配置工程,又创建实例调用方法,又创建回调方法...或者自己已经对SDK进行了封装,只需要把代码拷到新工程就可以了,当然这对一个有一两年开发经验的也不过是分分钟的事儿。
续:开发背景
别高兴的太早,你上级领导说别的app都有微信登录、分享、支付,怎么我们没有,你二话不说,默默打开了微信开放平台...你上级领导又说了,支付宝这么方便你不用,你似不似傻,你叹了口气,又打开了支付宝开放平台...领导觉得还不过瘾,友盟、百度、高德、极光...
Pik是这样做的
然而在Pik里,你只需要这样:
PikSDK.getInstance().login_qq();
领导,可以QQ登录了...
PikSDK.getInstance().share_qq(params);
领导,可以QQ分享了...
PikSDK.getInstance().login_wechat();
领导,可以微信登录了...
PikSDK.getInstance().pay_wechat(orderJson);
领导,可以微信支付了...
PikSDK.getInstance().pay_alipy(this, payInfo);
领导,可以支付宝支付了...
...
领导摸着你的腿:你就是人人称赞的小王吧,来,这个月给你涨的工资...
详谈Pik
集成步骤
- 将sdk.jar拷贝到工程libs目录下,设置工程依赖
-
AndroidManifest.xml中配置application节点信息
android:name="com.w.pik.sdk.PikApplication"
注:如果工程没有特定的Application,可直接使用PikApplication,如果有,可以继承PikApplication,或者在自己Application的onCreate方法中实现PikSDK.getInstance().onAppCreate(this) - 在工程主Activity中调用
PikSDK.getInstance().init(this) - 在需要登录、分享、支付...的地方调用相应的方法即可。注意,实现这些方法的Activity要继承PikBaseActivity,重写onResult方法实现回调监听(Demo以QQ集成为例,完整演示使用方法)
- 打包生成 app.apk。(重要:Android studio 3.0及以上版本请在gradle.properties文件中添加android.enableAapt2=false)
项目配置
- 在Pik工具目录下的game文件夹中新建demo文件夹,将app.apk和签名文件key.jks拷贝到demo目录下。
- 在config.xml模板文件中配置需要集成的插件和签名文件的密码、别名
- 在Pik\plugin\tencent文件夹下的SDKManifest.xml文件中配置自己在腾讯开放平台申请的APPID。
- 双击Pik目录下的Pik.bat即可自动将集成插件,在output文件夹下生成最终的签名apk。
结语
Pik工具似乎更适合经常需要集成第三方SDK的开发人员,完全剥离开发对第三方SDK的接触,只需要关注一些必须的APPID、APPSECRET...就可以同时集成任意多的SDK。
注
1、Demo地址:https://github.com/StormFeng/PikDemo.git
2、Pik工具地址:https://github.com/StormFeng/PikTool.git
3、联系方式:QQ 1170017470
2018.4.27 补充,Pik工具原理说明
别说话,先看一个再简单不过的例子: Hello world!
<!--布局文件-->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world"/>
</LinearLayout>
<!--strings资源文件-->
<resources>
<string name="hello_world">Hello World!</string>
</resources>
APP是这样子的:
MainActivity.jpg
嗯,客户说这界面纤毫毕现,回味无穷,韵味十足,耐人寻味,情景再现,精妙绝伦...可以发布啦!
于是你迫不及待的将打包后的app.apk发布到应用商店...
结果这款APP上架没多加竟异常火爆,引起了人们的广泛关注,这其中就有一个名叫尼欧的不法分子,尼欧专注捣蛋很多年,他默默的下载了这款app,用 apktool 工具反编译 app.apk ,得到下面这些文件:
app.apk内容.jpg
在res/values文件夹中尼欧发现了 strings.xml ,他打开这个文件,将其中的 “Hello World!” 改写成了 “Fuck The World!”。然后用 apktool 工具回编译得到apk文件后重新签名,上传到一个钓鱼网站上面...几天后,客户给你留言:"I will fuck you to die before you fuck the world..."
经过这次事件之后,虽然你背了锅被老板炒了鱿鱼,但是一个大胆的想法在你脑海中开始酝酿:如果我修改了smali文件夹中的内容会怎样?
你新建了一个工程,界面中有一个Button,点击之后会执行某种特异功能,什么特异功能?鬼才知道呢,你自己都没想好。于是,界面是这样的:
Button.jpg
工程中只有两个类:
类.jpg
MainActivity:
ublic class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onClick(View view){
UtilInterface util = null;
try {
util = (UtilInterface) Class.forName("com.example.administrator.test.Util").newInstance();
} catch (Exception e) {
e.printStackTrace();
}
if(util!=null){
util.doSomeThing();
}
}
}
UtilInterface:
public interface UtilInterface {
void doSomeThing();
}
这能干屌?这当然屌都不能干!工程中没有Util类,所以在onClick方法中会报无法找到类异常。但是你用接口抽象了这个点击的动作,给你以后扩展app的功能带来了无限的可能。
某天,你新交了一个小你18岁的女友,肤白貌美笑如花,你的心里乐呱呱,一高兴写了个Util类实现UtilInterface:
public class Util implements UtilInterface{
@Override
public void doSomeThing() {
Log.d("Pik", "Love the world!");
}
}
本来,反编译上面的抽象工程后得到的smali文件是这样的:
smali.jpg
你把上面的Util反编译后得到的 Util.smali 也放到这里面,然后回编译,之前报找不到类的异常竟然可以工作了,还嗲嗲的跟你说了声"Love the world!"
但,你小女友的爹地不乐意了,他觉得你们两个称兄道弟,你却想上他女儿,硬生生把你俩给拆散了,你悲痛万分,欲死欲仙,额!不对,欲死不能,到处发泄,又写了个Util类实现UtilInterface:
public class Util implements UtilInterface{
@Override
public void doSomeThing() {
Log.d("Pik", "Fuck the world again and again!");
}
}
得到Util.smali后,同样回编译,点击按钮之后你觉得泄愤了很爽!
于是,你把两次写的Util分别保存下来,爽的时候就Love,不爽的时候就Fuck!
思考
如果工程中你有这样的一个接口:
public interface IPikWechatUser {
void login();
void share(String content, String description, PikWXShareTarget target);
void share(Bitmap bitmap, PikWXShareTarget target);
void share(String url, String title, String description, Bitmap thumb, PikWXShareType type, PikWXShareTarget target);
void pay(String s);
}
app1, app2, app3 ... 都有这些功能的调用,那么,这些功能只需要一次实现,然后反编译扩展到这些app就可以了吧。
如果上面这些工作都有脚本来执行,我们只需要配置需要用到的插件,SDK的相关id、key等信息,岂不是更方便!
最后
幸运的是,Pik就是用python写的脚本,不但将这仅仅只需要一次实现的事情做了,还承担了反编译、补充资源、补充smali文件...的功能,开发人员只需接入抽象层,和打包工具的配置
PS:最近工作有点忙,有空会把打包工具重新整理,加更多的功能(修改包名,修改app名,多渠道打包等等),写一份使用说明出来供大家批评指点,谢谢关注!