8 次代码提交 3adf1902c2 ... 78bfaabe3b

作者 SHA1 备注 提交日期
  wangyongj 78bfaabe3b sync 2 年之前
  wangyongj 759572951d sync 2 年之前
  wangyongj 9c64659b7a sync merging 2 年之前
  wangyongj 390a0494dd sync 2 年之前
  wangyongj d540f66002 merging 2 年之前
  wangyongj 399203924e “sync” 2 年之前
  wangyongj e9253c0766 Merge branch 'master' of http://8.136.234.80:10002/WangYongJun/GameConsole 2 年之前
  wangyongj 3c12a8419e sync 2 年之前

二进制
3399_systemkey.jks


二进制
android_10_system.jks


+ 16 - 0
app/build.gradle

@@ -37,6 +37,22 @@ android {
             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
         }
     }
+    signingConfigs {
+        debug {
+            keyAlias 'system'
+            keyPassword 'xugame888'
+            storeFile file('../s905_system.jks')
+//            storeFile file('../3399_systemkey.jks')
+//            storeFile file('../android_10_system.jks')
+            storePassword 'xugame888'
+        }
+        release {
+            keyAlias 'system'
+            keyPassword 'xugame888'
+            storeFile file('../s905_system.jks')
+            storePassword 'xugame888'
+        }
+    }
     compileOptions {
         sourceCompatibility JavaVersion.VERSION_1_8
         targetCompatibility JavaVersion.VERSION_1_8

+ 42 - 28
app/src/main/AndroidManifest.xml

@@ -3,13 +3,21 @@
     xmlns:tools="http://schemas.android.com/tools"
     package="com.xugame.gameconsole"
     android:installLocation="internalOnly"
+    android:sharedUserId="android.uid.system"
     android:versionCode="1597175257"
-    android:versionName="1.15.0"
-    >
+    android:versionName="1.15.0">
+
     <uses-feature android:glEsVersion="0x00020000" />
-    <uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
-    <uses-feature android:name="android.software.leanback" android:required="false" />
-    <uses-feature android:name="android.hardware.gamepad" android:required="false"/>
+    <uses-feature
+        android:name="android.hardware.touchscreen"
+        android:required="false" />
+    <uses-feature
+        android:name="android.software.leanback"
+        android:required="false" />
+    <uses-feature
+        android:name="android.hardware.gamepad"
+        android:required="false" />
+
     <uses-permission android:name="android.permission.VIBRATE" />
 
     <uses-permission android:name="android.permission.INTERNET" />
@@ -32,46 +40,53 @@
     <!--    <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>-->
 
 
-
     <uses-permission android:name="android.permission.RECORD_AUDIO" />
 
 
     <application
-        android:allowBackup="true"
         android:allowAudioPlaybackCapture="true"
-        android:icon="@drawable/test_icon_4"
-        android:label="@string/app_name"
-        android:roundIcon="@drawable/test_icon_4"
-        android:supportsRtl="true"
-        android:isGame="true"
-        android:hasCode="true"
+        android:allowBackup="true"
         android:extractNativeLibs="true"
+        android:hasCode="true"
+        android:icon="@mipmap/ic_launcher"
+        android:isGame="true"
+        android:label="@string/app_name"
         android:requestLegacyExternalStorage="true"
+        android:roundIcon="@mipmap/ic_launcher"
+        android:supportsRtl="true"
         android:theme="@style/Theme.GameConsole"
-        tools:ignore="UnusedAttribute"
-        >
+        tools:ignore="UnusedAttribute">
         <activity
             android:name=".TextCopyFileActivity"
-            android:launchMode="singleTop"
             android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale"
+            android:exported="true"
 
-            android:exported="true">
+            android:launchMode="singleTop">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
-
                 <category android:name="android.intent.category.LAUNCHER" />
+                <data
+                    android:host="com.xugame.gameconsole.TextCopyFileActivity"
+                    android:scheme="com.xugame.gameconsole.TextCopyFileActivity"
+                    tools:ignore="AppLinkUrlError" />
             </intent-filter>
         </activity>
-        <activity android:name=".MainActivity"
+        <activity
+            android:name=".MainActivity"
             android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale"
-
-            ></activity>
+            android:exported="true">
+            <intent-filter>
+                <data
+                    android:host="com.xugame.gameconsole.MainActivity"
+                    android:scheme="com.xugame.gameconsole.MainActivity"
+                    tools:ignore="AppLinkUrlError" />
+            </intent-filter>
+        </activity>
         <activity
             android:name=".emulator.RetroArchEmulatorActivity"
             android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale"
 
-            android:launchMode="standard"
-            >
+            android:launchMode="standard">
             <meta-data
                 android:name="android.app.lib_name"
                 android:value="retroarch-activity" />
@@ -80,8 +95,7 @@
                 android:value="ANativeActivity_onCreate" />
         </activity>
 
-        <activity android:name=".Test2Activity"
-            >
+        <activity android:name=".Test2Activity">
             <meta-data
                 android:name="android.app.lib_name"
                 android:value="retroarch-activity" />
@@ -90,14 +104,14 @@
                 android:value="ANativeActivity_onCreate" />
 
         </activity>
-        <activity android:name="com.xugame.Test3Activity"
-            ></activity>
+        <activity android:name="com.xugame.Test3Activity"></activity>
+
         <provider
             android:name="com.retroarch.browser.provider.RetroDocumentsProvider"
             android:authorities="${applicationId}.documents"
-            android:grantUriPermissions="true"
             android:enabled="@bool/document_provider_enabled"
             android:exported="true"
+            android:grantUriPermissions="true"
             android:permission="android.permission.MANAGE_DOCUMENTS">
             <intent-filter>
                 <action android:name="android.content.action.DOCUMENTS_PROVIDER" />

+ 2 - 0
app/src/main/java/com/retroarch/browser/retroactivity/RetroActivityCommon.java

@@ -407,7 +407,9 @@ DebugUtil.i(TAG,"onTick"+millisUntilFinished);
     }
   }
 
+  //call by jni
   public void openGameDialog() {
+    DebugUtil.i(TAG,"openGameDialog");
     showExitDialog();
   }
 

+ 60 - 72
app/src/main/java/com/xugame/gameconsole/MainActivity.java

@@ -24,6 +24,7 @@ import android.widget.Toast;
 
 import com.xugame.gameconsole.emulator.RetroArchEmulatorActivity;
 import com.xugame.gameconsole.preferences.UserPreferences;
+import com.xugame.gameconsole.util.DebugUtil;
 import com.xugame.gameconsole.util.Util;
 
 import java.io.BufferedOutputStream;
@@ -44,19 +45,15 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
     public static String PACKAGE_NAME;
     boolean checkPermissions = false;
 
-    public void showMessageOKCancel(String message, DialogInterface.OnClickListener onClickListener)
-    {
+    public void showMessageOKCancel(String message, DialogInterface.OnClickListener onClickListener) {
         new AlertDialog.Builder(this).setMessage(message)
                 .setPositiveButton("OK", onClickListener).setCancelable(false)
                 .setNegativeButton("Cancel", null).create().show();
     }
 
-    private boolean addPermission(List<String> permissionsList, String permission)
-    {
-        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M)
-        {
-            if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED)
-            {
+    private boolean addPermission(List<String> permissionsList, String permission) {
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
+            if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
                 permissionsList.add(permission);
 
                 // Check for Rationale Option
@@ -68,10 +65,8 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
         return true;
     }
 
-    public void checkRuntimePermissions()
-    {
-        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M)
-        {
+    public void checkRuntimePermissions() {
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
             // Android 6.0+ needs runtime permission checks
             List<String> permissionsNeeded = new ArrayList<String>();
             final List<String> permissionsList = new ArrayList<String>();
@@ -81,12 +76,10 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
             if (!addPermission(permissionsList, Manifest.permission.WRITE_EXTERNAL_STORAGE))
                 permissionsNeeded.add("Write External Storage");
 
-            if (permissionsList.size() > 0)
-            {
+            if (permissionsList.size() > 0) {
                 checkPermissions = true;
 
-                if (permissionsNeeded.size() > 0)
-                {
+                if (permissionsNeeded.size() > 0) {
                     // Need Rationale
                     Log.i("MainMenuActivity", "Need to request external storage permissions.");
 
@@ -96,13 +89,10 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
                         message = message + ", " + permissionsNeeded.get(i);
 
                     showMessageOKCancel(message,
-                            new DialogInterface.OnClickListener()
-                            {
+                            new DialogInterface.OnClickListener() {
                                 @Override
-                                public void onClick(DialogInterface dialog, int which)
-                                {
-                                    if (which == AlertDialog.BUTTON_POSITIVE)
-                                    {
+                                public void onClick(DialogInterface dialog, int which) {
+                                    if (which == AlertDialog.BUTTON_POSITIVE) {
                                         requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
                                                 REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
 
@@ -110,9 +100,7 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
                                     }
                                 }
                             });
-                }
-                else
-                {
+                } else {
                     requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
                             REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
 
@@ -121,14 +109,12 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
             }
         }
 
-        if (!checkPermissions)
-        {
+        if (!checkPermissions) {
             finalStartup();
         }
     }
 
-    public void finalStartup()
-    {
+    public void finalStartup() {
         final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
         Intent retro = new Intent(this, RetroArchEmulatorActivity.class);
 
@@ -147,9 +133,9 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
         startActivity(retro);
         finish();
     }
+
     public static void startRetroActivity(Intent retro, String contentPath, String corePath,
-                                          String configFilePath, String imePath, String dataDirPath, String dataSourcePath)
-    {
+                                          String configFilePath, String imePath, String dataDirPath, String dataSourcePath) {
         if (contentPath != null) {
             retro.putExtra("ROM", contentPath);
         }
@@ -161,27 +147,21 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
         retro.putExtra("SDCARD", Environment.getExternalStorageDirectory().getAbsolutePath());
         String external = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + PACKAGE_NAME + "/files";
         retro.putExtra("EXTERNAL", external);
-        Log.i("TEST_STAT","rompath="+contentPath+"\ncorePath="+corePath+"\n"+"configFilePath="+configFilePath+"\nimePath="+imePath
-                +"\nDATADIR="+dataDirPath+"\nAPK="+dataSourcePath+
-                "\nSDCARD="+Environment.getExternalStorageDirectory().getAbsolutePath()+"\nEXTERNAL="
-                +external);
-        retro.putExtra("screenMode",screenMode);
+        Log.i("TEST_STAT", "rompath=" + contentPath + "\ncorePath=" + corePath + "\n" + "configFilePath=" + configFilePath + "\nimePath=" + imePath
+                + "\nDATADIR=" + dataDirPath + "\nAPK=" + dataSourcePath +
+                "\nSDCARD=" + Environment.getExternalStorageDirectory().getAbsolutePath() + "\nEXTERNAL="
+                + external);
+        retro.putExtra("screenMode", screenMode);
     }
 
     @Override
-    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
-    {
-        switch (requestCode)
-        {
+    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+        switch (requestCode) {
             case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS:
-                for (int i = 0; i < permissions.length; i++)
-                {
-                    if(grantResults[i] == PackageManager.PERMISSION_GRANTED)
-                    {
+                for (int i = 0; i < permissions.length; i++) {
+                    if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                         Log.i("MainMenuActivity", "Permission: " + permissions[i] + " was granted.");
-                    }
-                    else
-                    {
+                    } else {
                         Log.i("MainMenuActivity", "Permission: " + permissions[i] + " was not granted.");
                     }
                 }
@@ -194,8 +174,10 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
 
         finalStartup();
     }
-    private String corePath,romPath,coreName;
-    private static int screenMode=0;
+
+    private String baseUsbPath, corePath, romPath, coreName;
+    private static int screenMode = 0;
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -203,24 +185,24 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
 //        this.findView();
         Util.init(this);
         PACKAGE_NAME = getPackageName();
-        romPath=getIntent().getStringExtra("romPath");
-        corePath=getIntent().getStringExtra("corePath");
-        coreName=getIntent().getStringExtra("coreName");
-        screenMode=getIntent().getIntExtra("screenMode",0);
-
-
+        baseUsbPath = getIntent().getStringExtra("baseUsbPath");
+        romPath = getIntent().getStringExtra("romPath");
+        corePath = getIntent().getStringExtra("corePath");
+        coreName = getIntent().getStringExtra("coreName");
+        screenMode = getIntent().getIntExtra("screenMode", 0);
         checkCores();
 
     }
-    private void checkCores(){
-        if(TextUtils.isEmpty(corePath)){
+
+    private void checkCores() {
+        if (TextUtils.isEmpty(corePath)) {
             finish();
         }
-        File file=new File(corePath);
-        if(file.exists()){
+        File file = new File(corePath);
+        if (file.exists()) {
             start();
-        }else {
-            startCopy(coreName,corePath);
+        } else {
+            startCopy(coreName, corePath);
         }
     }
 
@@ -232,7 +214,7 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
         new AsyncTask<String, Integer, String>() {
             @Override
             protected String doInBackground(String... strings) {
-                copyFile(getFilesDir().getParent() + File.separator+"cores/" + fileName, fileName);
+                copyFile(getFilesDir().getParent() + File.separator + "cores/" + fileName, fileName);
                 return null;
             }
 
@@ -246,17 +228,23 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
 
 
     private boolean copyFile(String file_path, String fileName) {
-        File baseFile=new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/arcade/cores/");
-        if(!baseFile.exists())//创建/arcade/cores文件夹
+        File baseFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/arcade/cores/");
+        if (!baseFile.exists())//创建/arcade/cores文件夹
             baseFile.mkdirs();
+        File file;
+        if (!TextUtils.isEmpty(baseUsbPath)) {
+            file = new File(baseUsbPath + "/cores/" + fileName);
+        } else
+            file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/arcade/cores/" + fileName);
 
-        File file=new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/arcade/cores/"+fileName);
-        if(!file.exists())//检测cores文件夹下是否存在.so
+        if (!file.exists())//检测cores文件夹下是否存在.so
             return false;
+        DebugUtil.i("COPY:", file.getAbsolutePath());
+
         try {
             InputStream in = null;
 //            in = this.getResources().getAssets().open("xucores/"+fileName);
-            in= new FileInputStream(file);
+            in = new FileInputStream(file);
             BufferedOutputStream outStream
                     = new BufferedOutputStream(new FileOutputStream(file_path, false));
             byte[] buffer = new byte[1024];
@@ -276,11 +264,12 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
 
         return false;
     }
-    private void start(){
+
+    private void start() {
         // Bind audio stream to hardware controls.
         setVolumeControlStream(AudioManager.STREAM_MUSIC);
 
-        UserPreferences.updateConfigFile(this);
+        UserPreferences.updateConfigFile(this,baseUsbPath+File.separator+"/system");
 
         checkRuntimePermissions();
     }
@@ -303,9 +292,8 @@ public class MainActivity extends PreferenceActivity implements View.OnClickList
 
         if (view == mBtnLocalGame) {
 
-            if (!checkPermissions)
-            {
-            finalStartup();
+            if (!checkPermissions) {
+                finalStartup();
             }
 
 //            String PACKAGE_NAME = this.getPackageName();

+ 5 - 1
app/src/main/java/com/xugame/gameconsole/TextCopyFileActivity.java

@@ -109,7 +109,7 @@ public class TextCopyFileActivity extends Activity {
         btn1 = findViewById(R.id.btn1);
         btn2 = findViewById(R.id.btn2);
         btn3 = findViewById(R.id.btn3);
-        btn4 = findViewById(R.id.btn4);
+        btn4=findViewById(R.id.btn4);
         btn1.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
@@ -140,6 +140,8 @@ public class TextCopyFileActivity extends Activity {
         btn4.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
+
+
                 startGame(Environment.getExternalStorageDirectory().getAbsolutePath() + "/arcade/rom/PPSSPP/三国无双/三国无双.iso",
                         mContext.getFilesDir().getParent() + "/cores/ppsspp_libretro_android.so",
                         EmulatorType.PSP);
@@ -168,6 +170,8 @@ public class TextCopyFileActivity extends Activity {
                 case NES:
                     coreName = "mesen_libretro_android.so";
                     break;
+                case PS1:
+                    coreName="mednafen_psx_libretro_android.so";
                 case PSP:
                     coreName = "ppsspp_libretro_android.so";
                     break;

+ 8 - 0
app/src/main/java/com/xugame/gameconsole/dialog/gamemenu/GameMenuDialog.java

@@ -275,6 +275,14 @@ public class GameMenuDialog extends BaseDialog
 
     }
 
+    @Override
+    public void dismiss() {
+        if(mListener!=null){
+            mListener.onResumeGame(mType, mReadArchiveIndex);
+        }
+        super.dismiss();
+
+    }
 
     @Override
     public void onClick(View view) {

+ 1 - 0
app/src/main/java/com/xugame/gameconsole/emulator/EmulatorType.java

@@ -6,5 +6,6 @@ public enum EmulatorType {
     CPS1,
     CPS2,
     CPS3,
+    PS1,
     PSP,
 }

+ 19 - 15
app/src/main/java/com/xugame/gameconsole/emulator/RetroArchEmulatorActivity.java

@@ -114,14 +114,18 @@ public class RetroArchEmulatorActivity extends RetroActivityCamera {
 
     @Override
     public void showLocalExitDialog() {
-        runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                showDialog();
-            }
-        });
-
-        DebugUtil.i(TAG, "showLocalExitDialog");
+//        runOnUiThread(new Runnable() {
+//            @Override
+//            public void run() {
+//                showDialog();
+//            }
+//        });
+        Intent intent=new Intent();//调出主菜单UI
+        ComponentName componentName=new ComponentName("com.xugame.gameconsoleMenu",
+                "com.xugame.gameconsole.dialog.localgamesetting.LocalGameSettingDialog");
+        intent.setComponent(componentName);
+        startActivityForResult(intent,200);
+        DebugUtil.i(TAG,"showLocalExitDialog");
     }
 
     @Override
@@ -169,8 +173,8 @@ public class RetroArchEmulatorActivity extends RetroActivityCamera {
             // This requires NVIDIA Android extensions (available on NVIDIA Shield), if they are not
             // available then nothing will be done
             if (retro.hasExtra("HIDEMOUSE")) hideMouseCursor();
-            int screenMode = retro.getIntExtra("screenMode", 0);
-            if (screenMode >= 0 && screenMode < 3) {
+            int screenMode=retro.getIntExtra("screenMode",0);
+            if(screenMode>=0&&screenMode<3){
                 switch (screenMode) {
                     case 0:
                         setAspectRatio(AspectRatio.ASPECT_RATIO_CORE.getValue());
@@ -235,11 +239,11 @@ public class RetroArchEmulatorActivity extends RetroActivityCamera {
         if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
                 && event.getAction() == KeyEvent.ACTION_DOWN) {
 //            showDialog();
-            Intent intent = new Intent();//调出主菜单UI
-            ComponentName componentName = new ComponentName("com.xugame.gameconsoleMenu",
+            Intent intent=new Intent();//调出主菜单UI
+            ComponentName componentName=new ComponentName("com.xugame.gameconsoleMenu",
                     "com.xugame.gameconsole.dialog.localgamesetting.LocalGameSettingDialog");
-            intent.setComponent(componentName);
-            startActivityForResult(intent, 200);
+           intent.setComponent(componentName);
+            startActivityForResult(intent,200);
             return super.dispatchKeyEvent(event);
         }
 
@@ -352,7 +356,7 @@ public class RetroArchEmulatorActivity extends RetroActivityCamera {
                 if (data != null) {
                     int scanLine = data.getIntExtra("scanLine", 0);
                     int screen = data.getIntExtra("screen", 0);
-                    DebugUtil.i(TAG, "scanline=" + scanLine + "screen=" + screen);
+                    DebugUtil.i(TAG,"scanline="+scanLine+"screen="+screen);
 
                     if (screen >= 0 && screen < 3) {
                         switch (screen) {

+ 78 - 0
app/src/main/java/com/xugame/gameconsole/monitor/EmulatorMonitor.java

@@ -0,0 +1,78 @@
+package com.xugame.gameconsole.monitor;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.text.TextUtils;
+
+import com.xugame.gameconsole.util.DebugUtil;
+
+public class EmulatorMonitor {
+
+    private final String TAG = "EmulatorMonitor";
+    private static final String EMULATOR_SAVE_STATE_ACTION = "EMULATOR_SAVE_STATE_ACTION";
+    private static final String EMULATOR_LOAD_STATE_ACTION = "EMULATOR_LOAD_STATE_ACTION";
+
+
+    private static final String SYSTEM_REASON = "reason";
+    private static final String SYSTEM_HOME_KEY = "homekey";
+    private static final String SYSTEM_HOME_RECENT_APPS = "recentapps";
+
+    private Context mContext;
+    private BroadcastReceiver mDeviceKeyReceiver = null;
+    private EmulatorMonitorListener mListener;
+
+    public EmulatorMonitor(Context context, EmulatorMonitorListener listener) {
+        mContext = context;
+        mListener = listener;
+        mDeviceKeyReceiver = new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (intent != null) {
+                    parserIntent(intent);
+                }
+            }
+        };
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+        filter.addAction(EMULATOR_SAVE_STATE_ACTION);
+        filter.addAction(EMULATOR_LOAD_STATE_ACTION);
+        mContext.registerReceiver(mDeviceKeyReceiver,
+                filter);
+    }
+
+
+    private void parserIntent(Intent intent) {
+        DebugUtil.i(TAG, "" + intent.getAction());
+        if (intent.getAction().equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
+            String reason = intent.getStringExtra(SYSTEM_REASON);
+            if (!TextUtils.isEmpty(reason)) {
+                if (SYSTEM_HOME_KEY.equals(reason)) {
+                    mListener.onHomeClick();
+                } else if (SYSTEM_HOME_RECENT_APPS.equals(reason)) {
+                    mListener.onRecentClick();
+                }
+            }
+        } else if (intent.getAction().equals(EMULATOR_SAVE_STATE_ACTION)) {
+            int stateIndex = intent.getIntExtra("saveState", -1);
+            if (stateIndex >= 0 && mListener != null) {
+                mListener.onMenuSaveState(stateIndex);
+            }
+        } else if (intent.getAction().equals(EMULATOR_LOAD_STATE_ACTION)) {
+            int stateIndex = intent.getIntExtra("loadState", -1);
+            if (stateIndex >=0 && mListener != null) {
+                mListener.onMenuLoadState(stateIndex);
+            }
+        }
+    }
+
+
+    public void unregister() {
+        if (mDeviceKeyReceiver != null) {
+            mContext.unregisterReceiver(mDeviceKeyReceiver);
+            mDeviceKeyReceiver = null;
+        }
+    }
+
+}

+ 11 - 0
app/src/main/java/com/xugame/gameconsole/monitor/EmulatorMonitorListener.java

@@ -0,0 +1,11 @@
+package com.xugame.gameconsole.monitor;
+
+public interface EmulatorMonitorListener {
+    void onHomeClick();
+
+    void onRecentClick();
+
+    void onMenuSaveState(int index);
+
+    void onMenuLoadState(int index);
+}

+ 34 - 63
app/src/main/java/com/xugame/gameconsole/preferences/UserPreferences.java

@@ -21,19 +21,16 @@ public class UserPreferences {
     private static final String TAG = "UserPreferences";
 
     // Disallow explicit instantiation.
-    private UserPreferences()
-    {
+    private UserPreferences() {
     }
 
     /**
      * Retrieves the path to the default location of the libretro config.
      *
      * @param ctx the current {@link Context}
-     *
      * @return the path to the default location of the libretro config.
      */
-    public static String getDefaultConfigPath(Context ctx)
-    {
+    public static String getDefaultConfigPath(Context ctx) {
         // Internal/External storage dirs.
         final String internal = ctx.getFilesDir().getAbsolutePath();
         String external = null;
@@ -58,30 +55,23 @@ public class UserPreferences {
 
         String append_path;
         // If we aren't using the global config.
-        if (!globalConfigEnabled && !libretro_path.equals(coreDir))
-        {
+        if (!globalConfigEnabled && !libretro_path.equals(coreDir)) {
             String sanitized_name = sanitizeLibretroPath(libretro_path);
             append_path = File.separator + sanitized_name + ".cfg";
-        }
-        else // Using global config.
+        } else // Using global config.
         {
             append_path = File.separator + "retroarch.cfg";
         }
 
-        if (external != null)
-        {
+        if (external != null) {
             String confPath = external + append_path;
             if (new File(confPath).exists())
                 return confPath;
-        }
-        else if (internal != null)
-        {
+        } else if (internal != null) {
             String confPath = internal + append_path;
             if (new File(confPath).exists())
                 return confPath;
-        }
-        else
-        {
+        } else {
             String confPath = "/mnt/extsd" + append_path;
             if (new File(confPath).exists())
                 return confPath;
@@ -101,9 +91,7 @@ public class UserPreferences {
 
         try {
             new File(new_path).createNewFile();
-        }
-        catch (IOException e)
-        {
+        } catch (IOException e) {
             Log.e(TAG, "Failed to create config file to: " + new_path);
         }
         return new_path;
@@ -115,8 +103,7 @@ public class UserPreferences {
      *
      * @param ctx the current {@link Context}.
      */
-    public static void updateConfigFile(Context ctx)
-    {
+    public static void updateConfigFile(Context ctx, String systemDir) {
         String path = getDefaultConfigPath(ctx);
         ConfigFile config = new ConfigFile(path);
 
@@ -133,6 +120,10 @@ public class UserPreferences {
         config.setString("input_overlay_enable", "false");
         config.setBoolean("log_verbosity", true);
         config.setBoolean("fps_show", true);
+        config.setString("system_directory", systemDir);//20230829添加system路径设置
+        DebugUtil.i(TAG,"write system dir:"+systemDir);
+        config.setInt("input_player1_analog_dpad_mode", 1);
+
         config.setInt("frontend_log_level", 1);
         config.setInt("libretro_log_level", 1);
 
@@ -141,66 +132,56 @@ public class UserPreferences {
             config.setInt("audio_out_rate", samplingRate);
         }
 
-        try
-        {
-            int version							= ctx.getPackageManager().
+        try {
+            int version = ctx.getPackageManager().
                     getPackageInfo(ctx.getPackageName(), 0).versionCode;
-            final String dst_path			= dataDir;
-            final String dst_path_subdir	= "assets";
+            final String dst_path = dataDir;
+            final String dst_path_subdir = "assets";
 
             Log.i(TAG, "dst dir is: " + dst_path);
             Log.i(TAG, "dst subdir is: " + dst_path_subdir);
 
             config.setString("bundle_assets_src_path", ctx.getApplicationInfo().sourceDir);
-            DebugUtil.i(TAG,"source="+ctx.getApplicationInfo().sourceDir);
-            DebugUtil.i(TAG,"versionCode="+version);
+            DebugUtil.i(TAG, "source=" + ctx.getApplicationInfo().sourceDir);
+            DebugUtil.i(TAG, "versionCode=" + version);
             config.setString("bundle_assets_dst_path", dst_path);
             config.setString("bundle_assets_dst_path_subdir", dst_path_subdir);
             config.setInt("bundle_assets_extract_version_current", version);
-        }
-        catch (PackageManager.NameNotFoundException ignored)
-        {
+        } catch (PackageManager.NameNotFoundException ignored) {
         }
 
         // Refactor this entire mess and make this usable for per-core config
-        if (Build.VERSION.SDK_INT >= 17 && prefs.getBoolean("audio_latency_auto", true))
-        {
+        if (Build.VERSION.SDK_INT >= 17 && prefs.getBoolean("audio_latency_auto", true)) {
             int bufferSize = getLowLatencyBufferSize(ctx);
             if (bufferSize != -1) {
                 config.setInt("audio_block_frames", bufferSize);
             }
         }
 
-        try
-        {
+        try {
             config.write(path);
-        }
-        catch (IOException e)
-        {
+        } catch (IOException e) {
             Log.e(TAG, "Failed to save config file to: " + path);
         }
     }
 
-    private static void readbackString(ConfigFile cfg, SharedPreferences.Editor edit, String key)
-    {
+    private static void readbackString(ConfigFile cfg, SharedPreferences.Editor edit, String key) {
         if (cfg.keyExists(key))
             edit.putString(key, cfg.getString(key));
         else
             edit.remove(key);
     }
 
-    private static void readbackBool(ConfigFile cfg, SharedPreferences.Editor edit, String key)
-    {
+    private static void readbackBool(ConfigFile cfg, SharedPreferences.Editor edit, String key) {
         if (cfg.keyExists(key))
             edit.putBoolean(key, cfg.getBoolean(key));
         else
             edit.remove(key);
     }
 
-    private static void readbackDouble(ConfigFile cfg, SharedPreferences.Editor edit, String key)
-    {
+    private static void readbackDouble(ConfigFile cfg, SharedPreferences.Editor edit, String key) {
         if (cfg.keyExists(key))
-            edit.putFloat(key, (float)cfg.getDouble(key));
+            edit.putFloat(key, (float) cfg.getDouble(key));
         else
             edit.remove(key);
     }
@@ -229,11 +210,9 @@ public class UserPreferences {
      * Sanitizes a libretro core path.
      *
      * @param path The path to the libretro core.
-     *
      * @return the sanitized libretro path.
      */
-    private static String sanitizeLibretroPath(String path)
-    {
+    private static String sanitizeLibretroPath(String path) {
         String sanitized_name = path.substring(
                 path.lastIndexOf('/') + 1,
                 path.lastIndexOf('.'));
@@ -247,11 +226,9 @@ public class UserPreferences {
      * Gets a {@link SharedPreferences} instance containing current settings.
      *
      * @param ctx the current {@link Context}.
-     *
      * @return A SharedPreference instance containing current settings.
      */
-    public static SharedPreferences getPreferences(Context ctx)
-    {
+    public static SharedPreferences getPreferences(Context ctx) {
         return PreferenceManager.getDefaultSharedPreferences(ctx);
     }
 
@@ -259,16 +236,14 @@ public class UserPreferences {
      * Gets the optimal sampling rate for low-latency audio playback.
      *
      * @param ctx the current {@link Context}.
-     *
      * @return the optimal sampling rate for low-latency audio playback in Hz.
      */
     @TargetApi(17)
-    private static int getLowLatencyOptimalSamplingRate(Context ctx)
-    {
+    private static int getLowLatencyOptimalSamplingRate(Context ctx) {
         AudioManager manager = (AudioManager) ctx.getSystemService(Context.AUDIO_SERVICE);
         String value = manager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
 
-        if(value == null || value.isEmpty()) {
+        if (value == null || value.isEmpty()) {
             return -1;
         }
 
@@ -279,16 +254,14 @@ public class UserPreferences {
      * Gets the optimal buffer size for low-latency audio playback.
      *
      * @param ctx the current {@link Context}.
-     *
      * @return the optimal output buffer size in decimal PCM frames.
      */
     @TargetApi(17)
-    private static int getLowLatencyBufferSize(Context ctx)
-    {
+    private static int getLowLatencyBufferSize(Context ctx) {
         AudioManager manager = (AudioManager) ctx.getSystemService(Context.AUDIO_SERVICE);
         String value = manager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
 
-        if(value == null || value.isEmpty()) {
+        if (value == null || value.isEmpty()) {
             return -1;
         }
 
@@ -307,11 +280,9 @@ public class UserPreferences {
      * as returned by the hardware.
      *
      * @param ctx The current {@link Context}.
-     *
      * @return the optimal audio sampling rate in Hz.
      */
-    private static int getOptimalSamplingRate(Context ctx)
-    {
+    private static int getOptimalSamplingRate(Context ctx) {
         int ret;
         if (Build.VERSION.SDK_INT >= 17)
             ret = getLowLatencyOptimalSamplingRate(ctx);

二进制
app/src/main/res/drawable/app_main_bg.png


+ 5 - 3
app/src/main/res/layout/textcopp_layout.xml

@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
+    android:orientation="vertical"
     android:layout_height="match_parent">
 
     <Button
@@ -29,7 +30,8 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_below="@+id/btn1"
-        android:layout_marginTop="110dp"
+        android:layout_marginTop="54dp"
         android:text="三国无双"></Button>
+</LinearLayout>
+
 
-</RelativeLayout>

+ 1 - 1
app/src/main/res/values/strings.xml

@@ -1,3 +1,3 @@
 <resources>
-    <string name="app_name">约战掌机测试</string>
+    <string name="app_name">Emulator</string>
 </resources>

+ 1 - 0
app/src/main/res/values/themes.xml

@@ -8,6 +8,7 @@
         <!-- Secondary brand color. -->
         <item name="colorSecondary">@color/teal_200</item>
         <item name="colorSecondaryVariant">@color/teal_700</item>
+        <item name="android:windowBackground">@drawable/app_main_bg</item>
         <item name="colorOnSecondary">@color/black</item>
         <!-- Status bar color. -->
         <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>

二进制
s905_system.jks