Skip to content

Commit b85942b

Browse files
committed
cocos2d-js 3.0 jsb环境调用底层java代码
1 parent ab88939 commit b85942b

File tree

1 file changed

+285
-0
lines changed

1 file changed

+285
-0
lines changed

android-jsb.md

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
# cocos2d-js 3.0 jsb环境调用底层java代码
2+
3+
------
4+
5+
## 1. C++端工作
6+
7+
------
8+
9+
环境还是cocos2d-js 3.0 beta,准备给javascript加一个osInfo的函数,来判断用户的系统信息以及网络信息。
10+
11+
首先在项目目录下的frameworks/runtime-src/Classes/目录添加jsb_os_info.hpp,内容如下:
12+
13+
```
14+
#include "cocos2d_specifics.hpp"
15+
#include "cocos2d.h"
16+
17+
#include <jni.h>
18+
#include "platform/android/jni/JniHelper.h"
19+
20+
/**c++调用java中的方法*/
21+
std::string call_java() {
22+
cocos2d::JniMethodInfo osInfoBoard;
23+
24+
bool isHave = cocos2d::JniHelper::getStaticMethodInfo(
25+
osInfoBoard,
26+
"org/cocos2dx/javascript/AppActivity", // 改的话对应frameworks/runtime-src/proj.android/src下修改
27+
"osInfoBoardStatic",
28+
"()Ljava/lang/String;"
29+
);
30+
if (!isHave) {
31+
cocos2d::CCLog("jni:osInfoBoardStatic false");
32+
return NULL;
33+
}
34+
35+
jstring jstr = (jstring)osInfoBoard.env->CallStaticObjectMethod(osInfoBoard.classID, osInfoBoard.methodID);
36+
return cocos2d::JniHelper::jstring2string(jstr);
37+
}
38+
39+
/**定义用来处理js请求的函数:
40+
*cx:JS的上下文
41+
*argc:参数的个数
42+
*vp:具体的参数列表
43+
*/
44+
bool jsb_os_info(JSContext *cx, uint32_t argc, JS::Value *vp) {
45+
jsval ret = std_string_to_jsval(cx, call_java());
46+
JS_SET_RVAL(cx, vp, ret);
47+
48+
return true;
49+
}
50+
51+
/**在AppDelegate.cpp中被注册的函数:sc->addRegisterCallback(register_jsb_os_info);*/
52+
void register_jsb_os_info(JSContext* cx, JSObject* obj) {
53+
//绑定:“osInfo”为开发给js调用的方法
54+
JS_DefineFunction(cx, obj, "osInfo", jsb_os_info, 0, 0);
55+
}
56+
57+
```
58+
59+
然后修改同目录下AppDelegate.cpp文件,添加相应的引用和注册javascript函数:
60+
61+
```
62+
...
63+
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
64+
#include "jsb_os_info.hpp"
65+
#include "platform/android/CCJavascriptJavaBridge.h"
66+
#endif
67+
...
68+
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
69+
sc->addRegisterCallback(register_jsb_os_info);
70+
sc->addRegisterCallback(JavascriptJavaBridge::_js_register);
71+
#endif
72+
sc->start();
73+
...
74+
```
75+
76+
注意顺序,其他非相关代码都省略了。
77+
78+
## 2. java端工作
79+
80+
------
81+
82+
修改项目目录frameworks/runtime-src/proj.android/src/org/cocos2dx/javascript/AppActivity.java,这个程序本来是空的,增加代码如下:
83+
84+
```
85+
package org.cocos2dx.javascript;
86+
87+
import org.cocos2dx.lib.Cocos2dxActivity;
88+
import android.content.Context;
89+
import android.net.ConnectivityManager;
90+
import android.net.NetworkInfo;
91+
import android.net.wifi.WifiManager;
92+
import android.net.wifi.WifiInfo;
93+
import android.telephony.TelephonyManager;
94+
95+
public class AppActivity extends Cocos2dxActivity {
96+
private static Context mContext;
97+
98+
private static String formatIp(int ip) {
99+
return ( ip & 0xFF ) + "." +
100+
((ip >> 8 ) & 0xFF) + "." +
101+
((ip >> 16 ) & 0xFF) + "." +
102+
((ip >> 24 ) & 0xFF) ;
103+
}
104+
105+
public static NetworkInfo getNetworkInfo(Context context){
106+
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
107+
return cm.getActiveNetworkInfo();
108+
}
109+
110+
public static boolean isConnected(Context context){
111+
NetworkInfo info = AppActivity.getNetworkInfo(context);
112+
return (info != null && info.isConnected());
113+
}
114+
115+
public static String getWifi(Context context){
116+
NetworkInfo info = AppActivity.getNetworkInfo(context);
117+
if (info != null && info.isConnected() && info.getType() == ConnectivityManager.TYPE_WIFI) {
118+
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
119+
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
120+
121+
return "Wifi|" + WifiManager.calculateSignalLevel(wifiInfo.getRssi(), 10) + "|" + wifiInfo.getLinkSpeed();
122+
} else {
123+
return "";
124+
}
125+
}
126+
127+
public static String getMobile(Context context){
128+
NetworkInfo info = AppActivity.getNetworkInfo(context);
129+
if (info != null && info.isConnected() && info.getType() == ConnectivityManager.TYPE_MOBILE) {
130+
String mobileType = AppActivity.getMobileType(info.getSubtype());
131+
132+
return "Mobile|" + mobileType;
133+
} else {
134+
return "";
135+
}
136+
}
137+
138+
public static String getMobileType(int subType){
139+
switch(subType){
140+
case TelephonyManager.NETWORK_TYPE_1xRTT:
141+
return "1xRTT"; // ~ 50-100 kbps
142+
case TelephonyManager.NETWORK_TYPE_CDMA:
143+
return "CDMA"; // ~ 14-64 kbps
144+
case TelephonyManager.NETWORK_TYPE_EDGE:
145+
return "EDGE"; // ~ 50-100 kbps
146+
case TelephonyManager.NETWORK_TYPE_EVDO_0:
147+
return "EVDO_0"; // ~ 400-1000 kbps
148+
case TelephonyManager.NETWORK_TYPE_EVDO_A:
149+
return "EVDO_A"; // ~ 600-1400 kbps
150+
case TelephonyManager.NETWORK_TYPE_GPRS:
151+
return "GPRS"; // ~ 100 kbps
152+
case TelephonyManager.NETWORK_TYPE_HSDPA:
153+
return "HSDPA"; // ~ 2-14 Mbps
154+
case TelephonyManager.NETWORK_TYPE_HSPA:
155+
return "HSPA"; // ~ 700-1700 kbps
156+
case TelephonyManager.NETWORK_TYPE_HSUPA:
157+
return "HSUPA"; // ~ 1-23 Mbps
158+
case TelephonyManager.NETWORK_TYPE_UMTS:
159+
return "UMTS"; // ~ 400-7000 kbps
160+
/*
161+
* Above API level 7, make sure to set android:targetSdkVersion
162+
* to appropriate level to use these
163+
*/
164+
//case TelephonyManager.NETWORK_TYPE_EHRPD: // API level 11
165+
case 14:
166+
return "EHRPD"; // ~ 1-2 Mbps
167+
case TelephonyManager.NETWORK_TYPE_EVDO_B: // API level 9
168+
return "EVDO_B"; // ~ 5 Mbps
169+
//case TelephonyManager.NETWORK_TYPE_HSPAP: // API level 13
170+
case 15: // TelephonyManager.NETWORK_TYPE_HSPAP
171+
return "HSPAP"; // ~ 10-20 Mbps
172+
case TelephonyManager.NETWORK_TYPE_IDEN: // API level 8
173+
return "IDEN"; // ~25 kbps
174+
//case TelephonyManager.NETWORK_TYPE_LTE: // API level 11
175+
case 13: // TelephonyManager.NETWORK_TYPE_LTE
176+
return "LTE"; // ~ 10+ Mbps
177+
// Unknown
178+
case TelephonyManager.NETWORK_TYPE_UNKNOWN:
179+
default:
180+
return "UNKNOWN";
181+
}
182+
}
183+
184+
public static String getProvidersName(Context context) {
185+
try {
186+
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
187+
String operator = telephonyManager.getSimOperator();
188+
if (operator == null || operator.equals("")) {
189+
return "unknown";
190+
}
191+
192+
if (operator.startsWith("46000") || operator.startsWith("46002")) {
193+
return "cm";
194+
} else if (operator.startsWith("46001")) {
195+
return "cu";
196+
} else if (operator.startsWith("46003")) {
197+
return "ct";
198+
} else {
199+
return "unknown";
200+
}
201+
} catch (Exception e) {
202+
return "error";
203+
}
204+
}
205+
206+
public static String osInfoBoardStatic() {
207+
mContext = AppActivity.getContext();
208+
String info = android.os.Build.MODEL + "|Android|" + android.os.Build.VERSION.RELEASE + "|" + AppActivity.getProvidersName(mContext) + "|";
209+
String str = "";
210+
211+
if (!AppActivity.isConnected(mContext)) {
212+
return info + "Disconnected";
213+
} else {
214+
str = AppActivity.getWifi(mContext);
215+
if (str != "") {
216+
return info + str;
217+
}
218+
219+
str = AppActivity.getMobile(mContext);
220+
if (str != "") {
221+
return info + str;
222+
} else {
223+
return info + "Unknown";
224+
}
225+
}
226+
}
227+
}
228+
```
229+
230+
因为判断4G的TelephonyManager.NETWORK_TYPE_LTE属于API level 11,用这个定义写法,编译无法通过(默认编译是API level 10,最低可以是API level 9),所以这里写了硬编码。
231+
232+
## 3. 配置文件修改
233+
234+
------
235+
236+
修改项目目录frameworks/runtime-src/proj.android/jni/Android.mk文件,加上jsb_os_info.hpp:
237+
238+
```
239+
...
240+
LOCAL_SRC_FILES := hellojavascript/main.cpp \
241+
../../Classes/jsb_os_info.hpp \
242+
../../Classes/AppDelegate.cpp
243+
...
244+
```
245+
246+
然后重新编译就可以在jsb环境下,用javascript执行osInfo这个函数。
247+
248+
## 4. javascript端执行效果
249+
250+
------
251+
252+
Wifi和手机上网状态,用javascript的osInfo函数返回分别是这样的:
253+
254+
```
255+
vivo Xplay3S|Android|4.3|cm|Wifi|4|39
256+
vivo Xplay3S|Android|4.3|cm|Mobile|LTE
257+
```
258+
259+
主要是游戏对网络比较敏感,所以判断了是Wifi上网还是手机上网,Wifi还判断了信号强度以及连接速率,手机上网判断是哪种上网方式。
260+
261+
## 5. 反射机制调用
262+
263+
------
264+
265+
就在文档写到尾声的时候,在英文论坛突然发现这篇文档:
266+
267+
https://github.com/joshuastray/cocos-docs/blob/master/manual/framework/html5/v3/reflection/zh.md
268+
269+
有点无语,白白多花了几个小时,原来世界这么简单。强烈呼吁cocos2d-js团队的童鞋有文档就先在论坛里扔一下,小白鼠们都会抢着去测试的。
270+
271+
PS. IOS下javascript调用Objective-C有没有方便的方法?还是得普通jsb方式调用?
272+
273+
## 6. 参考文档
274+
275+
------
276+
277+
【集成友盟社会化SDK】COCOS2D-JS3.0ALPHA2中JAVA/C++/JAVASCRPIT 三方交互的实现
278+
http://www.asmld.com/?p=113
279+
280+
3.jni_c++调用java中的方法
281+
http://banshaotang.iteye.com/blog/2078501
282+
283+
cocos2d-x 使用JniHelper 调用 java代码 获取安卓生成的唯一标示UUID
284+
http://blog.csdn.net/yxiaom/article/details/17137479
285+

0 commit comments

Comments
 (0)