Android: Fix some crashes reported via Play Store

This commit is contained in:
Connor McLaughlin 2020-11-03 16:15:04 +10:00
parent efc0a7391d
commit 5a93760af9
6 changed files with 84 additions and 10 deletions

View file

@ -35,6 +35,7 @@ void AndroidProgressCallback::SetCancellable(bool cancellable)
void AndroidProgressCallback::SetTitle(const char* title) void AndroidProgressCallback::SetTitle(const char* title)
{ {
Assert(title);
JNIEnv* env = AndroidHelpers::GetJNIEnv(); JNIEnv* env = AndroidHelpers::GetJNIEnv();
jstring text_jstr = env->NewStringUTF(title); jstring text_jstr = env->NewStringUTF(title);
env->CallVoidMethod(m_java_object, m_set_title_method, text_jstr); env->CallVoidMethod(m_java_object, m_set_title_method, text_jstr);
@ -42,6 +43,7 @@ void AndroidProgressCallback::SetTitle(const char* title)
void AndroidProgressCallback::SetStatusText(const char* text) void AndroidProgressCallback::SetStatusText(const char* text)
{ {
Assert(text);
JNIEnv* env = AndroidHelpers::GetJNIEnv(); JNIEnv* env = AndroidHelpers::GetJNIEnv();
jstring text_jstr = env->NewStringUTF(text); jstring text_jstr = env->NewStringUTF(text);
env->CallVoidMethod(m_java_object, m_set_status_text_method, text_jstr); env->CallVoidMethod(m_java_object, m_set_status_text_method, text_jstr);
@ -85,6 +87,7 @@ void AndroidProgressCallback::DisplayDebugMessage(const char* message)
void AndroidProgressCallback::ModalError(const char* message) void AndroidProgressCallback::ModalError(const char* message)
{ {
Assert(message);
JNIEnv* env = AndroidHelpers::GetJNIEnv(); JNIEnv* env = AndroidHelpers::GetJNIEnv();
jstring message_jstr = env->NewStringUTF(message); jstring message_jstr = env->NewStringUTF(message);
env->CallVoidMethod(m_java_object, m_modal_error_method, message_jstr); env->CallVoidMethod(m_java_object, m_modal_error_method, message_jstr);
@ -92,6 +95,7 @@ void AndroidProgressCallback::ModalError(const char* message)
bool AndroidProgressCallback::ModalConfirmation(const char* message) bool AndroidProgressCallback::ModalConfirmation(const char* message)
{ {
Assert(message);
JNIEnv* env = AndroidHelpers::GetJNIEnv(); JNIEnv* env = AndroidHelpers::GetJNIEnv();
jstring message_jstr = env->NewStringUTF(message); jstring message_jstr = env->NewStringUTF(message);
return env->CallBooleanMethod(m_java_object, m_modal_confirmation_method, message_jstr); return env->CallBooleanMethod(m_java_object, m_modal_confirmation_method, message_jstr);
@ -99,6 +103,7 @@ bool AndroidProgressCallback::ModalConfirmation(const char* message)
void AndroidProgressCallback::ModalInformation(const char* message) void AndroidProgressCallback::ModalInformation(const char* message)
{ {
Assert(message);
JNIEnv* env = AndroidHelpers::GetJNIEnv(); JNIEnv* env = AndroidHelpers::GetJNIEnv();
jstring message_jstr = env->NewStringUTF(message); jstring message_jstr = env->NewStringUTF(message);
env->CallVoidMethod(m_java_object, m_modal_information_method, message_jstr); env->CallVoidMethod(m_java_object, m_modal_information_method, message_jstr);

View file

@ -96,6 +96,13 @@ float AndroidSettingsInterface::GetFloatValue(const char* section, const char* k
jstring string_object = reinterpret_cast<jstring>( jstring string_object = reinterpret_cast<jstring>(
env->CallObjectMethod(m_java_shared_preferences, m_get_string, env->NewStringUTF(GetSettingKey(section, key)), env->CallObjectMethod(m_java_shared_preferences, m_get_string, env->NewStringUTF(GetSettingKey(section, key)),
env->NewStringUTF(TinyString::FromFormat("%f", default_value)))); env->NewStringUTF(TinyString::FromFormat("%f", default_value))));
if (env->ExceptionCheck())
{
env->ExceptionClear();
return default_value;
}
if (!string_object) if (!string_object)
return default_value; return default_value;
@ -111,8 +118,15 @@ float AndroidSettingsInterface::GetFloatValue(const char* section, const char* k
bool AndroidSettingsInterface::GetBoolValue(const char* section, const char* key, bool default_value /*= false*/) bool AndroidSettingsInterface::GetBoolValue(const char* section, const char* key, bool default_value /*= false*/)
{ {
JNIEnv* env = AndroidHelpers::GetJNIEnv(); JNIEnv* env = AndroidHelpers::GetJNIEnv();
return static_cast<bool>(env->CallBooleanMethod(m_java_shared_preferences, m_get_boolean, jboolean bool_value = static_cast<bool>(env->CallBooleanMethod(m_java_shared_preferences, m_get_boolean,
env->NewStringUTF(GetSettingKey(section, key)), default_value)); env->NewStringUTF(GetSettingKey(section, key)), default_value));
if (env->ExceptionCheck())
{
env->ExceptionClear();
return default_value;
}
return bool_value;
} }
std::string AndroidSettingsInterface::GetStringValue(const char* section, const char* key, std::string AndroidSettingsInterface::GetStringValue(const char* section, const char* key,
@ -122,6 +136,16 @@ std::string AndroidSettingsInterface::GetStringValue(const char* section, const
jobject string_object = jobject string_object =
env->CallObjectMethod(m_java_shared_preferences, m_get_string, env->NewStringUTF(GetSettingKey(section, key)), env->CallObjectMethod(m_java_shared_preferences, m_get_string, env->NewStringUTF(GetSettingKey(section, key)),
env->NewStringUTF(default_value)); env->NewStringUTF(default_value));
if (env->ExceptionCheck())
{
env->ExceptionClear();
return default_value;
}
if (!string_object)
return default_value;
return AndroidHelpers::JStringToString(env, reinterpret_cast<jstring>(string_object)); return AndroidHelpers::JStringToString(env, reinterpret_cast<jstring>(string_object));
} }
@ -155,10 +179,22 @@ std::vector<std::string> AndroidSettingsInterface::GetStringList(const char* sec
JNIEnv* env = AndroidHelpers::GetJNIEnv(); JNIEnv* env = AndroidHelpers::GetJNIEnv();
jobject values_set = env->CallObjectMethod(m_java_shared_preferences, m_get_string_set, jobject values_set = env->CallObjectMethod(m_java_shared_preferences, m_get_string_set,
env->NewStringUTF(GetSettingKey(section, key)), nullptr); env->NewStringUTF(GetSettingKey(section, key)), nullptr);
if (env->ExceptionCheck())
{
env->ExceptionClear();
return {};
}
if (!values_set) if (!values_set)
return {}; return {};
jobjectArray values_array = reinterpret_cast<jobjectArray>(env->CallObjectMethod(values_set, m_set_to_array)); jobjectArray values_array = reinterpret_cast<jobjectArray>(env->CallObjectMethod(values_set, m_set_to_array));
if (env->ExceptionCheck())
{
env->ExceptionClear();
return {};
}
if (!values_array) if (!values_array)
return {}; return {};

View file

@ -104,4 +104,8 @@ public class AndroidHostInterface {
static public AndroidHostInterface getInstance() { static public AndroidHostInterface getInstance() {
return mInstance; return mInstance;
} }
static public boolean hasInstanceAndEmulationThreadIsRunning() {
return hasInstance() && getInstance().isEmulationThreadRunning();
}
} }

View file

@ -116,6 +116,16 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
mApplySettingsOnSurfaceRestored = true; mApplySettingsOnSurfaceRestored = true;
} }
/// Ends the activity if it was restored without properly being created.
private boolean checkActivityIsValid() {
if (!AndroidHostInterface.hasInstance() || !AndroidHostInterface.getInstance().isEmulationThreadRunning()) {
finish();
return false;
}
return true;
}
@Override @Override
public void surfaceCreated(SurfaceHolder holder) { public void surfaceCreated(SurfaceHolder holder) {
} }
@ -227,7 +237,9 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
@Override @Override
public void onConfigurationChanged(@NonNull Configuration newConfig) { public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig); super.onConfigurationChanged(newConfig);
updateOrientation(newConfig.orientation);
if (checkActivityIsValid())
updateOrientation(newConfig.orientation);
} }
private void updateOrientation() { private void updateOrientation() {

View file

@ -42,6 +42,9 @@ public final class FileUtil {
@SuppressLint("ObsoleteSdkInt") @SuppressLint("ObsoleteSdkInt")
private static String getVolumePath(final String volumeId, Context context) { private static String getVolumePath(final String volumeId, Context context) {
if (volumeId == null)
return null;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return null; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return null;
try { try {
StorageManager mStorageManager = StorageManager mStorageManager =
@ -113,18 +116,26 @@ public final class FileUtil {
@TargetApi(Build.VERSION_CODES.LOLLIPOP) @TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static String getVolumeIdFromUri(final Uri treeUri) { private static String getVolumeIdFromUri(final Uri treeUri) {
final String docId = DocumentsContract.getDocumentId(treeUri); try {
final String[] split = docId.split(":"); final String docId = DocumentsContract.getDocumentId(treeUri);
if (split.length > 0) return split[0]; final String[] split = docId.split(":");
else return null; if (split.length > 0) return split[0];
else return null;
} catch (Exception e) {
return null;
}
} }
@TargetApi(Build.VERSION_CODES.LOLLIPOP) @TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static String getDocumentPathFromUri(final Uri treeUri) { private static String getDocumentPathFromUri(final Uri treeUri) {
final String docId = DocumentsContract.getDocumentId(treeUri); try {
final String[] split = docId.split(":"); final String docId = DocumentsContract.getDocumentId(treeUri);
if ((split.length >= 2) && (split[1] != null)) return split[1]; final String[] split = docId.split(":");
else return File.separator; if ((split.length >= 2) && (split[1] != null)) return split[1];
else return File.separator;
} catch (Exception e) {
return null;
}
} }
} }

View file

@ -143,6 +143,9 @@ public class TouchscreenControllerView extends FrameLayout {
private boolean handleTouchEvent(MotionEvent event) { private boolean handleTouchEvent(MotionEvent event) {
switch (event.getActionMasked()) { switch (event.getActionMasked()) {
case MotionEvent.ACTION_UP: { case MotionEvent.ACTION_UP: {
if (!AndroidHostInterface.hasInstanceAndEmulationThreadIsRunning())
return false;
for (TouchscreenControllerButtonView buttonView : mButtonViews) { for (TouchscreenControllerButtonView buttonView : mButtonViews) {
buttonView.setPressed(false); buttonView.setPressed(false);
} }
@ -158,6 +161,9 @@ public class TouchscreenControllerView extends FrameLayout {
case MotionEvent.ACTION_POINTER_DOWN: case MotionEvent.ACTION_POINTER_DOWN:
case MotionEvent.ACTION_POINTER_UP: case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_MOVE: { case MotionEvent.ACTION_MOVE: {
if (!AndroidHostInterface.hasInstanceAndEmulationThreadIsRunning())
return false;
Rect rect = new Rect(); Rect rect = new Rect();
final int pointerCount = event.getPointerCount(); final int pointerCount = event.getPointerCount();
final int liftedPointerIndex = (event.getActionMasked() == MotionEvent.ACTION_POINTER_UP) ? event.getActionIndex() : -1; final int liftedPointerIndex = (event.getActionMasked() == MotionEvent.ACTION_POINTER_UP) ? event.getActionIndex() : -1;