转载:https://www.jianshu.com/p/152fd3af1193
各位看官,上文 手游SDK— 第二篇(架构设计篇)已经介绍过了架构实现的基本思路,那废话就不多说了,进入正题,看下代码的具体实现。
PS:不具备实际项目用途,仅做框架Demo展示
项目结构搭建
首先咱们先整体搭建下项目工程的框架模块,根据之前的项目架构设计搭建的,这里也比较简单,我简单附上一张图。

PS:相关的模块管理可参考
- Android Studio 多Module统一管理方法
项目代码实现
第一部分:基础库
基础库涉及的功能库比较多,大概抽离部分模块大体讲解下,主要分两部分:涉及SDK架构的代码实现和部分三方框架的封装思路讲解。
项目/插件/渠道管理设计
项目的框架主体骨架
配置文件格式:Project_config.txt / Plugin_config.txt / Channel_config.txt
1
2
3
4
5
6
7
8
9
10
11
{
"project": [
{
"project_name": "project",
"class_name": "com.bzai.gamesdk.project.juhe.JuHeProject",
"description": "聚合SDK项目",
"version": "1.0.0"
}
]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"plugin": [
{
"plugin_name": "plugin_wechat",
"class_name": "com.bzai.gamesdk.plugin.wechat.WechatPlugin",
"description": "微信功能插件",
"version": "5.1.4"
},
{
"plugin_name": "plugin_alipay",
"class_name": "com.bzai.gamesdk.plugin.alipay.AlipayPlugin",
"description": "支付宝功能插件",
"version": "15.5.5"
}
]
}
1
2
3
4
5
6
7
8
9
10
11
{
"channel": [
{
"channel_name": "channel",
"class_name": "com.bzai.gamesdk.channel.test.TestChannelSDK",
"description": "测试渠道SDK",
"version": "1.0.0"
}
]
}
比较简单就不细说,是Json格式的数据,大家可以根据需求进行数据拓展。
PS:备注说明下,其实是可以通过一个配置文件就能配置完的,但是将项目、插件、渠道分别配置加载的目的是方便快速的分别替换项目、插件、渠道配置。一个项目Project可以对应多个渠道、多个插件。后续可以在多渠道、多插件上进行快速的插拔和后台开关切换渠道,不过正常的需求都是一个项目对应零个或一个渠道、零个或多个功能插件。
代码实现
抽象类解析
1、抽象的项目Project类,主要是面向SDKAPI接口设计的,预定义对外的接口及Activity生命周期接口。但是通常对外的接口一般设计好后非必要就很少修改,为了对外接口设计进行扩展,预定义通用的拓展接口extendFunction(Activity activity, int functionType, Object object, CallBackListener callBackListener),通过不同的funtionType进行扩展。
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
public abstract class Project implements ProguardInterface{
复制代码<span class="hljs-comment">/***************************** Project 加载接口 **********************************/</span>
<span class="hljs-keyword">public</span> ProjectBeanList.ProjectBean projectBean;
<span class="hljs-keyword">private</span> boolean hasInited;
<span class="hljs-function"><span class="hljs-keyword">protected</span> synchronized <span class="hljs-keyword">void</span> <span class="hljs-title">initProject</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">if</span> (hasInited) {
<span class="hljs-keyword">return</span>;
}
hasInited = <span class="hljs-literal">true</span>;
}
@<span class="hljs-function">Override
<span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">return</span> <span class="hljs-string">"Project{"</span> + <span class="hljs-string">"projectBean="</span> + projectBean + <span class="hljs-string">", hasInited="</span> + hasInited + <span class="hljs-string">'}'</span>;
}
<span class="hljs-comment">/***************************** 顶层 Project 功能接口:初始化、登陆、支付、退出 **********************************/</span>
<span class="hljs-comment">/**
* 初始化
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">init</span><span class="hljs-params">(Activity activity, String gameid, String gamekey, CallBackListener callBackListener)</span> </span>{}
<span class="hljs-comment">/**
* 登录
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">login</span><span class="hljs-params">(Activity activity, HashMap<String,Object> loginParams)</span> </span>{}
<span class="hljs-comment">/**
* 支付
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">pay</span><span class="hljs-params">(Activity activity, HashMap<String,Object> payParams, CallBackListener callBackListener)</span> </span>{}
<span class="hljs-comment">/**
* 切换账号
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">switchAccount</span><span class="hljs-params">(Activity activity)</span></span>{}
<span class="hljs-comment">/**
* 登出
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">logout</span><span class="hljs-params">(Activity activity)</span> </span>{}
<span class="hljs-comment">/**
* 退出
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">exit</span><span class="hljs-params">(Activity activity, CallBackListener callBackListener)</span> </span>{}
<span class="hljs-comment">/**
* 上报数据
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">reportData</span><span class="hljs-params">(Context context, HashMap<String,Object> dataMap)</span></span>{}
<span class="hljs-comment">/**
* 设置SDK账号监听
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setAccountCallBackLister</span><span class="hljs-params">(CallBackListener callBackLister)</span></span>{}
<span class="hljs-comment">/**
* 显示SDK悬浮窗,将登录、支付等信息回调
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">showFloatView</span><span class="hljs-params">(Activity activity)</span></span>{}
<span class="hljs-comment">/**
* 关闭SDK悬浮窗
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">dismissFloatView</span><span class="hljs-params">(Activity activity)</span></span>{}
<span class="hljs-comment">/**
* 拓展接口,处理渠道的定制接口
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">extendFunction</span><span class="hljs-params">(Activity activity, <span class="hljs-keyword">int</span> functionType, Object object, CallBackListener callBackListener)</span></span>{}
<span class="hljs-comment">/**
* 获取渠道ID
* @return
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getChannelID</span><span class="hljs-params">()</span></span>{
<span class="hljs-keyword">return</span> null;
}
<span class="hljs-comment">/******************************* 顶层 Project 生命周期接口 (目前实现各插件的生命周期)******************************/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(Activity activity, Bundle savedInstanceState)</span> </span>{
PluginManager.getInstance().onCreate(activity, savedInstanceState);
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onStart</span><span class="hljs-params">(Activity activity)</span> </span>{
PluginManager.getInstance().onStart(activity);
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onResume</span><span class="hljs-params">(Activity activity)</span> </span>{
PluginManager.getInstance().onResume(activity);
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onPause</span><span class="hljs-params">(Activity activity)</span> </span>{
PluginManager.getInstance().onPause(activity);
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onStop</span><span class="hljs-params">(Activity activity)</span> </span>{
PluginManager.getInstance().onStop(activity);
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onRestart</span><span class="hljs-params">(Activity activity)</span> </span>{
PluginManager.getInstance().onRestart(activity);
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onDestroy</span><span class="hljs-params">(Activity activity)</span> </span>{
PluginManager.getInstance().onDestroy(activity);
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onNewIntent</span><span class="hljs-params">(Activity activity, Intent intent)</span> </span>{
PluginManager.getInstance().onNewIntent(activity,intent);
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onActivityResult</span><span class="hljs-params">(Activity activity, <span class="hljs-keyword">int</span> requestCode, <span class="hljs-keyword">int</span> resultCode, Intent data)</span> </span>{
PluginManager.getInstance().onActivityResult(activity, requestCode, requestCode, data);
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onRequestPermissionsResult</span><span class="hljs-params">(Activity activity, <span class="hljs-keyword">int</span> requestCode, String[] permissions, <span class="hljs-keyword">int</span>[] grantResults)</span> </span>{
PluginManager.getInstance().onRequestPermissionsResult(activity,requestCode,permissions,grantResults);
}
}
2、抽象的功能插件Plugin类,主要是面向第三方SDK设计的,预定义生命周期方法。具体功能实现接口根据功能设计。
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
public class Plugin implements LifeCycleInterface, ProguardInterface {
复制代码<span class="hljs-keyword">public</span> PluginBeanList.PluginBean pluginBean;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">boolean</span> hasInited;
<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">initPlugin</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">if</span> (hasInited) {
<span class="hljs-keyword">return</span>;
}
hasInited = <span class="hljs-keyword">true</span>;
}
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">return</span> <span class="hljs-string">"Plugin{"</span> + <span class="hljs-string">"pluginMessage="</span> + pluginBean + <span class="hljs-string">", hasInited="</span> + hasInited + <span class="hljs-string">'}'</span>;
}
<span class="hljs-comment">/****************************************生命周期方法*********************************************/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(Context context, Bundle savedInstanceState)</span> </span>{}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onStart</span><span class="hljs-params">(Context context)</span> </span>{}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onResume</span><span class="hljs-params">(Context context)</span> </span>{}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onPause</span><span class="hljs-params">(Context context)</span> </span>{}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onStop</span><span class="hljs-params">(Context context)</span> </span>{}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onRestart</span><span class="hljs-params">(Context context)</span> </span>{}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onDestroy</span><span class="hljs-params">(Context context)</span> </span>{}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onNewIntent</span><span class="hljs-params">(Context context, Intent intent)</span></span>{}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onActivityResult</span><span class="hljs-params">(Context context, <span class="hljs-keyword">int</span> requestCode, <span class="hljs-keyword">int</span> resultCode, Intent data)</span> </span>{}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onRequestPermissionsResult</span><span class="hljs-params">(Context context, <span class="hljs-keyword">int</span> requestCode, String[] permissions, <span class="hljs-keyword">int</span>[] grantResults)</span> </span>{}
}
3、抽象的渠道Channel类,主要是面向渠道SDK设计的,主要分为业务必须接口和非业务必须接口。必须业务接口设计为抽象,子类必须实现的。
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
/**
* 用于描述渠道SDK的顶层接口
*/
public abstract class Channel extends ChannelListenerImpl implements LifeCycleInterface, ProguardInterface {
复制代码<span class="hljs-comment">/***************************** Channel 加载必须接口 **********************************/</span>
<span class="hljs-comment">/**
* 实例渠道插件对象,必须实现
*/</span>
<span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">initChannel</span><span class="hljs-params">()</span></span>;
<span class="hljs-keyword">public</span> ChannelBeanList.ChannelBean channelBean;
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">return</span> <span class="hljs-string">"Channel{"</span> + <span class="hljs-string">"channelBean="</span> + channelBean +<span class="hljs-string">'}'</span>;
}
<span class="hljs-comment">/****************************** 必须业务逻辑接口 ****************************/</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String PARAMS_OAUTH_TYPE = <span class="hljs-string">"PARAMS_OAUTH_TYPE"</span>;
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String PARAMS_OAUTH_URL = <span class="hljs-string">"PARAMS_OAUTH_URL"</span>;
<span class="hljs-comment">/**
* 返回渠道的ID(用于识别渠道)
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> String <span class="hljs-title">getChannelID</span><span class="hljs-params">()</span></span>;
<span class="hljs-comment">/**
* 由于个别渠道只简单实现登录、支付接口,
* 对外提供该接口给CP判断该接口是否已实现
* <span class="hljs-doctag">@param</span> FuncType
* <span class="hljs-doctag">@return</span>
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isSupport</span><span class="hljs-params">(<span class="hljs-keyword">int</span> FuncType)</span></span>;
<span class="hljs-comment">/**
* 渠道SDK初始化
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">init</span><span class="hljs-params">(Context context, HashMap<String,Object> initMap, CallBackListener initCallBackListener)</span></span>;
<span class="hljs-comment">/**
* 渠道SDK登录
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">login</span><span class="hljs-params">(Context context, HashMap<String,Object> loginMap, CallBackListener loginCallBackListener)</span></span>;
<span class="hljs-comment">/**
* 渠道切换账号
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">switchAccount</span><span class="hljs-params">(Context context, CallBackListener changeAccountCallBackLister)</span></span>;
<span class="hljs-comment">/**
* 渠道SDK注销账号
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">logout</span><span class="hljs-params">(Context context, CallBackListener logoutCallBackLister)</span></span>;
<span class="hljs-comment">/**
* 渠道SDK支付
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">pay</span><span class="hljs-params">(Context context, HashMap<String,Object> payMap, CallBackListener payCallBackListener)</span></span>;
<span class="hljs-comment">/**
* 渠道SDK退出
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">exit</span><span class="hljs-params">(Context context, CallBackListener exitCallBackLister)</span></span>;
<span class="hljs-comment">/****************************** 非必须业务逻辑接口 ****************************/</span>
<span class="hljs-comment">/**
* 返回渠道版本号
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getChannelVersion</span><span class="hljs-params">()</span></span>{
<span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
}
<span class="hljs-comment">/**
* 渠道SDK个人中心
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">enterPlatform</span><span class="hljs-params">(Context context, CallBackListener enterPlatformCallBackLister)</span></span>{}
<span class="hljs-comment">/**
* 显示渠道SDK悬浮窗
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">showFloatView</span><span class="hljs-params">(Context context)</span></span>{}
<span class="hljs-comment">/**
* 关闭渠道SDK悬浮窗
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">dismissFloatView</span><span class="hljs-params">(Context context)</span></span>{}
<span class="hljs-comment">/**
* 渠道SDK上报数据
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">reportData</span><span class="hljs-params">(Context context, HashMap<String,Object> dataMap)</span></span>{}
<span class="hljs-comment">/**
* 横竖屏
* <span class="hljs-doctag">@return</span> true为横屏,false为竖屏
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">getOrientation</span><span class="hljs-params">(Context context)</span></span>{
<span class="hljs-keyword">boolean</span> isLandscape = context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
<span class="hljs-keyword">return</span> isLandscape;
}
<span class="hljs-comment">/****************************** 非业务逻辑 生命周期接口 ****************************/</span>
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(Context context, Bundle savedInstanceState)</span> </span>{}
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onStart</span><span class="hljs-params">(Context context)</span> </span>{}
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onResume</span><span class="hljs-params">(Context context)</span> </span>{}
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onPause</span><span class="hljs-params">(Context context)</span> </span>{}
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onStop</span><span class="hljs-params">(Context context)</span> </span>{}
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onRestart</span><span class="hljs-params">(Context context)</span> </span>{}
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onDestroy</span><span class="hljs-params">(Context context)</span> </span>{}
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onNewIntent</span><span class="hljs-params">(Context context, Intent intent)</span> </span>{}
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onActivityResult</span><span class="hljs-params">(Context context, <span class="hljs-keyword">int</span> requestCode, <span class="hljs-keyword">int</span> resultCode, Intent data)</span> </span>{}
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onRequestPermissionsResult</span><span class="hljs-params">(Context context, <span class="hljs-keyword">int</span> requestCode, String[] permissions, <span class="hljs-keyword">int</span>[] grantResults)</span> </span>{}
}
配置文件的bean类
配置文件的bean类,通过反射加载Project / Plugin / Channel具体实现对象。示例展示Project,其他两个是类似的,详看项目Demo。
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
public class ProjectBeanList extends ProguardObject{
复制代码<span class="hljs-keyword">private</span> List<ProjectBean> project;<span class="hljs-comment">//注意解析的名字要跟文件一致,不然会导致解析错误</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> List<ProjectBean> <span class="hljs-title">getProject</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">return</span> project;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setProject</span><span class="hljs-params">(List<ProjectBean> project)</span> </span>{
<span class="hljs-keyword">this</span>.project = project;
}
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProjectBean</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ProguardObject</span></span>{
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String TAG = <span class="hljs-string">"ProjectBean"</span>;
<span class="hljs-comment">/**
* 反射插件的单例模式方法
* 返回的插件可能为空
* <span class="hljs-doctag">@return</span>
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> Project <span class="hljs-title">invokeGetInstance</span><span class="hljs-params">()</span> </span>{
Project p = <span class="hljs-keyword">null</span>;
Class<?> glass = <span class="hljs-keyword">null</span>;
<span class="hljs-keyword">if</span> (TextUtils.isEmpty(class_name)) {
LogUtils.debug_w(TAG, <span class="hljs-string">"invokeGetInstance: the class_name is blank"</span>);
<span class="hljs-keyword">return</span> p;
}
<span class="hljs-keyword">try</span> {
glass = Class.forName(class_name);
} <span class="hljs-keyword">catch</span> (ClassNotFoundException e) {
LogUtils.debug_w(TAG, <span class="hljs-string">"invokeGetInstance: "</span> + <span class="hljs-string">"do not find "</span> + class_name);
}
<span class="hljs-keyword">try</span> {
<span class="hljs-comment">//尝试调用getInstance</span>
Method m = glass.getDeclaredMethod(<span class="hljs-string">"getInstance"</span>, <span class="hljs-keyword">new</span> Class<?>[]{});
m.setAccessible(<span class="hljs-keyword">true</span>);
p = (Project) m.invoke(<span class="hljs-keyword">null</span>, <span class="hljs-keyword">new</span> Object[]{});
} <span class="hljs-keyword">catch</span> (NoSuchMethodException e1) {
<span class="hljs-comment">//调用getInstance失败后,尝试new其对象</span>
<span class="hljs-keyword">try</span> {
p = (Project) glass.newInstance();
} <span class="hljs-keyword">catch</span> (Exception exception) {
LogUtils.debug_w(TAG, <span class="hljs-string">"glass.newInstance(): "</span> + <span class="hljs-string">"do not find "</span> + class_name);
}
} <span class="hljs-keyword">catch</span> (Exception exception) {
LogUtils.debug_w(TAG, <span class="hljs-string">"glass.getInstance(): "</span> + <span class="hljs-string">"do not find "</span> + class_name);
}
<span class="hljs-keyword">if</span> (p == <span class="hljs-keyword">null</span>) {
LogUtils.debug_w(TAG, class_name + <span class="hljs-string">" is empty."</span>);
} <span class="hljs-keyword">else</span> {
p.projectBean = <span class="hljs-keyword">this</span>;
}
<span class="hljs-keyword">return</span> p;
}
<span class="hljs-comment">/**
* project_name : 项目名称
* class_name : 项目入口类
* description : 项目描述
* version : 版本信息
*/</span>
<span class="hljs-keyword">private</span> String project_name;
<span class="hljs-keyword">private</span> String class_name;
<span class="hljs-keyword">private</span> String description;
<span class="hljs-keyword">private</span> String version;
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getProject_name</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">return</span> project_name;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setProject_name</span><span class="hljs-params">(String plugin_name)</span> </span>{
<span class="hljs-keyword">this</span>.project_name = plugin_name;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getClass_name</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">return</span> class_name;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setClass_name</span><span class="hljs-params">(String class_name)</span> </span>{
<span class="hljs-keyword">this</span>.class_name = class_name;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getDescription</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">return</span> description;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setDescription</span><span class="hljs-params">(String description)</span> </span>{
<span class="hljs-keyword">this</span>.description = description;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getVersion</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">return</span> version;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setVersion</span><span class="hljs-params">(String version)</span> </span>{
<span class="hljs-keyword">this</span>.version = version;
}
<span class="hljs-meta">@Override</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">toString</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">return</span> <span class="hljs-string">"ProjectBean{"</span> +
<span class="hljs-string">" project_name='"</span> + project_name + <span class="hljs-string">'''</span> +
<span class="hljs-string">", class_name='"</span> + class_name + <span class="hljs-string">'''</span> +
<span class="hljs-string">", description='"</span> + description + <span class="hljs-string">'''</span> +
<span class="hljs-string">", version='"</span> + version + <span class="hljs-string">'''</span> +
<span class="hljs-string">'}'</span>;
}
}
}
配置管理类
主要加载配置文件及对外提供加载接口和实现部分逻辑控制。(示例展示Project,其他两个是类似的,详看项目Demo。注意:Plugin需遍历生命周期加载N个功能插件的生命周期。)
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
public class ProjectManager {
复制代码<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String TAG = <span class="hljs-string">"ProjectManager"</span>;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> String PROJECT_CONFIG = <span class="hljs-string">"Project_config.txt"</span>;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Project project;
<span class="hljs-keyword">private</span> HashMap<String, ProjectBeanList.ProjectBean> projectBeans = <span class="hljs-keyword">new</span> HashMap<>();
<span class="hljs-comment">/********************* 同步锁双重检测机制实现单例模式(懒加载)********************/</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">volatile</span> <span class="hljs-keyword">static</span> ProjectManager projectManager;
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> ProjectManager <span class="hljs-title">init</span><span class="hljs-params">(Context context)</span> </span>{
<span class="hljs-keyword">if</span> (projectManager == <span class="hljs-keyword">null</span>) {
<span class="hljs-keyword">synchronized</span> (ProjectManager.class) {
<span class="hljs-keyword">if</span> (projectManager == <span class="hljs-keyword">null</span>) {
projectManager = <span class="hljs-keyword">new</span> ProjectManager(context);
}
}
}
<span class="hljs-keyword">return</span> projectManager;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> ProjectManager <span class="hljs-title">getInstance</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">return</span> projectManager;
}
<span class="hljs-comment">/********************* 同步锁双重检测机制实现单例模式 ********************/</span>
<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">ProjectManager</span><span class="hljs-params">(Context context)</span> </span>{
parse(context, PROJECT_CONFIG);
}
<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">parse</span><span class="hljs-params">(Context context, String pluginFilePath)</span> </span>{
<span class="hljs-comment">//从配置文件中,读取插件配置</span>
StringBuilder projectContent = FileUtils.readAssetsFile(context, pluginFilePath);
String strProjectContent = String.valueOf(projectContent);
<span class="hljs-comment">//进行解析</span>
Gson gson = <span class="hljs-keyword">new</span> Gson();
<span class="hljs-keyword">if</span> (!TextUtils.isEmpty(strProjectContent)) {
<span class="hljs-keyword">try</span> {
ProjectBeanList projectBeanList = gson.fromJson(strProjectContent, ProjectBeanList.class);
<span class="hljs-keyword">if</span> (projectBeanList.getProject() != <span class="hljs-keyword">null</span> && projectBeanList.getProject().size() != <span class="hljs-number">0</span>) {
<span class="hljs-comment">//如果解析结果无误,载入到listPluginBean中去</span>
<span class="hljs-keyword">for</span> (ProjectBeanList.ProjectBean projectBean : projectBeanList.getProject()) {
projectBeans.put(projectBean.getProject_name(), projectBean);
}
<span class="hljs-comment">//打印解析结果</span>
LogUtils.debug_i(TAG, PROJECT_CONFIG +<span class="hljs-string">" parse: n"</span> + projectBeans.toString());
} <span class="hljs-keyword">else</span> {
<span class="hljs-comment">//解析结果出错</span>
LogUtils.e(TAG, PROJECT_CONFIG + <span class="hljs-string">" parse error."</span>);
}
} <span class="hljs-keyword">catch</span> (Exception e) {
<span class="hljs-comment">//解析结果出错</span>
LogUtils.e(TAG, PROJECT_CONFIG + <span class="hljs-string">" parse exception."</span>);
e.printStackTrace();
}
}<span class="hljs-keyword">else</span> {
LogUtils.e(TAG, PROJECT_CONFIG + <span class="hljs-string">" parse is blank."</span>);
}
}
<span class="hljs-keyword">private</span> <span class="hljs-keyword">boolean</span> hasLoaded;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> HashMap<String, Project> ProjectLists = <span class="hljs-keyword">new</span> HashMap<String, Project>();
<span class="hljs-comment">/**
* 加载所有的Project,可能存在多个项目
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">loadAllProjects</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">if</span> (hasLoaded) {
<span class="hljs-keyword">return</span>;
}
HashMap<String, ProjectBeanList.ProjectBean> entries = projectBeans;
Set<String> set = entries.keySet();
<span class="hljs-keyword">for</span> (String key : set) {
loadProject(key);
}
LogUtils.debug_i(TAG, <span class="hljs-string">"loadAllProjects:"</span> + ProjectLists.toString());
hasLoaded = <span class="hljs-keyword">true</span>;
}
<span class="hljs-comment">/**
* 加载一个项目,返回的Project可能为空
*
* <span class="hljs-doctag">@param</span> projectName
* <span class="hljs-doctag">@return</span>
* <span class="hljs-doctag">@throws</span> RuntimeException
*/</span>
<span class="hljs-function"><span class="hljs-keyword">private</span> Project <span class="hljs-title">loadProject</span><span class="hljs-params">(String projectName)</span> <span class="hljs-keyword">throws</span> RuntimeException </span>{
<span class="hljs-comment">// 1.查看从配置文件中读取的插件列表,是否存在此插件</span>
HashMap<String, ProjectBeanList.ProjectBean> entries = projectBeans;
ProjectBeanList.ProjectBean projectBean = entries.get(projectName);
<span class="hljs-keyword">if</span> (projectBean == <span class="hljs-keyword">null</span>) {
LogUtils.debug_i(TAG, <span class="hljs-string">"The project ["</span> + projectName + <span class="hljs-string">"] does not exists in "</span> + PROJECT_CONFIG);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
}
Project project = <span class="hljs-keyword">null</span>;
<span class="hljs-comment">// 2.调用其单例模式方法</span>
project = projectBean.invokeGetInstance();
<span class="hljs-keyword">if</span> (project != <span class="hljs-keyword">null</span>) {
<span class="hljs-comment">// 3.反射初始化插件</span>
project.initProject();
<span class="hljs-comment">// 4.将已加载好的插件,添加到插件列表中去</span>
ProjectLists.put(projectName, project);
}
<span class="hljs-keyword">return</span> project;
}
<span class="hljs-comment">/**
* 获取特定项目
* 可能为空
*
* <span class="hljs-doctag">@param</span> projectName
* <span class="hljs-doctag">@return</span>
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> Project <span class="hljs-title">getProject</span><span class="hljs-params">(String projectName)</span> </span>{
<span class="hljs-keyword">if</span> (!hasLoaded) {
LogUtils.debug_i(TAG, <span class="hljs-string">"getProject: "</span> + projectName + <span class="hljs-string">"Project not loaded yet"</span>);
<span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
}
Project project = <span class="hljs-keyword">null</span>;
HashMap<String, Project> entries = ProjectLists;
project = entries.get(projectName);
<span class="hljs-keyword">return</span> project;
}
}
项目回调设计
任何一个项目都会存在模块之间的调用,任何事件的事件流都会有事件结果回调。都会涉及到回调机制。
相关原理可参考下这篇文章: Java回调机制解读简单介绍下项目的回调设计思路:
定义基类的回调接口,定义成功和失败回调,失败回调可以通过错误码和描述信息来区分错误事件的详细信息。这里有个小技巧就是定义返回错误码,CP就可以根据错误码做相关的界面UI提示,这里就可以偷懒尽量避免做多语言和多UI处理啦。
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
public interface CallBackListener<T> {
复制代码<span class="hljs-comment">/**
* 成功回调
* <span class="hljs-doctag">@param</span> t 详细信息
*/</span>
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">onSuccess</span><span class="hljs-params">(T t)</span></span>;
<span class="hljs-comment">/**
* 失败回调
*
* <span class="hljs-doctag">@param</span> code 错误码
* <span class="hljs-doctag">@param</span> msg 错误详细描述信息
*/</span>
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">onFailure</span><span class="hljs-params">(<span class="hljs-keyword">int</span> code, String msg)</span></span>;
}
项目数据设计
一般项目都会涉及到数据的交互与数据存储,数据存储一般常用的数据存储方式SharedPreferences存储、文件存储、SQLite数据库存储、ContentProvider存储、网络存储等混合使用。相关的存储方式及使用这里就不介绍了。由于游戏SDK涉及到的数据量不大,主要以内存存储和SharedPreferences存储和文件存储为主。
PS:如果数据设计到多进程数据交互,建议使用ContentProvider存储方式。简单介绍下内存缓存的思路:
定义全局的集合,通过单例来管理相关的数据存储和读取接口。
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
public class BaseCache {
复制代码<span class="hljs-keyword">private</span> Application mAppContext;
<span class="hljs-function"><span class="hljs-keyword">public</span> Context <span class="hljs-title">getApplication</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">return</span> mAppContext;
}
<span class="hljs-comment">/********************* 同步锁双重检测机制实现单例模式(懒加载)********************/</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">volatile</span> <span class="hljs-keyword">static</span> BaseCache sCache;
<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">BaseCache</span><span class="hljs-params">(Application appContext)</span> </span>{
mAppContext = appContext;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> BaseCache <span class="hljs-title">getInstance</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">if</span> (sCache == <span class="hljs-keyword">null</span>) {
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(<span class="hljs-string">"get(Context) never called"</span>);
}
<span class="hljs-keyword">return</span> sCache;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> BaseCache <span class="hljs-title">init</span><span class="hljs-params">(Application cxt)</span> </span>{
<span class="hljs-keyword">if</span> (sCache == <span class="hljs-keyword">null</span>) {
<span class="hljs-keyword">synchronized</span> (BaseCache.class) {
<span class="hljs-keyword">if</span> (sCache == <span class="hljs-keyword">null</span>) {
sCache = <span class="hljs-keyword">new</span> BaseCache(cxt);
}
}
}
<span class="hljs-keyword">return</span> sCache;
}
<span class="hljs-comment">/********************* 同步锁双重检测机制实现单例模式(懒加载)********************/</span>
<span class="hljs-comment">/**
* hashMap是线程不安全的,做全局缓存时,用锁来保证存储值
*/</span>
<span class="hljs-keyword">private</span> HashMap<String, Object> mConfigs = <span class="hljs-keyword">new</span> HashMap<>();
<span class="hljs-keyword">private</span> ReentrantLock mLock = <span class="hljs-keyword">new</span> ReentrantLock();
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">put</span><span class="hljs-params">(String key, Object value)</span></span>{
mLock.lock();
mConfigs.put(key,value);
mLock.unlock();
}
<span class="hljs-function"><span class="hljs-keyword">public</span> Object <span class="hljs-title">get</span><span class="hljs-params">(String key)</span></span>{
mLock.lock();
Object object = mConfigs.get(key);
mLock.unlock();
<span class="hljs-keyword">return</span> object;
}
项目域名设计
因为SDK涉及到多个项目,每个项目肯定是会有不同的域名的,并且同一个项目也存在测试环境、沙盒环境、正式环境的域名区分,域名设计的主要的作用是统一管理域名及方便后续不同的项目来回切换不同的域名地址,这是比较重要的。
简单说下域名的设计思路:
一般修改域名不涉及到代码的修改,对外的包如何动态的修改域名设置呢?
1、通过后台配置预设域名,但是后台的设置会影响到线上环境。慎重。
2、通过包体的配置文件来读取域名,开发人员可以通过反编译包体修改域名调试代码。
PS:开发人员根据需求设计,但是切记要统一管理,方便维护。
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class UrlConfig {
复制代码<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> final String TAG = <span class="hljs-string">"UrlConfig"</span>;
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> String Project_SDKUrl; <span class="hljs-comment">//url</span>
<span class="hljs-comment">//项目的基础ip域名地址</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> String Project_BaseApi = <span class="hljs-string">"https://www.baidu.com/"</span>;
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">getSdkUrl</span><span class="hljs-params">()</span></span>{
<span class="hljs-keyword">return</span> Project_SDKUrl;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">initUrl</span><span class="hljs-params">()</span></span>{
<span class="hljs-comment">//通过配置读取域名</span>
String SDK_Base_Url = BaseCache.getInstance().getSdkUrl();
<span class="hljs-keyword">if</span> (!TextUtils.isEmpty(SDK_Base_Url)){<span class="hljs-comment">//通过配置文件来修改域名</span>
Project_BaseApi = SDK_Base_Url;
}
LogUtils.debug_d(TAG,Project_SDKUrl);
}
<span class="hljs-comment">/**
* 预设设置修改当前网络的请求域名接口
* 思考特殊的场景:
* 多个项目交叉调用时,域名地址不一样,可通过修改临时域名做请求。
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">getReSetUrl</span><span class="hljs-params">(String sdk_type, String channelId)</span></span>{
String tempUrl = <span class="hljs-string">""</span>;
<span class="hljs-keyword">return</span> tempUrl; <span class="hljs-comment">//返回临时的域名</span>
}
}
项目混淆设计
SDK是对外提供功能的,而且从安全性考虑的话,对外提供的包体都应该是经常各种混淆和加密处理的。不然被攻击的可能性就很高了。
项目的设计是定义顶层的类或接口,具体的实现类继承该类或者实现该接口就不混淆了。关于相关的混淆规则及配置可参考: Android混淆打包那些事儿
1
2
3
4
5
6
/**
* 定义基础混淆接口
*/
public interface ProguardInterface {
}
/**
- 定义基础混淆对象
*/
public class ProguardObject {
}
项目三方库的封装设计
在实际开发中,会使用到大量的三方库,避免重复造轮子,特别是网络库、图片加载图等。但是,开源库过几年就可能会有更好的开源库,或者原有的开源库有局限性满足不了现有的项目需求,需要拓展或者替换的新的框架。所以需要做封装处理,避免后续替换改动太大。可参考:
对于有多种可替代解决方案的业务逻辑,提供一种快速替换方法PS:项目中封装的是Volley,根据实际项目做了简单网络库的封装,不做任何商业模块使用,慎用!
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
public class RequestExecutor {
复制代码<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> final String GET = <span class="hljs-string">"GET"</span>;
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> final String POST = <span class="hljs-string">"POST"</span>;
<span class="hljs-keyword">private</span> IRequestManager iRequestManager;
<span class="hljs-keyword">private</span> String method;
<span class="hljs-keyword">private</span> String url;
<span class="hljs-keyword">private</span> String header;
<span class="hljs-keyword">private</span> String userAgent;
<span class="hljs-keyword">private</span> Map<String,Object> params;
<span class="hljs-keyword">private</span> RequestCallback requestCallback;
<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">RequestExecutor</span><span class="hljs-params">(RequestExecutor.Builder builder)</span></span>{
<span class="hljs-keyword">this</span>.method = builder.method;
<span class="hljs-keyword">this</span>.url = builder.url;
<span class="hljs-keyword">this</span>.header = builder.header;
<span class="hljs-keyword">this</span>.userAgent = builder.userAgent;
<span class="hljs-keyword">this</span>.params = builder.params;
<span class="hljs-keyword">this</span>.requestCallback = builder.requestCallback;
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">startRequest</span><span class="hljs-params">()</span></span>{
<span class="hljs-comment">/**
* 网络框架要替换成别的时候,实现具体封装就OK了,并修改具体实现
* 比如换成okhttp写法 :return new OkHttpRequestManager();
*/</span>
iRequestManager = <span class="hljs-keyword">new</span> VolleyRequestManager();
iRequestManager.setHeader(header);
iRequestManager.setUserAgent(userAgent);
<span class="hljs-keyword">if</span> (RequestExecutor.GET.equals(method)){
iRequestManager.get(url,params,requestCallback);
}<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (RequestExecutor.POST.equals(method)){
iRequestManager.post(url,params,requestCallback);
}
}
<span class="hljs-comment">/**
* 取消当前的网络请求,
*/</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">cancel</span><span class="hljs-params">()</span></span>{
iRequestManager.cancel();
}
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Builder</span>{</span>
<span class="hljs-keyword">private</span> String method;
<span class="hljs-keyword">private</span> String url;
<span class="hljs-keyword">private</span> String header;
<span class="hljs-keyword">private</span> String userAgent;
<span class="hljs-keyword">private</span> Map<String,Object> params;
<span class="hljs-keyword">private</span> RequestCallback requestCallback;
<span class="hljs-function"><span class="hljs-keyword">public</span> RequestExecutor <span class="hljs-title">build</span><span class="hljs-params">()</span></span>{
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> RequestExecutor(<span class="hljs-keyword">this</span>);
}
<span class="hljs-keyword">public</span> RequestExecutor.<span class="hljs-function">Builder <span class="hljs-title">setMethod</span><span class="hljs-params">(String method)</span></span>{
<span class="hljs-keyword">this</span>.method = method;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
<span class="hljs-keyword">public</span> RequestExecutor.<span class="hljs-function">Builder <span class="hljs-title">setUrl</span><span class="hljs-params">(String url)</span></span>{
<span class="hljs-keyword">this</span>.url = url;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
<span class="hljs-keyword">public</span> RequestExecutor.<span class="hljs-function">Builder <span class="hljs-title">setHeader</span><span class="hljs-params">(String header)</span></span>{
<span class="hljs-keyword">this</span>.header = header;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
<span class="hljs-keyword">public</span> RequestExecutor.<span class="hljs-function">Builder <span class="hljs-title">setUserAgent</span><span class="hljs-params">(String userAgent)</span></span>{
<span class="hljs-keyword">this</span>.userAgent = userAgent;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
<span class="hljs-keyword">public</span> RequestExecutor.<span class="hljs-function">Builder <span class="hljs-title">setParams</span><span class="hljs-params">(HashMap<String,Object> params)</span></span>{
<span class="hljs-keyword">this</span>.params = params;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
<span class="hljs-keyword">public</span> RequestExecutor.<span class="hljs-function">Builder <span class="hljs-title">setRequestCallback</span><span class="hljs-params">(RequestCallback requestCallback)</span></span>{
<span class="hljs-keyword">this</span>.requestCallback = requestCallback;
<span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
}
}
}
结语:
最后
以上就是无心月亮最近收集整理的关于手游SDK — 第三篇(SDK架构设计代码实现篇(上)- 基础库)项目结构搭建项目代码实现的全部内容,更多相关手游SDK内容请搜索靠谱客的其他文章。
发表评论 取消回复