1 package com.tencent.bugly.agent;
2
3 import android.app.Activity;
4 import android.content.Context;
5 import android.os.Handler;
6 import android.os.Looper;
7 import android.os.Process;
8 import android.text.TextUtils;
9 import android.util.Log;
10 import java.lang.ref.WeakReference;
11 import java.lang.reflect.Constructor;
12 import java.lang.reflect.Field;
13 import java.lang.reflect.InvocationTargetException;
14 import java.lang.reflect.Method;
15 import java.util.Locale;
16
17 public class GameAgent
18 {
19 private static final String VERSION = "2.0";
20 private static final String LOG_TAG = "CrashReport-GameAgent";
21 private static final int GAME_TYPE_COCOS = 1;
22 private static final int GAME_TYPE_UNITY = 2;
23 private static final int LOG_LEVEL_VERBOSE = 0;
24 private static final int LOG_LEVEL_DEBUG = 1;
25 private static final int LOG_LEVEL_INFO = 2;
26 private static final int LOG_LEVEL_WARN = 3;
27 private static final int LOG_LEVEL_ERROR = 4;
28 private static final int TYPE_U3D_CRASH = 4;
29 private static final int TYPE_COCOS2DX_JS_CRASH = 5;
30 private static final int TYPE_COCOS2DX_LUA_CRASH = 6;
31 private static final String STRATEGY_CLASS_SUFFIX = "BuglyStrategy";
32 private static final String OLD_STRATEGY_CLASS_SUFFIX = "crashreport.CrashReport$UserStrategy";
33 private static final String CRASH_REPORT_CLASS_SUFFIX = "crashreport.CrashReport";
34 private static final String CLASS_UNITY_PLAYER = "com.unity3d.player.UnityPlayer";
35 private static final String CLASS_COCOS_ACTIVITY = "org.cocos2dx.lib.Cocos2dxActivity";
36 private static String sdkPackageName = "com.tencent.bugly";
37 private static Handler sHandler = null;
38 private static String sAppVersion = null;
39 private static String sAppChannel = null;
40 private static String sUserId = null;
41 private static boolean sIsDebug = false;
42 private static int sGameType = 0;
43 private static WeakReference<Activity> sContext = null;
44
45 public static String getVersion()
46 {
47 return "2.0";
48 }
49
50 public static void printLog(String paramString)
51 {
52 if (TextUtils.isEmpty(paramString)) {
53 return;
54 }
55 if (paramString.startsWith("<Log>"))
56 printLog(2, paramString);
57 else if (paramString.startsWith("<LogDebug>"))
58 printLog(1, paramString);
59 else if (paramString.startsWith("<LogInfo>"))
60 printLog(2, paramString);
61 else if (paramString.startsWith("<LogWarning>"))
62 printLog(3, paramString);
63 else if (paramString.startsWith("<LogAssert>"))
64 printLog(3, paramString);
65 else if (paramString.startsWith("<LogError>"))
66 printLog(4, paramString);
67 else if (paramString.startsWith("<LogException>"))
68 printLog(4, paramString);
69 else
70 printLog(0, paramString);
71 }
72
73 private static void printLog(int paramInt, String paramString)
74 {
75 setLog(paramInt, "CrashReport-GameAgent", paramString);
76 }
77
78 public static Activity getUnityActivity()
79 {
80 try
81 {
82 Object localObject = Reflection.getStaticField("com.unity3d.player.UnityPlayer", "currentActivity", null);
83 if ((localObject != null) && ((localObject instanceof Activity)))
84 return (Activity)localObject;
85 }
86 catch (Exception localException) {
87 Log.w("CrashReport-GameAgent", "Failed to get the current activity from UnityPlayer");
88 localException.printStackTrace();
89 }
90
91 return null;
92 }
93
94 public static Activity getCocosActivity()
95 {
96 try
97 {
98 Object localObject = Reflection.invokeStaticMethod("org.cocos2dx.lib.Cocos2dxActivity", "getContext", null, new Class[0]);
99 if ((localObject != null) && ((localObject instanceof Activity)))
100 return (Activity)localObject;
101 }
102 catch (Exception localException) {
103 Log.w("CrashReport-GameAgent", "Failed to get the current activity from UnityPlayer");
104 localException.printStackTrace();
105 }
106
107 return null;
108 }
109
110 private static Activity getActivity() {
111 Activity localActivity = null;
112 if ((sContext != null) && (sContext.get() != null)) {
113 return (Activity)sContext.get();
114 }
115 switch (sGameType) {
116 case 1:
117 localActivity = getCocosActivity();
118 break;
119 case 2:
120 localActivity = getUnityActivity();
121 break;
122 default:
123 Log.w("CrashReport-GameAgent", "Game type has not been set.");
124 }
125
126 return localActivity;
127 }
128
129 private static Context getApplicationContext() {
130 Activity localActivity = getActivity();
131 if (localActivity != null) {
132 return localActivity.getApplicationContext();
133 }
134 return null;
135 }
136
137 private static void runTaskInUiThread(Runnable paramRunnable) {
138 Activity localActivity = getActivity();
139 if (localActivity != null)
140 localActivity.runOnUiThread(paramRunnable);
141 else
142 new Thread(paramRunnable).start();
143 }
144
145 private static void exitApplication()
146 {
147 int i = Process.myPid();
148 printLog(3, String.format(Locale.US, "Exit application by kill process[%d]", new Object[] { Integer.valueOf(i) }));
149
150 Process.killProcess(i);
151 }
152
153 private static void delayExit(long paramLong)
154 {
155 paramLong = Math.max(0L, paramLong);
156
157 if (sHandler != null) {
158 sHandler.postDelayed(new Runnable()
159 {
160 public void run() {
161 GameAgent.access$200();
162 }
163 }
164 , paramLong);
165 }
166 else
167 {
168 try
169 {
170 Thread.sleep(paramLong);
171 exitApplication();
172 } catch (InterruptedException localInterruptedException) {
173 localInterruptedException.printStackTrace();
174 }
175 }
176 }
177
178 private static String convertToCanonicalName(String paramString)
179 {
180 StringBuilder localStringBuilder = new StringBuilder();
181 if (sdkPackageName == null) {
182 sdkPackageName = "com.tencent.bugly";
183 }
184 localStringBuilder.append(sdkPackageName);
185 localStringBuilder.append(".");
186 localStringBuilder.append(paramString);
187 return localStringBuilder.toString();
188 }
189
190 public static void setSdkPackageName(String paramString)
191 {
192 if (TextUtils.isEmpty(paramString)) {
193 return;
194 }
195 sdkPackageName = paramString;
196 }
197
198 public static void setGameType(int paramInt) {
199 sGameType = paramInt;
200 }
201
202 public static void setLogEnable(boolean paramBoolean)
203 {
204 sIsDebug = paramBoolean;
205 }
206
207 private static Object newStrategy(Context paramContext, String paramString1, String paramString2, long paramLong)
208 {
209 if ((paramContext == null) || ((TextUtils.isEmpty(paramString1)) && (TextUtils.isEmpty(paramString2)))) {
210 return null;
211 }
212 Object localObject = Reflection.newInstance(convertToCanonicalName("crashreport.CrashReport$UserStrategy"), new Object[] { paramContext }, new Class[] { Context.class });
213
214 if (localObject != null) {
215 try {
216 Class localClass = Class.forName(convertToCanonicalName("BuglyStrategy"));
217 Method localMethod1 = localClass.getDeclaredMethod("setAppChannel", new Class[] { String.class });
218 localMethod1.invoke(localObject, new Object[] { paramString1 });
219
220 Method localMethod2 = localClass.getDeclaredMethod("setAppVersion", new Class[] { String.class });
221 localMethod2.invoke(localObject, new Object[] { paramString2 });
222
223 Method localMethod3 = localClass.getDeclaredMethod("setAppReportDelay", new Class[] { Long.TYPE });
224 localMethod3.invoke(localObject, new Object[] { Long.valueOf(paramLong) });
225
226 return localObject;
227 } catch (NoSuchMethodException localNoSuchMethodException) {
228 localNoSuchMethodException.printStackTrace();
229 } catch (IllegalAccessException localIllegalAccessException) {
230 localIllegalAccessException.printStackTrace();
231 } catch (IllegalArgumentException localIllegalArgumentException) {
232 localIllegalArgumentException.printStackTrace();
233 } catch (InvocationTargetException localInvocationTargetException) {
234 localInvocationTargetException.printStackTrace();
235 } catch (Exception localException) {
236 localException.printStackTrace();
237 }
238 }
239 return null;
240 }
241
242 public static void initCrashReport(String paramString, boolean paramBoolean) {
243 setLogEnable(paramBoolean);
244 initCrashReport(paramString, sAppChannel, sAppVersion, sUserId, 0L);
245 }
246
247 private static void initCrashReport(final String paramString1, String paramString2, String paramString3, final String paramString4, long paramLong)
248 {
249 final Context localContext = getApplicationContext();
250 if (localContext == null) {
251 printLog(4, "Context is null. bugly initialize terminated.");
252 return;
253 }
254 if (TextUtils.isEmpty(paramString1)) {
255 printLog(4, "Please input appid when initCrashReport.");
256 return;
257 }
258 sHandler = new Handler(Looper.getMainLooper());
259 Object localObject = newStrategy(localContext, paramString2, paramString3, paramLong);
260 runTaskInUiThread(new Runnable()
261 {
262 public void run()
263 {
264 int i = 0;
265 boolean bool = GameAgent.sIsDebug;
266 if (this.val$strategy != null) {
267 Class localClass = null;
268 try {
269 localClass = Class.forName(GameAgent.convertToCanonicalName("crashreport.CrashReport$UserStrategy"));
270 } catch (ClassNotFoundException localClassNotFoundException) {
271 localClassNotFoundException.printStackTrace();
272 } catch (Exception localException) {
273 localException.printStackTrace();
274 }
275 if (localClass != null) {
276 GameAgent.Reflection.invokeStaticMethod(GameAgent.access$500("crashreport.CrashReport"), "initCrashReport", new Object[] { localContext, paramString1, Boolean.valueOf(bool), this.val$strategy }, new Class[] { Context.class, String.class, Boolean.TYPE, localClass });
277
278 i = 1;
279 }
280 }
281
282 if (i == 0) {
283 GameAgent.Reflection.invokeStaticMethod(GameAgent.access$500("crashreport.CrashReport"), "initCrashReport", new Object[] { localContext, paramString1, Boolean.valueOf(bool) }, new Class[] { Context.class, String.class, Boolean.TYPE });
284 }
285
286 GameAgent.setUserId(paramString4);
287 }
288 });
289 }
290
291 public static void setAppVersion(String paramString)
292 {
293 if (TextUtils.isEmpty(paramString)) {
294 return;
295 }
296 sAppVersion = paramString;
297 runTaskInUiThread(new Runnable()
298 {
299 public void run() {
300 GameAgent.Reflection.invokeStaticMethod(GameAgent.access$500("crashreport.CrashReport"), "setAppVersion", new Object[] { GameAgent.access$600(), this.val$version }, new Class[] { Context.class, String.class });
301 }
302 });
303 }
304
305 public static void setAppChannel(String paramString)
306 {
307 if (TextUtils.isEmpty(paramString)) {
308 return;
309 }
310 sAppChannel = paramString;
311 runTaskInUiThread(new Runnable()
312 {
313 public void run() {
314 GameAgent.Reflection.invokeStaticMethod(GameAgent.access$500("crashreport.CrashReport"), "setAppChannel", new Object[] { GameAgent.access$600(), this.val$channel }, new Class[] { Context.class, String.class });
315 }
316 });
317 }
318
319 public static void setUserId(String paramString)
320 {
321 if (TextUtils.isEmpty(paramString)) {
322 return;
323 }
324 sUserId = paramString;
325 runTaskInUiThread(new Runnable()
326 {
327 public void run() {
328 GameAgent.Reflection.invokeStaticMethod(GameAgent.access$500("crashreport.CrashReport"), "setUserId", new Object[] { GameAgent.access$600(), this.val$userId }, new Class[] { Context.class, String.class });
329 }
330 });
331 }
332
333 public static void setUserSceneTag(int paramInt)
334 {
335 runTaskInUiThread(new Runnable()
336 {
337 public void run() {
338 GameAgent.Reflection.invokeStaticMethod(GameAgent.access$500("crashreport.CrashReport"), "setUserSceneTag", new Object[] { GameAgent.access$600(), Integer.valueOf(this.val$sceneId) }, new Class[] { Context.class, Integer.TYPE });
339 }
340 });
341 }
342
343 public static void putUserData(String paramString1, final String paramString2)
344 {
345 if ((TextUtils.isEmpty(paramString1)) || (TextUtils.isEmpty(paramString2))) {
346 return;
347 }
348 runTaskInUiThread(new Runnable()
349 {
350 public void run() {
351 GameAgent.Reflection.invokeStaticMethod(GameAgent.access$500("crashreport.CrashReport"), "putUserData", new Object[] { GameAgent.access$600(), this.val$key, paramString2 }, new Class[] { Context.class, String.class, String.class });
352 }
353 });
354 }
355
356 public static void removeUserData(String paramString)
357 {
358 if (TextUtils.isEmpty(paramString)) {
359 return;
360 }
361 runTaskInUiThread(new Runnable()
362 {
363 public void run() {
364 GameAgent.Reflection.invokeStaticMethod(GameAgent.access$500("crashreport.CrashReport"), "removeUserData", new Object[] { GameAgent.access$600(), this.val$key }, new Class[] { Context.class, String.class });
365 }
366 });
367 }
368
369 public static void setSdkConfig(String paramString1, final String paramString2)
370 {
371 if ((TextUtils.isEmpty(paramString1)) || (TextUtils.isEmpty(paramString2))) {
372 return;
373 }
374 runTaskInUiThread(new Runnable()
375 {
376 public void run() {
377 GameAgent.Reflection.invokeStaticMethod(GameAgent.access$500("crashreport.CrashReport"), "putSdkData", new Object[] { GameAgent.access$600(), "SDK_" + this.val$key, paramString2 }, new Class[] { Context.class, String.class, String.class });
378 }
379 });
380 }
381
382 public static void setLog(int paramInt, final String paramString1, final String paramString2)
383 {
384 if (TextUtils.isEmpty(paramString1))
385 return;
386 String str;
387 switch (paramInt) {
388 case 0:
389 str = "v";
390 break;
391 case 1:
392 str = "d";
393 break;
394 case 2:
395 str = "i";
396 break;
397 case 3:
398 str = "w";
399 break;
400 case 4:
401 str = "e";
402 break;
403 default:
404 str = null;
405 }
406
407 if (str != null)
408 runTaskInUiThread(new Runnable()
409 {
410 public void run() {
411 GameAgent.Reflection.invokeStaticMethod(GameAgent.access$500("crashreport.BuglyLog"), this.val$method, new Object[] { paramString1, paramString2 }, new Class[] { String.class, String.class });
412 }
413 });
414 }
415
416 private static void postCocosException(int paramInt, String paramString1, final String paramString2, String paramString3, final boolean paramBoolean)
417 {
418 try
419 {
420 if (paramString3.startsWith("stack traceback")) {
421 paramString3 = paramString3.substring(paramString3.indexOf("\n") + 1, paramString3.length()).trim();
422 }
423
424 int i = paramString3.indexOf("\n");
425 if (i > 0) {
426 paramString3 = paramString3.substring(i + 1, paramString3.length());
427 }
428
429 i = paramString3.indexOf("\n");
430 str2 = paramString3;
431 if (i > 0) {
432 str2 = paramString3.substring(0, i);
433 }
434
435 int j = str2.indexOf("]:");
436 if ((paramString1 == null) || (paramString1.length() == 0)) {
437 if (j != -1)
438 paramString1 = str2.substring(0, j + 1);
439 else
440 paramString1 = paramString2;
441 }
442 }
443 catch (Throwable localThrowable)
444 {
445 if ((paramString1 == null) || (paramString1.length() == 0)) {
446 paramString1 = paramString2;
447 }
448 }
449 final String str1 = paramString1;
450 final String str2 = paramString3;
451 runTaskInUiThread(new Runnable()
452 {
453 public void run() {
454 GameAgent.Reflection.invokeStaticMethod(GameAgent.access$500("crashreport.inner.InnerApi"), "postCocos2dxCrashAsync", new Object[] { Integer.valueOf(this.val$category), str1, paramString2, str2 }, new Class[] { Integer.TYPE, String.class, String.class, String.class });
455
456 if (paramBoolean)
457 GameAgent.delayExit(3000L);
458 }
459 });
460 }
461
462 private static void postUnityException(String paramString1, final String paramString2, final String paramString3, final boolean paramBoolean)
463 {
464 runTaskInUiThread(new Runnable()
465 {
466 public void run() {
467 GameAgent.Reflection.invokeStaticMethod(GameAgent.access$500("crashreport.inner.InnerApi"), "postU3dCrashAsync", new Object[] { this.val$type, paramString2, paramString3 }, new Class[] { String.class, String.class, String.class });
468
469 if (paramBoolean)
470 GameAgent.delayExit(3000L);
471 }
472 });
473 }
474
475 public static void postException(int paramInt, String paramString1, String paramString2, String paramString3, boolean paramBoolean)
476 {
477 switch (paramInt) {
478 case 5:
479 case 6:
480 postCocosException(paramInt, paramString1, paramString2, paramString3, paramBoolean);
481 break;
482 case 4:
483 postUnityException(paramString1, paramString2, paramString3, paramBoolean);
484 break;
485 default:
486 printLog(4, new StringBuilder().append("The category of exception posted is unknown: ").append(String.valueOf(paramInt)).toString());
487 }
488 }
489
490 private static class Reflection
491 {
492 private static Object getStaticField(String paramString1, String paramString2, Object paramObject)
493 {
494 try
495 {
496 Class localClass = Class.forName(paramString1);
497
498 Field localField = localClass.getDeclaredField(paramString2);
499 localField.setAccessible(true);
500 return localField.get(paramObject);
501 } catch (ClassNotFoundException localClassNotFoundException) {
502 localClassNotFoundException.printStackTrace();
503 } catch (NoSuchFieldException localNoSuchFieldException) {
504 localNoSuchFieldException.printStackTrace();
505 } catch (IllegalAccessException localIllegalAccessException) {
506 localIllegalAccessException.printStackTrace();
507 }
508
509 return null;
510 }
511
512 private static Object invokeStaticMethod(String paramString1, String paramString2, Object[] paramArrayOfObject, Class<?>[] paramArrayOfClass)
513 {
514 try
515 {
516 Class localClass = Class.forName(paramString1);
517 Method localMethod = localClass.getDeclaredMethod(paramString2, paramArrayOfClass);
518 localMethod.setAccessible(true);
519 return localMethod.invoke(null, paramArrayOfObject);
520 } catch (ClassNotFoundException localClassNotFoundException) {
521 localClassNotFoundException.printStackTrace();
522 } catch (NoSuchMethodException localNoSuchMethodException) {
523 localNoSuchMethodException.printStackTrace();
524 } catch (InvocationTargetException localInvocationTargetException) {
525 localInvocationTargetException.printStackTrace();
526 } catch (IllegalAccessException localIllegalAccessException) {
527 localIllegalAccessException.printStackTrace();
528 } catch (Exception localException) {
529 localException.printStackTrace();
530 }
531 return null;
532 }
533
534 private static Object newInstance(String paramString, Object[] paramArrayOfObject, Class<?>[] paramArrayOfClass)
535 {
536 try
537 {
538 Class localClass = Class.forName(paramString);
539 if (paramArrayOfObject == null) {
540 return localClass.newInstance();
541 }
542 Constructor localConstructor = localClass.getConstructor(paramArrayOfClass);
543 return localConstructor.newInstance(paramArrayOfObject);
544 }
545 catch (ClassNotFoundException localClassNotFoundException) {
546 localClassNotFoundException.printStackTrace();
547 } catch (NoSuchMethodException localNoSuchMethodException) {
548 localNoSuchMethodException.printStackTrace();
549 } catch (InstantiationException localInstantiationException) {
550 localInstantiationException.printStackTrace();
551 } catch (IllegalAccessException localIllegalAccessException) {
552 localIllegalAccessException.printStackTrace();
553 } catch (InvocationTargetException localInvocationTargetException) {
554 localInvocationTargetException.printStackTrace();
555 } catch (Exception localException) {
556 localException.printStackTrace();
557 }
558 return null;
559 }
560 }
561 }