SdkProject/app/build.gradle
@@ -7,7 +7,7 @@ buildToolsVersion "30.0.2" defaultConfig { applicationId "com.secondworld.sdk" applicationId "com.secondworld.demo" minSdkVersion 21 targetSdkVersion 29 versionCode 1 @@ -32,7 +32,7 @@ implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'com.google.android.material:material:1.2.1' implementation 'androidx.constraintlayout:constraintlayout:2.0.3' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation project(path: ':library') testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.2' SdkProject/app/src/androidTest/java/com/secondworld/sdk/ExampleInstrumentedTest.java
File was renamed from SdkProject/app/src/androidTest/java/com/secondworld/universalsdk/ExampleInstrumentedTest.java @@ -1,4 +1,4 @@ package com.secondworld.universalsdk; package com.secondworld.sdk; import android.content.Context; SdkProject/app/src/main/AndroidManifest.xml
@@ -1,6 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.secondworld.universalsdk"> package="com.secondworld.demo"> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" @@ -8,15 +10,14 @@ android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:name=".BaseApplication" android:theme="@style/Theme.SdkProject"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> SdkProject/app/src/main/java/com/secondworld/demo/MainActivity.java
New file @@ -0,0 +1,35 @@ package com.secondworld.demo; import android.app.Activity; import android.os.Bundle; import com.secondworld.sdk.UnityMsgHandler; import com.secondworld.sdk.utils.CodeU2A; import org.json.JSONException; import org.json.JSONObject; import java.util.UUID; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.btnInit).setOnClickListener((v -> { JSONObject json = new JSONObject(); try { json.put("code", CodeU2A.CopyContent); json.put("content", "这是复制内容哦:" + UUID.randomUUID().toString()); } catch (JSONException e) { e.printStackTrace(); } UnityMsgHandler.onUnityMessage(json.toString()); })); } } SdkProject/app/src/main/java/com/secondworld/universalsdk/MainActivity.java
File was deleted SdkProject/app/src/main/res/layout/activity_main.xml
@@ -1,9 +1,19 @@ <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> android:gravity="center"> </androidx.constraintlayout.widget.ConstraintLayout> <Button android:id="@+id/btnInit" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="24dp" android:text="init" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/editTextNumber" /> </LinearLayout> SdkProject/app/src/test/java/com/secondworld/sdk/ExampleUnitTest.java
File was renamed from SdkProject/app/src/test/java/com/secondworld/universalsdk/ExampleUnitTest.java @@ -1,4 +1,4 @@ package com.secondworld.universalsdk; package com.secondworld.sdk; import org.junit.Test; SdkProject/channel/test/java/com/secondworld/sdk/MyApplication.java
New file @@ -0,0 +1,4 @@ package com.secondworld.sdk; public class MyApplication extends GameApp { } SdkProject/channel/test/java/com/secondworld/universalsdk/MyApplication.java
File was deleted SdkProject/library/build.gradle
@@ -112,32 +112,51 @@ } } //拷贝清单文件作为unity直接使用 //拷贝清单文件 task copyDebugManifest(type: Copy) { from zipTree("build/outputs/aar/library-debug-${CHANNEL_NAME}.aar") include "AndroidManifest.xml" into "${outPutPath}\\${CHANNEL_NAME}\\debug" } task copyManifest(type: Copy) { dependsOn 'assembleRelease' dependsOn 'copyDebugManifest' from zipTree("build/outputs/aar/library-release-${CHANNEL_NAME}.aar") include "AndroidManifest.xml" into "${outPutPath}\\${CHANNEL_NAME}\\" into "${outPutPath}\\${CHANNEL_NAME}\\release" } task copyDebugSdk(type: Copy) { from "build/outputs/aar/" include "library-debug-${CHANNEL_NAME}.aar" into "${outPutPath}\\${CHANNEL_NAME}\\debug\\libs\\" } //执行打包任务以及拷贝到外部 task assembleAndCopySdk(type: Copy) { dependsOn copyManifest delete "${outPutPath}\\${CHANNEL_NAME}" dependsOn 'assembleMerger' // dependsOn copyManifest dependsOn copyDebugSdk from "build/outputs/aar/" include "library-release-${CHANNEL_NAME}.aar" into "${outPutPath}\\${CHANNEL_NAME}\\libs\\" into "${outPutPath}\\${CHANNEL_NAME}\\release\\libs\\" } dependencies { implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'com.google.android.material:material:1.2.1' implementation 'androidx.constraintlayout:constraintlayout:2.0.3' implementation 'androidx.navigation:navigation-fragment:2.3.1' implementation 'androidx.navigation:navigation-ui:2.3.1' testImplementation 'junit:junit:4.13.1' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'com.google.android.material:material:1.2.1' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'androidx.navigation:navigation-fragment:2.3.1' implementation 'androidx.navigation:navigation-ui:2.3.1' implementation 'com.github.pqpo:Log4a:1.4.2@aar' implementation files('libs/unity-classes.jar') implementation fileTree(dir: 'libs', include: ['*.jar'], exclude: ['unity-classes.jar']) compileOnly files('libs/unity-classes.jar') } SdkProject/library/libs/unity-classes.jarBinary files differ
SdkProject/library/src/androidTest/java/com/secondworld/sdk/ExampleInstrumentedTest.java
File was renamed from SdkProject/library/src/androidTest/java/com/secondworld/universalsdk/ExampleInstrumentedTest.java @@ -1,4 +1,4 @@ package com.secondworld.universalsdk; package com.secondworld.sdk; import android.content.Context; SdkProject/library/src/main/AndroidManifest.xml
@@ -1,7 +1,17 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.secondworld.universalsdk"> package="com.secondworld.sdk"> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <application android:name="com.secondworld.sdk.GameApp" android:allowBackup="true" android:supportsRtl="true"> <activity android:name="com.secondworld.sdk.GameActivity"/> </application> </manifest> SdkProject/library/src/main/java/com/secondworld/sdk/AsyncTaskOperator.java
New file @@ -0,0 +1,24 @@ package com.secondworld.sdk; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; //耗时任务操作 public class AsyncTaskOperator { public static AsyncTaskOperator I = new AsyncTaskOperator(); private ExecutorService cachedThreadPool; private ExecutorService getCachedThreadPool() { if (cachedThreadPool == null) { cachedThreadPool = Executors.newCachedThreadPool(); } return cachedThreadPool; } public void run(Runnable runnable) { getCachedThreadPool().execute(runnable); } } SdkProject/library/src/main/java/com/secondworld/sdk/GameActivity.java
New file @@ -0,0 +1,26 @@ package com.secondworld.sdk; import android.os.Bundle; import android.view.View; import android.widget.FrameLayout; public class GameActivity extends UnityPlayerActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // setContentView(R.layout.activity_main); checkPermission(); // addUnityView(); } private void checkPermission() { } protected void addUnityView() { FrameLayout _frameLayout = findViewById(R.id.unity_view); View unityView = mUnityPlayer.getView(); _frameLayout.addView(unityView); } } SdkProject/library/src/main/java/com/secondworld/sdk/GameApp.java
New file @@ -0,0 +1,54 @@ package com.secondworld.sdk; import android.app.AlarmManager; import android.app.Application; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Handler; import com.secondworld.sdk.utils.LogUtil; import com.unity3d.player.UnityPlayer; public class GameApp extends Application { public static GameApp I; @Override public void onCreate() { super.onCreate(); I = this; InitSdk(); } public void InitSdk() { LogUtil.Init(this); UnityMsgHandler.initCommandMap(); } public static void AppExit() { new Handler().postDelayed(new Runnable() { @Override public void run() { android.os.Process.killProcess(android.os.Process.myPid());// 杀进程 } }, 1000); if (UnityPlayer.currentActivity != null) UnityPlayer.currentActivity.finish(); } public static void RestartApp() { new Handler().postDelayed(() -> { String _pn = I.getPackageName(); PackageManager packageManager = I.getPackageManager(); Intent intent = packageManager.getLaunchIntentForPackage(_pn); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); I.startActivity(intent); android.os.Process.killProcess(android.os.Process.myPid());// 杀进程 }, 1000); if (UnityPlayer.currentActivity != null) UnityPlayer.currentActivity.finish(); } } SdkProject/library/src/main/java/com/secondworld/sdk/UnityMsgHandler.java
New file @@ -0,0 +1,98 @@ package com.secondworld.sdk; import com.secondworld.sdk.command.CmdInit; import com.secondworld.sdk.command.ICommand; import com.secondworld.sdk.utils.LogUtil; import com.secondworld.sdk.utils.StaticDefine; import com.unity3d.player.UnityPlayer; import org.json.JSONObject; import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import dalvik.system.DexFile; public class UnityMsgHandler { private static final HashMap<Integer, ICommand> allCommand = new HashMap<>(); /** * 初始化所有命令 */ public static void initCommandMap() { try { allCommand.clear(); new CmdInit(); List<String> classesName = getClassName("com.secondworld.sdk.command"); for (String name : classesName) { Class<?> aClass = Class.forName(name); LogUtil.debug("initCommandMap", name); if (!aClass.isInterface() && ICommand.class.isAssignableFrom(aClass))//此处必须判断是否为ICommand子类,因为匿名类也会生成至此包 addCommand((ICommand) aClass.newInstance()); } } catch (Exception e) { e.printStackTrace(); LogUtil.e("initCommandMap", e); } } public static void addCommand(ICommand command) { allCommand.put(command.getCode(), command); } /** * 处理unity 发来的消息 * * @param json */ public static void onUnityMessage(String json) { try { LogUtil.debug("onUnityMessage", json); JSONObject _json = new JSONObject(json); int code = _json.getInt("code"); ICommand command = allCommand.get(code); if (command == null) LogUtil.w("onUnityMessage", "未知命令" + code); else command.process(_json); } catch (Exception e) { LogUtil.e("onUnityMessage", e); } } /** * 通过反射读取指定包名下的所有类名 * * @param * @return */ public static List<String> getClassName(String packageName) throws IOException { List<String> classNameList = new ArrayList<String>(); DexFile df = new DexFile(GameApp.I.getPackageCodePath());//通过DexFile查找当前的APK中可执行文件 Enumeration<String> enumeration = df.entries();//获取df中的元素 这里包含了所有可执行的类名 该类名包含了包名+类名的方式 while (enumeration.hasMoreElements()) {//遍历 String className = (String) enumeration.nextElement(); if (className.contains(packageName)) {//在当前所有可执行的类里面查找包含有该包名的所有类 classNameList.add(className); } } return classNameList; } public static void sendMessageToUnity(Map<String, Object> jsonMap) { if (jsonMap == null || jsonMap.isEmpty()) { return; } JSONObject _jsonObject = new JSONObject(jsonMap); UnityPlayer.UnitySendMessage(StaticDefine.UnityGameObjectName, StaticDefine.UnityHandleFuncName, _jsonObject.toString()); } } SdkProject/library/src/main/java/com/secondworld/sdk/UnityPlayerActivity.java
New file @@ -0,0 +1,132 @@ // GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN package com.secondworld.sdk; import android.app.Activity; import android.content.Intent; import android.content.res.Configuration; import android.os.Bundle; import android.os.Process; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.Window; import com.unity3d.player.IUnityPlayerLifecycleEvents; import com.unity3d.player.UnityPlayer; public class UnityPlayerActivity extends Activity implements IUnityPlayerLifecycleEvents { protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code // Override this in your custom UnityPlayerActivity to tweak the command line arguments passed to the Unity Android Player // The command line arguments are passed as a string, separated by spaces // UnityPlayerActivity calls this from 'onCreate' // Supported: -force-gles20, -force-gles30, -force-gles31, -force-gles31aep, -force-gles32, -force-gles, -force-vulkan // See https://docs.unity3d.com/Manual/CommandLineArguments.html // @param cmdLine the current command line arguments, may be null // @return the modified command line string or null protected String updateUnityCommandLineArguments(String cmdLine) { return cmdLine; } // Setup activity layout @Override protected void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); super.onCreate(savedInstanceState); String cmdLine = updateUnityCommandLineArguments(getIntent().getStringExtra("unity")); getIntent().putExtra("unity", cmdLine); mUnityPlayer = new UnityPlayer(this, this); setContentView(mUnityPlayer); mUnityPlayer.requestFocus(); } // When Unity player unloaded move task to background @Override public void onUnityPlayerUnloaded() { moveTaskToBack(true); } // When Unity player quited kill process @Override public void onUnityPlayerQuitted() { Process.killProcess(Process.myPid()); } @Override protected void onNewIntent(Intent intent) { // To support deep linking, we need to make sure that the client can get access to // the last sent intent. The clients access this through a JNI api that allows them // to get the intent set on launch. To update that after launch we have to manually // replace the intent with the one caught here. setIntent(intent); mUnityPlayer.newIntent(intent); } // Quit Unity @Override protected void onDestroy () { mUnityPlayer.destroy(); super.onDestroy(); } // Pause Unity @Override protected void onPause() { super.onPause(); mUnityPlayer.pause(); } // Resume Unity @Override protected void onResume() { super.onResume(); mUnityPlayer.resume(); } // Low Memory Unity @Override public void onLowMemory() { super.onLowMemory(); mUnityPlayer.lowMemory(); } // Trim Memory Unity @Override public void onTrimMemory(int level) { super.onTrimMemory(level); if (level == TRIM_MEMORY_RUNNING_CRITICAL) { mUnityPlayer.lowMemory(); } } // This ensures the layout will be correct. @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); mUnityPlayer.configurationChanged(newConfig); } // Notify Unity of the focus change. @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); mUnityPlayer.windowFocusChanged(hasFocus); } // For some reason the multiple keyevent type is not supported by the ndk. // Force event injection by overriding dispatchKeyEvent(). @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_MULTIPLE) return mUnityPlayer.injectEvent(event); return super.dispatchKeyEvent(event); } // Pass any events not handled by (unfocused) views straight to UnityPlayer @Override public boolean onKeyUp(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); } /*API12*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); } } SdkProject/library/src/main/java/com/secondworld/sdk/command/CmdBatteryListenStart.java
New file @@ -0,0 +1,18 @@ package com.secondworld.sdk.command; import com.secondworld.sdk.utils.BatteryUtil; import com.secondworld.sdk.utils.CodeU2A; import org.json.JSONObject; public class CmdBatteryListenStart implements ICommand { @Override public int getCode() { return CodeU2A.BatteryListenStart; } @Override public void process(JSONObject json) { BatteryUtil.getInstance().start(); } } SdkProject/library/src/main/java/com/secondworld/sdk/command/CmdBatteryListenStop.java
New file @@ -0,0 +1,18 @@ package com.secondworld.sdk.command; import com.secondworld.sdk.utils.BatteryUtil; import com.secondworld.sdk.utils.CodeU2A; import org.json.JSONObject; public class CmdBatteryListenStop implements ICommand { @Override public int getCode() { return CodeU2A.BatteryListenStop; } @Override public void process(JSONObject json) { BatteryUtil.getInstance().stop(); } } SdkProject/library/src/main/java/com/secondworld/sdk/command/CmdCopyAsset.java
New file @@ -0,0 +1,19 @@ package com.secondworld.sdk.command; import com.secondworld.sdk.AsyncTaskOperator; import com.secondworld.sdk.utils.CodeU2A; import com.secondworld.sdk.utils.FileUtil; import org.json.JSONObject; public class CmdCopyAsset implements ICommand { @Override public int getCode() { return CodeU2A.CopyAsset; } @Override public void process(JSONObject json) { AsyncTaskOperator.I.run(FileUtil::copyAssets); } } SdkProject/library/src/main/java/com/secondworld/sdk/command/CmdCopyContent.java
New file @@ -0,0 +1,35 @@ package com.secondworld.sdk.command; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; import com.secondworld.sdk.AsyncTaskOperator; import com.secondworld.sdk.GameApp; import com.secondworld.sdk.utils.CodeU2A; import com.secondworld.sdk.utils.LogUtil; import org.json.JSONException; import org.json.JSONObject; public class CmdCopyContent implements ICommand { @Override public int getCode() { return CodeU2A.CopyContent; } @Override public void process(JSONObject json) { try { String content = json.getString("content"); ClipboardManager mgr = (ClipboardManager) GameApp.I.getSystemService( Context.CLIPBOARD_SERVICE); ClipData data = ClipData.newPlainText("playerId", content); mgr.setPrimaryClip(data); } catch (Exception e) { LogUtil.e("CmdCopyContent", e); } } } SdkProject/library/src/main/java/com/secondworld/sdk/command/CmdCopyOneAsset.java
New file @@ -0,0 +1,21 @@ package com.secondworld.sdk.command; import com.secondworld.sdk.AsyncTaskOperator; import com.secondworld.sdk.utils.CodeU2A; import com.secondworld.sdk.utils.FileUtil; import org.json.JSONObject; public class CmdCopyOneAsset implements ICommand { @Override public int getCode() { return CodeU2A.CopyOneAsset; } @Override public void process(JSONObject json) { AsyncTaskOperator.I.run(() -> { FileUtil.copyOneAsset(json.toString()); }); } } SdkProject/library/src/main/java/com/secondworld/sdk/command/CmdInit.java
New file @@ -0,0 +1,61 @@ package com.secondworld.sdk.command; import android.app.AlertDialog; import com.secondworld.sdk.GameApp; import com.secondworld.sdk.UnityMsgHandler; import com.secondworld.sdk.utils.CodeA2U; import com.secondworld.sdk.utils.CodeU2A; import com.secondworld.sdk.utils.DeviceUtil; import com.secondworld.sdk.utils.LogUtil; import com.unity3d.player.UnityPlayer; import org.json.JSONObject; import java.util.HashMap; import java.util.Map; /** * 游戏初始化 */ public class CmdInit implements ICommand { @Override public int getCode() { return CodeU2A.Init; } @Override public void process(JSONObject json) { long size = DeviceUtil.getTotalRAMSize() / 1024 / 1024; LogUtil.debug("CmdInit", "内存:" + size + " mb"); if (size < 1024) { LogUtil.w("CmdInit", "检测设备内存不满足运行程序标准,内存:" + size + " mb"); AlertDialog.Builder _builder = new AlertDialog.Builder(UnityPlayer.currentActivity); _builder.setTitle("警告"); _builder.setCancelable(false); _builder.setMessage("您的设备运行内存不满足要求,无法正常运行游戏"); _builder.setPositiveButton("确定", (dialogInterface, i) -> { GameApp.AppExit(); }); _builder.show(); return; } //发送设备信息 Map<String, Object> _msgStruct = new HashMap<>(); _msgStruct.put("code", CodeA2U.DeviceInfo); _msgStruct.put("userAgent", System.getProperty("http.agent")); _msgStruct.put("mac", DeviceUtil.getLocalMac()); _msgStruct.put("imei", ""); _msgStruct.put("android_id", DeviceUtil.getAndroidId()); _msgStruct.put("unique_id", DeviceUtil.getUniqueID()); _msgStruct.put("memoryTotal", size); UnityMsgHandler.sendMessageToUnity(_msgStruct); //通知sdk初始化完成 _msgStruct.clear(); _msgStruct.put("code", CodeA2U.SdkInitComplete); UnityMsgHandler.sendMessageToUnity(_msgStruct); LogUtil.debug("CmdInit", "Sdk初始化完成"); } } SdkProject/library/src/main/java/com/secondworld/sdk/command/CmdInstallAPK.java
New file @@ -0,0 +1,40 @@ package com.secondworld.sdk.command; import android.content.Intent; import android.net.Uri; import android.widget.Toast; import com.secondworld.sdk.GameApp; import com.secondworld.sdk.utils.CodeU2A; import com.secondworld.sdk.utils.LogUtil; import org.json.JSONObject; import java.io.File; public class CmdInstallAPK implements ICommand { @Override public int getCode() { return CodeU2A.InstallAPK; } @Override public void process(JSONObject json) { try { String path = json.getString("path"); File file = new File(path); if (!file.exists()) { LogUtil.w("InstallApp", "文件不存在"); Toast.makeText(GameApp.I, "找不安装文件", Toast.LENGTH_SHORT).show(); return; } Intent _intent = new Intent(Intent.ACTION_VIEW); _intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); _intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); GameApp.I.startActivity(_intent); } catch (Exception e) { LogUtil.e("CmdInstallAPK", e); } } } SdkProject/library/src/main/java/com/secondworld/sdk/command/CmdOpenWebView.java
New file @@ -0,0 +1,17 @@ package com.secondworld.sdk.command; import com.secondworld.sdk.utils.CodeU2A; import org.json.JSONObject; public class CmdOpenWebView implements ICommand { @Override public int getCode() { return CodeU2A.OpenWebView; } @Override public void process(JSONObject json) { } } SdkProject/library/src/main/java/com/secondworld/sdk/command/CmdRequestManifestPermissions.java
New file @@ -0,0 +1,17 @@ package com.secondworld.sdk.command; import com.secondworld.sdk.utils.CodeU2A; import org.json.JSONObject; public class CmdRequestManifestPermissions implements ICommand { @Override public int getCode() { return CodeU2A.RequestManifestPermissions; } @Override public void process(JSONObject json) { } } SdkProject/library/src/main/java/com/secondworld/sdk/command/CmdRequestPermission.java
New file @@ -0,0 +1,18 @@ package com.secondworld.sdk.command; import com.secondworld.sdk.utils.CodeU2A; import org.json.JSONObject; public class CmdRequestPermission implements ICommand { @Override public int getCode() { return CodeU2A.RequestPermission; } @Override public void process(JSONObject json) { } } SdkProject/library/src/main/java/com/secondworld/sdk/command/CmdRestartApp.java
New file @@ -0,0 +1,18 @@ package com.secondworld.sdk.command; import com.secondworld.sdk.GameApp; import com.secondworld.sdk.utils.CodeU2A; import org.json.JSONObject; public class CmdRestartApp implements ICommand { @Override public int getCode() { return CodeU2A.RestartApp; } @Override public void process(JSONObject json) { GameApp.RestartApp(); } } SdkProject/library/src/main/java/com/secondworld/sdk/command/CmdUniqueID.java
New file @@ -0,0 +1,17 @@ package com.secondworld.sdk.command; import com.secondworld.sdk.utils.CodeU2A; import org.json.JSONObject; public class CmdUniqueID implements ICommand{ @Override public int getCode() { return CodeU2A.UniqueID; } @Override public void process(JSONObject json) { } } SdkProject/library/src/main/java/com/secondworld/sdk/command/ICommand.java
New file @@ -0,0 +1,14 @@ package com.secondworld.sdk.command; import org.json.JSONObject; /** * unity 传递过来的命令 */ public interface ICommand { int getCode(); void process(JSONObject json) throws Exception; } SdkProject/library/src/main/java/com/secondworld/sdk/utils/BatteryUtil.java
New file @@ -0,0 +1,108 @@ package com.secondworld.sdk.utils; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.BatteryManager; import com.secondworld.sdk.GameApp; import com.secondworld.sdk.UnityMsgHandler; import java.util.HashMap; import java.util.Map; import java.util.Objects; /** * Created by Administrator on 2018/7/15 0015. */ public class BatteryUtil { private static BatteryUtil s_Instance = null; public static BatteryUtil getInstance() { if (s_Instance == null) { s_Instance = new BatteryUtil(); } return s_Instance; } private BatteryBroadCastReceiver m_BatteryBroadCastReceiver; private BatteryUtil() { } public void start() { m_BatteryBroadCastReceiver = new BatteryBroadCastReceiver(); IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); GameApp.I.registerReceiver(m_BatteryBroadCastReceiver, filter); } public void stop() { if (m_BatteryBroadCastReceiver != null) { try { GameApp.I.unregisterReceiver(m_BatteryBroadCastReceiver); m_BatteryBroadCastReceiver = null; } catch (IllegalArgumentException e) { if (!Objects.requireNonNull(e.getMessage()).contains("Receiver not registered")) { throw e; } } } } private static class BatteryBroadCastReceiver extends BroadcastReceiver { private int m_BatteryLevel; private int m_Status; public BatteryBroadCastReceiver() { m_BatteryLevel = 0; } @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) { int _batteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); Map<String, Object> _msg = new HashMap<>(); if (_batteryLevel != m_BatteryLevel) { try { _msg.put("code", CodeA2U.BatteryLevel); _msg.put("level", _batteryLevel); UnityMsgHandler.sendMessageToUnity(_msg); m_BatteryLevel = _batteryLevel; } catch (Exception e) { e.printStackTrace(); } } int _status = intent.getIntExtra("status", 0); if (_status != m_Status) { _msg.clear(); int _transCode = 0; if (_status == BatteryManager.BATTERY_STATUS_CHARGING) { _transCode = 2; } else if (_status == BatteryManager.BATTERY_STATUS_NOT_CHARGING || _status == BatteryManager.BATTERY_STATUS_DISCHARGING) { _transCode = 1; } else if (_status == BatteryManager.BATTERY_STATUS_FULL) { _transCode = 3; } _msg.put("code", CodeA2U.BatteryCharging); _msg.put("status", _transCode); UnityMsgHandler.sendMessageToUnity(_msg); m_Status = _status; } } } } } SdkProject/library/src/main/java/com/secondworld/sdk/utils/CodeA2U.java
File was renamed from SdkProject/library/src/main/java/com/secondworld/universalsdk/utils/CodeA2U.java @@ -1,4 +1,4 @@ package com.secondworld.universalsdk.utils; package com.secondworld.sdk.utils; /** * Created by Administrator on 2018/7/18 0018. SdkProject/library/src/main/java/com/secondworld/sdk/utils/CodeU2A.java
File was renamed from SdkProject/library/src/main/java/com/secondworld/universalsdk/utils/CodeU2A.java @@ -1,4 +1,4 @@ package com.secondworld.universalsdk.utils; package com.secondworld.sdk.utils; /** * Created by Administrator on 2018/7/18 0018. @@ -8,7 +8,7 @@ /** * 执行资源拷贝 */ int AssetCopy = 0; int CopyAsset = 0; /** * 执行开始电量改变,充电状态改变监听 */ @@ -60,13 +60,13 @@ /** * 每个渠道各自的处理 * 每个渠道自己的处理 */ int FreePlatformInit = 100; int FreePlatformLogin = 101; int FreePlatformLogout = 102; int FreePlatformSwitchAccount = 103; int FreePlatformPay = 104; int PlatformInit = 100; int PlatformLogin = 101; int PlatformLogout = 102; int PlatformSwitchAccount = 103; int PlatformPay = 104; int PayFinished = 105; int CreateRole = 106; int RoleLogin = 107; SdkProject/library/src/main/java/com/secondworld/sdk/utils/DeviceUtil.java
New file @@ -0,0 +1,157 @@ package com.secondworld.sdk.utils; import android.app.ActivityManager; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Build; import android.provider.Settings; import com.secondworld.sdk.GameApp; import java.net.NetworkInterface; import java.util.Enumeration; import java.util.Locale; import java.util.UUID; public class DeviceUtil { public static final String FAKE_MAC = "02:00:00:00:00:00"; public static long getVersionCode() { long appVersionCode = 0; try { PackageInfo packageInfo = GameApp.I.getApplicationContext() .getPackageManager() .getPackageInfo(GameApp.I.getPackageName(), 0); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { appVersionCode = packageInfo.getLongVersionCode(); } else { appVersionCode = packageInfo.versionCode; } } catch (PackageManager.NameNotFoundException e) { LogUtil.e("getAppVersionCode", e); } return appVersionCode; } public static String getVersionName() { String appVersionName = ""; try { PackageInfo packageInfo = GameApp.I.getApplicationContext() .getPackageManager() .getPackageInfo(GameApp.I.getPackageName(), 0); appVersionName = packageInfo.versionName; } catch (PackageManager.NameNotFoundException e) { LogUtil.e("getAppVersionName", e); } return appVersionName; } /** * 获取当前设备总运行内存 * 单位为 byte * * @return */ public static long getTotalRAMSize() { ActivityManager manager = (ActivityManager) GameApp.I.getSystemService(Context.ACTIVITY_SERVICE); ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo(); manager.getMemoryInfo(info); return info.totalMem; } public static String getAndroidId() { String ANDROID_ID = Settings.System.getString(GameApp.I.getContentResolver(), Settings.System.ANDROID_ID); if (ANDROID_ID == null || ANDROID_ID.equals("9774d56d682e549c")) return ""; return ANDROID_ID; } /** * 唯一标识 * * @return */ public static String getUniqueID() { String uniqueID = SPUtils.get().getString(SPUtils.UNIQUE_ID, ""); if (!uniqueID.trim().isEmpty()) return uniqueID; uniqueID = getAndroidId() + getLocalMac(); //自己生成的uid if (uniqueID.trim().isEmpty()) uniqueID = UUID.randomUUID().toString(); uniqueID = Util.md5(uniqueID).toUpperCase(); SPUtils.get() .edit() .putString(SPUtils.UNIQUE_ID, uniqueID.trim()) .apply(); return uniqueID; } /** * mac 地址 * * @return */ public static String getLocalMac() { String mac = SPUtils.get().getString(SPUtils.MAC, ""); if (!mac.trim().isEmpty()) return mac; try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { String interfaceName = "wlan0"; Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); NetworkInterface intf = null; while (interfaces.hasMoreElements()) { intf = interfaces.nextElement(); if (!intf.getName().equalsIgnoreCase(interfaceName)) continue; byte[] addresses = intf.getHardwareAddress(); if (mac != null) { StringBuilder buf = new StringBuilder(); for (byte aMac : addresses) { buf.append(String.format("%02X:", aMac)); } if (buf.length() > 0) { buf.deleteCharAt(buf.length() - 1); } mac = buf.toString(); } break; } } else { WifiManager wifi = (WifiManager) GameApp.I.getSystemService(Context.WIFI_SERVICE); if (wifi != null) { WifiInfo wifiInfo = wifi.getConnectionInfo(); if (wifiInfo != null) { mac = wifiInfo.getMacAddress(); } } } } catch (Throwable e) { e.printStackTrace(); } mac = mac.toUpperCase(Locale.ENGLISH); if (mac.equals(FAKE_MAC)) mac = ""; SPUtils.get() .edit() .putString(SPUtils.MAC, mac.trim()) .apply(); return mac; } } SdkProject/library/src/main/java/com/secondworld/sdk/utils/FileUtil.java
New file @@ -0,0 +1,136 @@ package com.secondworld.sdk.utils; import android.content.res.AssetManager; import com.secondworld.sdk.GameApp; import com.secondworld.sdk.UnityMsgHandler; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.util.HashMap; import java.util.Map; /** * Created by Administrator on 2018/6/14 0014. */ public class FileUtil { /** * Unity随包资源批量拷贝 */ public static void copyAssets() { // 获取当前包的版本号 final long currentVer = DeviceUtil.getVersionCode(); // 已经拷贝过, 则再次判断一次版本号 // 如果版本号不相同, 则重新进行拷贝 // 获取本地存储的版本号 long installVer = SPUtils.get().getLong(SPUtils.LAST_COPY_VERSION, 0); if (installVer == currentVer) { LogUtil.i("copyAssets", "已拷贝过,installVer:" + installVer + ";" + "currentVer:" + currentVer); Map<String, Object> _msg = new HashMap<>(); _msg.put("code", CodeA2U.AssetCopyFinished); UnityMsgHandler.sendMessageToUnity(_msg); return; } String _dest = GameApp.I.getExternalFilesDir("").getAbsolutePath(); AssetManager _assetMgr = GameApp.I.getAssets(); try { String[] _fileNames = _assetMgr.list("android"); if (_fileNames != null) { for (String _fileName : _fileNames) { copy("android" + File.separator + _fileName, _dest + File.separator + _fileName); } } LogUtil.i("copyAssets", "全部拷贝完成," + "currentVer:" + currentVer); // 存储此次的拷贝版本 SPUtils.get().edit().putLong(SPUtils.LAST_COPY_VERSION, currentVer).apply(); Map<String, Object> _msg = new HashMap<>(); _msg.put("code", CodeA2U.AssetCopyFinished); UnityMsgHandler.sendMessageToUnity(_msg); } catch (Exception e) { e.printStackTrace(); } } /** * unity单个资源拷贝 * * @param fileName */ public static void copyOneAsset(String fileName) { String originalPath = "android" + File.separator + fileName; String destPath = GameApp.I.getExternalFilesDir( "").getAbsolutePath() + File.separator + fileName; String _destDir = destPath.substring(0, destPath.lastIndexOf('/') + 1); File _file = new File(_destDir); if (!_file.exists()) { boolean mkdir = _file.mkdir(); } try { InputStream _is = GameApp.I.getAssets().open(originalPath); FileOutputStream _fos = new FileOutputStream(new File(destPath)); byte[] _buffer = new byte[1024]; int _byteCount; while ((_byteCount = _is.read(_buffer)) != -1) { _fos.write(_buffer, 0, _byteCount); } _fos.flush(); _is.close(); _fos.close(); } catch (Exception e) { e.printStackTrace(); } } public static void copy(String original, String dest) { try { String[] fileNames = GameApp.I.getAssets().list(original); if (fileNames.length > 0) { File dir = new File(dest); String mkdir = dir.mkdir() ? "成功" : "失败"; LogUtil.i("copyAssets", "[" + original + "] 是一个文件夹, 创建文件夹: [" + dest + "] " + mkdir); for (String _fileName : fileNames) { copy(original + File.separator + _fileName, dest + File.separator + _fileName); } } else { InputStream _is = GameApp.I.getAssets().open(original); FileOutputStream _fos = new FileOutputStream(new File(dest)); byte[] _buffer = new byte[1024]; int _byteCount; while ((_byteCount = _is.read(_buffer)) != -1) { _fos.write(_buffer, 0, _byteCount); } _fos.flush(); _is.close(); _fos.close(); LogUtil.i("copyAssets", "文件: " + original + " 已拷贝至: " + dest); } } catch (Exception e) { e.printStackTrace(); } } public static String getFileNameWithoutExtension(String fileName) { return fileName.substring(0, fileName.lastIndexOf(".")); } /** * 获取文件后缀名 */ public static String getSuffixName(File file) { String fileName = file.getName(); int index = fileName.lastIndexOf("."); if (index == -1) return ""; return fileName.substring(index + 1); } } SdkProject/library/src/main/java/com/secondworld/sdk/utils/LogUtil.java
File was renamed from SdkProject/library/src/main/java/com/secondworld/universalsdk/utils/LogUtil.java @@ -1,9 +1,9 @@ package com.secondworld.universalsdk.utils; package com.secondworld.sdk.utils; import android.content.Context; import android.util.Log; import com.secondworld.universalsdk.BuildConfig; import com.secondworld.sdk.BuildConfig; import java.io.File; import java.text.SimpleDateFormat; SdkProject/library/src/main/java/com/secondworld/sdk/utils/SPUtils.java
New file @@ -0,0 +1,23 @@ package com.secondworld.sdk.utils; import android.content.Context; import android.content.SharedPreferences; import com.secondworld.sdk.GameApp; public class SPUtils { private static SharedPreferences data; public static SharedPreferences get() { if (data == null) data = GameApp.I.getSharedPreferences("data", Context.MODE_PRIVATE); return data; } public static final String UNIQUE_ID = "uniqueID"; public static final String MAC = "mac"; public static final String LAST_COPY_VERSION = "last_copy_version"; public static final String ASSET_IS_COPIED = "asset_is_copied"; } SdkProject/library/src/main/java/com/secondworld/sdk/utils/StaticDefine.java
New file @@ -0,0 +1,12 @@ package com.secondworld.sdk.utils; /** * Created by Administrator on 2018/6/14 0014. */ public interface StaticDefine { String UnityGameObjectName = "SDKUtility"; String UnityHandleFuncName = "HandleSdkMessage"; } SdkProject/library/src/main/java/com/secondworld/sdk/utils/Util.java
New file @@ -0,0 +1,33 @@ package com.secondworld.sdk.utils; import android.text.TextUtils; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class Util { public static String md5(String string) { if (TextUtils.isEmpty(string)) { return ""; } MessageDigest md5 = null; try { md5 = MessageDigest.getInstance("MD5"); byte[] bytes = md5.digest(string.getBytes()); StringBuilder result = new StringBuilder(); for (byte b : bytes) { String temp = Integer.toHexString(b & 0xff); if (temp.length() == 1) { temp = "0" + temp; } result.append(temp); } return result.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; } } SdkProject/library/src/main/java/com/secondworld/universalsdk/GameActivity.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/GameApp.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/H2EngineSDK.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/ThreadExecutor.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/UnityOperator.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/command/CmdAssetCopy.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/command/CmdBatteryListenStart.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/command/CmdBatteryListenStop.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/command/CmdCopyContent.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/command/CmdCopyOneAsset.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/command/CmdExteneralStorage.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/command/CmdInit.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/command/CmdInstallAPK.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/command/CmdOpenWebView.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/command/CmdRequestManifestPermissions.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/command/CmdRequestPermission.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/command/CmdRestartApp.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/command/CmdUniqueID.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/command/ICommand.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/utils/DeviceUtil.java
File was deleted SdkProject/library/src/main/java/com/secondworld/universalsdk/utils/StaticDefine.java
File was deleted SdkProject/library/src/main/res/layout/activity_main.xml
New file @@ -0,0 +1,12 @@ <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main_container" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@+id/unity_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout> SdkProject/library/src/main/res/values/strings.xml
New file @@ -0,0 +1 @@ <resources></resources> SdkProject/library/src/test/java/com/secondworld/sdk/ExampleUnitTest.java
File was renamed from SdkProject/library/src/test/java/com/secondworld/universalsdk/ExampleUnitTest.java @@ -1,4 +1,4 @@ package com.secondworld.universalsdk; package com.secondworld.sdk; import org.junit.Test;