CESDK Android阶段性总结

原始打算

打算直接接入微信和QQ的第三方登录,然后微信,QQ和支付宝的支付.不过研究了几天发现要弄的东西有很多,并且即使最后接入成功
后续上第三方市场时候会存在二次签名问题.这样微信登录仍旧会失效. 所以暂且先放放 选择直接使用聚合SDK.

不过经过这几天的研究又涨了不少知识.这里做下总结.

Unity导入工程到Intellij

Unity目前Export有三种方式

QQ20171207-171739

其中GradleADT都能导出安卓项目,不过尝试过直接导入Intellij.但是均未果. 主要是引入后Gradle都会找不到Gradle Home. 我本地Brew安装了也不行.

后续采取的方法是直接在Intellij中创建新的Android项目.然后将Unity 导出的项目直接复制进去即可.

模拟器调试

直接安装网易MuMu,Intellij可以直接认出来,进行真机调试.

应用签名(KeyStore)

微信SDK两个难点之一就是这个.

什么是KeyStore

首先要弄清楚的就是,什么是应用签名.
文章一,文章二
说的非常详细了.

20151225112950832

我说下我自己的理解. 签名就是 自己拿着一个密钥生成一个公钥,然后把公钥放进APK里面.然后把这个APK传到应用市场里面,比如GooglePlay.

此时如果别人反编译了APK,改了一些代码.因为没有密钥.所以他在不重新签名的情况无法编译出一个可运行的APK,而重新签名后的APK,又因为签名不同 无法回传到Goolgplay上去. 从而保证了市场里面的APK一定是你(密钥的所有者)传上去的.

如何生成

Intellij中选择

QQ20171207-175933
QQ20171207-180955

可以把KeyStore理解为支付宝,上面的那行就是支付宝的密码,而底下的Key0那行就是银行卡的密码. 一个支付宝可以绑定多张银行卡. 也就是能有多个key(key0,key1,key2等).

如何签名

Gradle

Gradle中是通过指定signingConfigs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
apply plugin: 'com.android.application'

android {
compileSdkVersion 26
buildToolsVersion "26.0.1"
defaultConfig {
applicationId "net.sourceforge.simcpux"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
debug {
signingConfig signingConfigs.release
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
signingConfigs {
debug {
storeFile file("../debug.keystore")
}
release {
storeFile file("xxxxxxxxStore")
storePassword "xxxxxxxx"
keyAlias "key0"
keyPassword "xxxxxxxx"
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:26.+'
testCompile 'junit:junit:4.12'
}

Unity

QQ20171207-181834

在PlayerSetting中直接指定即可.

如何查看

Gen_Signature_Android2.apk

微信SDK中自带了一个查看工具Gen Signature Android2

安装好后,直接输入需要查看的包名.比如其测试项目包名就是net.sourceforge.simcpux

57403754

上面这张图就是使用Demo中提供的debug.keystore产生的签名

coruntine_test.lua

这个图的签名是我Unity直接打包生成的APK所产生的签名(Unity默认的debug.keystore). 这也是我之前尝试调试.总出现无法唤起微信,一点发消息直接Crash的原因. 因为签名一直不对…

反编译

使用ApkTool反编译项目

在APK所在的目录执行如下命令:

1
apktool d xxx.apk

使用keytool查看original/META-INF/CERT.RSA

1
keytool -printcert -file 解压后的目录/original/META-INF/CERT.RSA

得到结果

59787968

可以看到MD5这行的信息和使用微信提供的工具查看到的信息相同.

这行值也是最后需要在微信后台填入的值,否则只能使用Demo项目改(包名和签名都要用他的)要不就会闪退.无法唤起微信

wxapi.WXEntryActivity

接入微信SDK,必须在包名下含有wxapi.WXEntryActivity类.但是这个Activity不需要是整个App的入口,只要含有这个Activity并且实现了IWXAPIEventHandler接口即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class WXEntryActivity extends Activity implements IWXAPIEventHandler {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//注意:
//第三方开发者如果使用透明界面来实现WXEntryActivity,需要判断handleIntent的返回值,如果返回值为false,则说明入参不合法未被SDK处理,应finish当前透明界面,避免外部通过传递非法参数的Intent导致停留在透明界面,引起用户的疑惑
try {
Log.i("Eran", "Eran->onCreate");
CESDK.instance.GetWeChatAPI().handleIntent(getIntent(), this);
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.i("Eran", "Eran->onNewIntent");
setIntent(intent);
CESDK.instance.GetWeChatAPI().handleIntent(intent, this);
}

// 微信发送请求到第三方应用时,会回调到该方法
@Override
public void onReq(BaseReq req) {
Log.i("Eran", "Eran->onReq");
CESDK.instance.GetBridge().Log("On receive request");
}

// 第三方应用发送到微信的请求处理后的响应结果,会回调到该方法
@Override
public void onResp(BaseResp resp) {
Log.i("Eran", "Eran->onResp");
CESDK.instance.GetBridge().Log("On receive onResp : " + resp.toString());
finish();
}

}

收到请求后直接调用finish()结束当前Activity就会返回UnityActivity

注意:AndroidManifest.xml中需要引用这个Activity并且设置exported=true属性

1
<activity android:name=".wxapi.WXEntryActivity" android:exported="true"/>

使用Fragment进行Activity扩展(未测试)

对于需要Override UnityActivity的扩展,可以考虑使用Fragment. 可以参考这篇教程

普通Override UnityActivity方法
Unity_Android_Plugin_Tutorial_Subclassing

使用Fragment方法进行扩展

Unity_Android_Plugin_Tutorial_Compositing

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class WeChatFragment extends Fragment implements IWXAPIEventHandler {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Log.i("Eran", "WeChatFragment on create");

CESDK.instance.GetBridge().Log("WeChatFragment on create");

// send oauth request
final SendAuth.Req req = new SendAuth.Req();
req.scope = "snsapi_userinfo";
req.state = "none";
CESDK.instance.GetWeChatAPI().sendReq(req);
}

@Override
public void onReq(BaseReq baseReq) {
Log.i("Eran", "Eran->onReq");
CESDK.instance.GetBridge().Log("Eran->onReq");
}

@Override
public void onResp(BaseResp baseResp) {
Log.i("Eran", "Eran->onResp");
CESDK.instance.GetBridge().Log("Eran->onResp");
}
}

然后在任意函数调用,将Fragment添加到当前的主Activity中来即可

1
2
WeChatFragment fragment = new WeChatFragment();
mBridge.GetUnityMainActivity().getFragmentManager().beginTransaction().add(fragment, "TAG_ABD").commit();

但是由于后来了解到WXEntryActivity不用为入口Activity,所以也没有深入研究.

获取wechat-sdk-android-without-mta-5.1.0.jar

因为不用重载UnityActivity,所以可以将接入部分直接作为lib库,以导入jar包的方式引用Unity.这样每次发版本时候,就不用导入Intellij 然后再发布APK了.

但是现在的项目都采用Gradle构建了,在工程目录下是找不到jar包的. 微信的SDK还好,其官网提供Eclipse工程,目录下有对应的jar包.不过上面也写了.从4.0.2版本以后都改为Gradle构建了.

Gradle的jar包在哪里呢?

QQ20171207-225650

可以参照Android环境搭建里面的步骤,构建相应的SDK.

因为这种方法仍旧是使用的Gradle进行打包,所以最终生成的jar包不会包含依赖库. 也就是wechat-sdk-android-without-mta-5.1.0.jar.

所以需要把生成好的jar包和微信的这个SDK一起拷贝的Unity任意目录即可.

注意不能/Plugins/Android/任意文件夹/libs目录. 因为这样会导致jar包被重复打包,导入jar文件冲突(DEX xxx 什么的错误).

Unity合并AndroidManifest.xml

原理

因为wxapi.WXEntryActivity的问题,在AndroidManifest.xml中必须导出这个Activity,而使用Unity直接打包,就需要给最终的AndroidManifest.xml加入这部分信息.

Unity规定

1
/Plugins/Android/任意文件夹/AndroidManifest.xml

在Android子文件夹下的AndroidManifest.xml文件会Merge到最终的AndroidManifest.xml中来.

如果存在/Plugins/Android/AndroidManifest.xml则使用该AndroidManifest.xml作为初始的模板,如果不存在则使用默认的.

project.properties

之前试了好几次都不行,困扰了我半天. 后来发现是因为子目录中没有包含project.properties文件.

每个子目录中必须包含一个project.properties文件,然后里面有一行

1
android.library=true

用以指定这个子目录是库目录,这样其下的AndroidManifest.xml文件才会被merge进来.

查看方法

如果使用Gradle导出项目,不能直接查看到Merge情况.

QQ20171207-231253

生成的工程回导出两个项目来,所以此时AndroidManifest.xml会有两个,还没有Merge

QQ20171207-231334

并且从主的build.gradle可以看出来. 主项目是依赖于CESDK这个项目的.

其实这个只要知道其内部肯定会Merge的就ok了,反正最终也不会真的导出Gradle项目再编译.

不过如果还是不放心,或有异常错误. 可以直接ApkTool反编译生成好的APK,其内部的AndroidManifest.xml就是最终的了.

放弃转而使用聚合SDK的原因

其实研究了上面的种种问题,Android SDK这边应该已经弄的七七八八了. 理论是可以直接接入微信SDK的了,不够后续还是打算直接使用聚合SDK. 主要是考虑到最终上某些安卓市场时候会存在 二次签名的情况. 一旦二次签名了. 那肯定和微信后台配的签名不同了 这样肯定是没法微信登录的.

后来又看了这篇文章,感觉应该是这些聚合SDK采用了其他的方式,绕开了二次签名的问题.
所以目前还是先采用聚合SDK. 后续再看是否需要自己去写.

坚持原创技术分享,您的支持将鼓励我继续创作!