(Android) Big changes -

- both MainMenuActivity and RetroActivity are single instances now
- AKEYCODE_BACK gets eaten and onBackPressed in Java is triggered
- onBackPressed right now calls an instance of MainMenuActivity
(reuses the existing activity on the stack)
- User can switch back and forth between RetroActivity and MainMenuActivity
with AKEYCODE_BACK / Back button
- When a subsequent intent is launched after RetroActivity has already been
started up once, the pending intent gets passed to the existing RetroActivity
throug onNewIntent - in C land it will look every frame if an intent is pending - if it is, it will look up certain variables through JNI to launch a new game - or whatever it is that the intent wants to do
- With this we can now switch seamlessly between Android UI and RetroArch
itself.
This commit is contained in:
twinaphex 2013-11-24 22:02:57 +01:00
parent 1d06b07a16
commit 6c638f91f4
11 changed files with 200 additions and 54 deletions

View File

@ -1692,7 +1692,13 @@ static void android_input_poll(void *data)
if (keycode == AKEYCODE_BACK)
{
if (android->onBackPressed)
uint8_t unpacked = (android->keycode_lut[AKEYCODE_BACK] >> ((state_id+1) << 3)) - 1;
uint64_t input_state = (1ULL << unpacked);
if (type_event == AINPUT_EVENT_TYPE_KEY && input_state < (1ULL << RARCH_FIRST_META_KEY)
&& input_state > 0)
{
}
else if (android->onBackPressed)
{
RARCH_LOG("Invoke onBackPressed through JNI.\n");
JNIEnv *env = jni_thread_getenv();
@ -1701,43 +1707,6 @@ static void android_input_poll(void *data)
CALL_VOID_METHOD(env, android_app->activity->clazz, android->onBackPressed);
}
}
#if 1
uint8_t unpacked = (android->keycode_lut[AKEYCODE_BACK] >> ((state_id+1) << 3)) - 1;
uint64_t input_state = (1ULL << unpacked);
// FIXME: all of the below will probably all have to be refactored
if (g_extern.lifecycle_state & (1ULL << MODE_INPUT_XPERIA_PLAY_HACK))
{
int meta = AKeyEvent_getMetaState(event);
if (!(meta & AMETA_ALT_ON))
{
*lifecycle_state |= (1ULL << RARCH_QUIT_KEY);
AInputQueue_finishEvent(android_app->inputQueue, event, handled);
break;
}
}
else if (type_event == AINPUT_EVENT_TYPE_KEY && input_state < (1ULL << RARCH_FIRST_META_KEY)
&& input_state > 0)
{
}
else if (g_settings.input.back_behavior == BACK_BUTTON_MENU_TOGGLE)
{
int action = AKeyEvent_getAction(event);
if (action == AKEY_EVENT_ACTION_DOWN)
*lifecycle_state |= (1ULL << RARCH_MENU_TOGGLE);
else if (action == AKEY_EVENT_ACTION_UP)
*lifecycle_state &= ~(1ULL << RARCH_MENU_TOGGLE);
AInputQueue_finishEvent(android_app->inputQueue, event, handled);
break;
}
else
{
// exits the app, so no need to check for up/down action
*lifecycle_state |= (1ULL << RARCH_QUIT_KEY);
AInputQueue_finishEvent(android_app->inputQueue, event, handled);
break;
}
#endif
}
if (type_event == AINPUT_EVENT_TYPE_MOTION)

View File

@ -17,7 +17,7 @@
android:label="@string/app_name"
android:hasCode="true">
<activity android:name="com.retroarch.browser.DisplayRefreshRateTest"/>
<activity android:name="com.retroarch.browser.mainmenu.MainMenuActivity" android:exported="true">
<activity android:name="com.retroarch.browser.mainmenu.MainMenuActivity" android:exported="true" android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@ -30,7 +30,7 @@
<activity android:name="com.retroarch.browser.preferences.PreferenceActivity" android:theme="@style/Theme.AppCompat" />
<activity android:name="com.retroarch.browser.coremanager.CoreManagerActivity" android:theme="@style/Theme.AppCompat"/>
<activity android:name="com.retroarch.browser.RetroActivity" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
<activity android:name="com.retroarch.browser.RetroActivity" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:launchMode="singleInstance">
<meta-data android:name="android.app.lib_name" android:value="retroarch-activity" />
<meta-data android:name="android.app.func_name" android:value="ANativeActivity_onCreate" />
</activity>

View File

@ -13,13 +13,14 @@
<!-- Main Menu Strings -->
<string name="mainmenu_title">RetroArch - Main Menu</string>
<string name="tv_mode">TV Mode</string>
<string name="tv_mode">Resume Game</string>
<string name="load_core">Load Core</string>
<string name="load_game">Load Game</string>
<string name="load_game_history">Load Game (History)</string>
<string name="settings">Settings</string>
<string name="help">Help</string>
<string name="about">About</string>
<string name="quit">Quit RetroArch</string>
<!-- Core Selection Class -->
<string name="select_libretro_core">Select a libretro core</string>

View File

@ -62,4 +62,9 @@
</Preference>
</PreferenceCategory>
</PreferenceScreen>
<!-- Quit RetroArch -->
<Preference
android:key="quitRetroArch"
android:title="@string/quit"/>
</PreferenceScreen>

View File

@ -106,7 +106,6 @@ public final class HistorySelection extends DialogFragment
retro.putExtra("LIBRETRO", corePath);
retro.putExtra("CONFIGFILE", UserPreferences.getDefaultConfigPath(ctx));
retro.putExtra("IME", current_ime);
retro.putExtra("USED", "false");
startActivity(retro);
dismiss();
}

View File

@ -2,10 +2,12 @@ package com.retroarch.browser;
import java.io.IOException;
import com.retroarch.browser.mainmenu.MainMenuActivity;
import com.retroarch.browser.preferences.util.UserPreferences;
import android.annotation.SuppressLint;
import android.app.NativeActivity;
import android.content.Intent;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Build;
@ -17,6 +19,7 @@ public final class RetroActivity extends NativeActivity
private long lastTimestamp = 0;
private SurfaceTexture texture;
private Boolean updateSurface = true;
private Intent pendingIntent = null;
public void onCameraStart()
{
@ -114,9 +117,53 @@ public final class RetroActivity extends NativeActivity
{
}
@Override
public void onNewIntent(Intent intent)
{
Log.i("RetroActivity", "onNewIntent invoked.");
super.onNewIntent(intent);
setIntent(intent);
pendingIntent = intent;
}
public String getPendingIntentFullPath()
{
return pendingIntent.getStringExtra("ROM");
}
public String getPendingIntentLibretroPath()
{
return pendingIntent.getStringExtra("LIBRETRO");
}
public String getPendingIntentConfigPath()
{
return pendingIntent.getStringExtra("CONFIGFILE");
}
public String getPendingIntentIME()
{
return pendingIntent.getStringExtra("IME");
}
public boolean hasPendingIntent()
{
if (pendingIntent == null)
return false;
return true;
}
public void clearPendingIntent()
{
pendingIntent = null;
}
@Override
public void onBackPressed()
{
Log.i("RetroActivity", "onBackKeyPressed");
Intent retro = new Intent(this, MainMenuActivity.class);
retro.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(retro);
}
}

View File

@ -59,6 +59,7 @@ public final class MainMenuFragment extends PreferenceListFragment implements On
findPreference("loadCorePref").setOnPreferenceClickListener(this);
findPreference("loadRomPref").setOnPreferenceClickListener(this);
findPreference("loadRomHistoryPref").setOnPreferenceClickListener(this);
findPreference("quitRetroArch").setOnPreferenceClickListener(this);
// Extract assets.
extractAssets();
@ -341,7 +342,6 @@ public final class MainMenuFragment extends PreferenceListFragment implements On
retro.putExtra("LIBRETRO", libretro_path);
retro.putExtra("CONFIGFILE", UserPreferences.getDefaultConfigPath(ctx));
retro.putExtra("IME", current_ime);
retro.putExtra("USED", "false");
startActivity(retro);
}
// Load Core Preference
@ -350,6 +350,12 @@ public final class MainMenuFragment extends PreferenceListFragment implements On
final CoreSelection coreSelection = new CoreSelection();
coreSelection.show(getFragmentManager(), "core_selection");
}
// Quit RetroArch preference
else if (prefKey.equals("quitRetroArch"))
{
// TODO - needs to close entire app gracefully - including
// NativeActivity if possible
}
// Load ROM Preference
else if (prefKey.equals("loadRomPref"))
{
@ -397,7 +403,6 @@ public final class MainMenuFragment extends PreferenceListFragment implements On
retro.putExtra("LIBRETRO", libretro_path);
retro.putExtra("CONFIGFILE", UserPreferences.getDefaultConfigPath(ctx));
retro.putExtra("IME", current_ime);
retro.putExtra("USED", "false");
startActivity(retro);
}
}

View File

@ -976,6 +976,20 @@ static void menu_flush_stack_type(void *data, unsigned final_type)
}
}
void load_menu_game_new_core(void)
{
#ifdef HAVE_DYNAMIC
libretro_free_system_info(&rgui->info);
libretro_get_system_info(g_settings.libretro, &rgui->info,
&rgui->load_no_rom);
g_extern.lifecycle_state |= (1ULL << MODE_LOAD_GAME);
#else
rarch_environment_cb(RETRO_ENVIRONMENT_SET_LIBRETRO_PATH, (void*)g_settings.libretro);
rarch_environment_cb(RETRO_ENVIRONMENT_EXEC, (void*)g_extern.fullpath);
#endif
}
static int menu_iterate_func(void *data, unsigned action)
{
rgui_handle_t *rgui = (rgui_handle_t*)data;
@ -1118,16 +1132,7 @@ static int menu_iterate_func(void *data, unsigned action)
// FIXME: Add for consoles.
strlcpy(g_settings.libretro, path, sizeof(g_settings.libretro));
strlcpy(g_extern.fullpath, rgui->deferred_path, sizeof(g_extern.fullpath));
#ifdef HAVE_DYNAMIC
libretro_free_system_info(&rgui->info);
libretro_get_system_info(g_settings.libretro, &rgui->info,
&rgui->load_no_rom);
g_extern.lifecycle_state |= (1ULL << MODE_LOAD_GAME);
#else
rarch_environment_cb(RETRO_ENVIRONMENT_SET_LIBRETRO_PATH, (void*)g_settings.libretro);
rarch_environment_cb(RETRO_ENVIRONMENT_EXEC, (void*)g_extern.fullpath);
#endif
load_menu_game_new_core();
rgui->msg_force = true;
ret = -1;
menu_flush_stack_type(rgui, RGUI_SETTINGS);

View File

@ -355,6 +355,7 @@ void menu_init_core_info(void *data);
void load_menu_game_prepare(void);
bool load_menu_game(void);
void load_menu_game_history(unsigned game_index);
extern void load_menu_game_new_core(void);
void menu_rom_history_push(const char *path, const char *core_path,
const char *core_name);
void menu_rom_history_push_current(void);

View File

@ -22,6 +22,7 @@
#include <sys/resource.h>
#include "platform_android.h"
#include "../menu/menu_common.h"
#include "../../android/native/jni/jni_macros.h"
#include "../../conf/config_file.h"
@ -460,13 +461,110 @@ static void get_environment_settings(int argc, char *argv[], void *data)
}
static void process_pending_intent(void *data)
{
RARCH_LOG("process_pending_intent.\n");
JNIEnv *env;
struct android_app* android_app = (struct android_app*)data;
jstring jstr = NULL;
bool valschanged = false;
bool startgame = false;
if (!android_app)
return;
env = jni_thread_getenv();
if (!env)
return;
// ROM
jstr = (*env)->CallObjectMethod(env, android_app->activity->clazz, android_app->getPendingIntentFullPath);
JNI_EXCEPTION(env);
RARCH_LOG("Checking arguments passed from intent...\n");
if (android_app->getPendingIntentFullPath && jstr)
{
const char *argv = (*env)->GetStringUTFChars(env, jstr, 0);
strlcpy(g_extern.fullpath, argv, sizeof(g_extern.fullpath));
(*env)->ReleaseStringUTFChars(env, jstr, argv);
valschanged = true;
startgame = true;
RARCH_LOG("ROM Filename: [%s].\n", g_extern.fullpath);
}
// Config file
jstr = (*env)->CallObjectMethod(env, android_app->activity->clazz, android_app->getPendingIntentConfigPath);
JNI_EXCEPTION(env);
if (android_app->getPendingIntentConfigPath && jstr)
{
const char *argv = (*env)->GetStringUTFChars(env, jstr, 0);
strlcpy(g_extern.config_path, argv, sizeof(g_extern.config_path));
(*env)->ReleaseStringUTFChars(env, jstr, argv);
valschanged = true;
RARCH_LOG("Config file: [%s].\n", g_extern.config_path);
}
// Current IME
jstr = (*env)->CallObjectMethod(env, android_app->activity->clazz, android_app->getPendingIntentIME);
JNI_EXCEPTION(env);
if (android_app->getPendingIntentIME && jstr)
{
const char *argv = (*env)->GetStringUTFChars(env, jstr, 0);
strlcpy(android_app->current_ime, argv, sizeof(android_app->current_ime));
(*env)->ReleaseStringUTFChars(env, jstr, argv);
valschanged = true;
RARCH_LOG("Current IME: [%s].\n", android_app->current_ime);
}
if (valschanged)
{
g_extern.block_config_read = false;
config_load();
g_extern.block_config_read = true;
}
//LIBRETRO
jstr = (*env)->CallObjectMethod(env, android_app->activity->clazz, android_app->getPendingIntentLibretroPath);
JNI_EXCEPTION(env);
if (android_app->getPendingIntentLibretroPath && jstr)
{
const char *argv = (*env)->GetStringUTFChars(env, jstr, 0);
strlcpy(g_settings.libretro, argv, sizeof(g_settings.libretro));
(*env)->ReleaseStringUTFChars(env, jstr, argv);
}
RARCH_LOG("Libretro path: [%s].\n", g_settings.libretro);
if (startgame)
{
RARCH_LOG("Starting new game %s...\n", g_extern.fullpath);
g_extern.lifecycle_state &= ~(1ULL << MODE_MENU);
g_extern.lifecycle_state &= ~(1ULL << MODE_GAME);
load_menu_game_new_core();
}
CALL_VOID_METHOD(env, android_app->activity->clazz, android_app->clearPendingIntent);
}
static int process_events(void *data)
{
jboolean hasPendingIntent;
JNIEnv *env;
struct android_app* android_app = (struct android_app*)data;
if (input_key_pressed_func(RARCH_PAUSE_TOGGLE))
android_run_events(android_app);
env = jni_thread_getenv();
if (!env)
return -1;
CALL_BOOLEAN_METHOD(env, hasPendingIntent, android_app->activity->clazz, android_app->hasPendingIntent);
if (hasPendingIntent)
process_pending_intent(android_app);
return 0;
}
@ -509,6 +607,16 @@ static void system_init(void *data)
GET_OBJECT_CLASS(env, class, android_app->activity->clazz);
GET_METHOD_ID(env, android_app->getIntent, class, "getIntent", "()Landroid/content/Intent;");
CALL_OBJ_METHOD(env, obj, android_app->activity->clazz, android_app->getIntent);
GET_METHOD_ID(env, android_app->hasPendingIntent, class, "hasPendingIntent", "()Z");
GET_METHOD_ID(env, android_app->clearPendingIntent, class, "clearPendingIntent", "()V");
GET_METHOD_ID(env, android_app->getPendingIntentConfigPath, class, "getPendingIntentConfigPath",
"()Ljava/lang/String;");
GET_METHOD_ID(env, android_app->getPendingIntentLibretroPath, class, "getPendingIntentLibretroPath",
"()Ljava/lang/String;");
GET_METHOD_ID(env, android_app->getPendingIntentFullPath, class, "getPendingIntentFullPath",
"()Ljava/lang/String;");
GET_METHOD_ID(env, android_app->getPendingIntentIME, class, "getPendingIntentIME",
"()Ljava/lang/String;");
GET_OBJECT_CLASS(env, class, obj);
GET_METHOD_ID(env, android_app->getStringExtra, class, "getStringExtra", "(Ljava/lang/String;)Ljava/lang/String;");

View File

@ -49,6 +49,12 @@ struct android_app
char current_ime[PATH_MAX];
jmethodID getIntent;
jmethodID getStringExtra;
jmethodID clearPendingIntent;
jmethodID hasPendingIntent;
jmethodID getPendingIntentConfigPath;
jmethodID getPendingIntentLibretroPath;
jmethodID getPendingIntentFullPath;
jmethodID getPendingIntentIME;
};
enum {