forked from Mirrorlandia_minetest/minetest
Android: Segmentation fault fix, PendingIntent flag, and other fixes (#12960)
* Android: Segmentation fault fix, PendingIntent flag, and other fixes - Information about the crosshair is sent after camera initialization. - Since API 31, PendingIntent requires mutability flag. - super (class) is called in onRequestPermissionsResult(). - GameActivity suppresses "unused" warning since most of its methods are called from native code. - Non-null safety is added for nullable function calls. - Warning/error logging is added for various function calls' return value. * Move utility functions into Utils.java - Some nullable functions are changed to be non-null functions. - Some null checking outside it is removed. - More annotations are added to functions and parameters.
This commit is contained in:
parent
055fc69c11
commit
281f9a9f88
@ -45,6 +45,7 @@ import java.util.Objects;
|
|||||||
// Native code finds these methods by name (see porting_android.cpp).
|
// Native code finds these methods by name (see porting_android.cpp).
|
||||||
// This annotation prevents the minifier/Proguard from mangling them.
|
// This annotation prevents the minifier/Proguard from mangling them.
|
||||||
@Keep
|
@Keep
|
||||||
|
@SuppressWarnings("unused")
|
||||||
public class GameActivity extends NativeActivity {
|
public class GameActivity extends NativeActivity {
|
||||||
static {
|
static {
|
||||||
System.loadLibrary("c++_shared");
|
System.loadLibrary("c++_shared");
|
||||||
|
@ -127,8 +127,12 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRequestPermissionsResult(int requestCode,
|
public void onRequestPermissionsResult(
|
||||||
@NonNull String[] permissions, @NonNull int[] grantResults) {
|
int requestCode,
|
||||||
|
@NonNull String[] permissions,
|
||||||
|
@NonNull int[] grantResults
|
||||||
|
) {
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||||
if (requestCode == PERMISSIONS) {
|
if (requestCode == PERMISSIONS) {
|
||||||
for (int grantResult : grantResults) {
|
for (int grantResult : grantResults) {
|
||||||
if (grantResult != PackageManager.PERMISSION_GRANTED) {
|
if (grantResult != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
@ -29,10 +29,10 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -77,9 +77,6 @@ public class UnzipService extends IntentService {
|
|||||||
try {
|
try {
|
||||||
setIsRunning(true);
|
setIsRunning(true);
|
||||||
File userDataDirectory = Utils.getUserDataDirectory(this);
|
File userDataDirectory = Utils.getUserDataDirectory(this);
|
||||||
if (userDataDirectory == null) {
|
|
||||||
throw new IOException("Unable to find user data directory");
|
|
||||||
}
|
|
||||||
|
|
||||||
try (InputStream in = this.getAssets().open(zipFile.getName())) {
|
try (InputStream in = this.getAssets().open(zipFile.getName())) {
|
||||||
try (OutputStream out = new FileOutputStream(zipFile)) {
|
try (OutputStream out = new FileOutputStream(zipFile)) {
|
||||||
@ -98,7 +95,9 @@ public class UnzipService extends IntentService {
|
|||||||
failureMessage = e.getLocalizedMessage();
|
failureMessage = e.getLocalizedMessage();
|
||||||
} finally {
|
} finally {
|
||||||
setIsRunning(false);
|
setIsRunning(false);
|
||||||
zipFile.delete();
|
if (!zipFile.delete()) {
|
||||||
|
Log.w("UnzipService", "Minetest installation ZIP cannot be deleted");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,8 +130,12 @@ public class UnzipService extends IntentService {
|
|||||||
Intent notificationIntent = new Intent(this, MainActivity.class);
|
Intent notificationIntent = new Intent(this, MainActivity.class);
|
||||||
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
|
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||||
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||||
|
int pendingIntentFlag = 0;
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
|
pendingIntentFlag = PendingIntent.FLAG_MUTABLE;
|
||||||
|
}
|
||||||
PendingIntent intent = PendingIntent.getActivity(this, 0,
|
PendingIntent intent = PendingIntent.getActivity(this, 0,
|
||||||
notificationIntent, 0);
|
notificationIntent, pendingIntentFlag);
|
||||||
|
|
||||||
builder.setContentTitle(getString(R.string.notification_title))
|
builder.setContentTitle(getString(R.string.notification_title))
|
||||||
.setSmallIcon(R.mipmap.ic_launcher)
|
.setSmallIcon(R.mipmap.ic_launcher)
|
||||||
@ -210,7 +213,9 @@ public class UnzipService extends IntentService {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
publishProgress(notificationBuilder, R.string.migrating, 0);
|
publishProgress(notificationBuilder, R.string.migrating, 0);
|
||||||
newLocation.mkdir();
|
if (!newLocation.mkdir()) {
|
||||||
|
Log.e("UnzipService", "New installation folder cannot be made");
|
||||||
|
}
|
||||||
|
|
||||||
String[] dirs = new String[] { "worlds", "games", "mods", "textures", "client" };
|
String[] dirs = new String[] { "worlds", "games", "mods", "textures", "client" };
|
||||||
for (int i = 0; i < dirs.length; i++) {
|
for (int i = 0; i < dirs.length; i++) {
|
||||||
@ -228,7 +233,9 @@ public class UnzipService extends IntentService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
recursivelyDeleteDirectory(oldLocation);
|
if (!recursivelyDeleteDirectory(oldLocation)) {
|
||||||
|
Log.w("UnzipService", "Old installation files cannot be deleted successfully");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void publishProgress(@Nullable Notification.Builder notificationBuilder, @StringRes int message, int progress) {
|
private void publishProgress(@Nullable Notification.Builder notificationBuilder, @StringRes int message, int progress) {
|
||||||
|
@ -1,36 +1,43 @@
|
|||||||
package net.minetest.minetest;
|
package net.minetest.minetest;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class Utils {
|
public class Utils {
|
||||||
public static @NonNull File createDirs(File root, String dir) {
|
@NonNull
|
||||||
|
public static File createDirs(@NonNull File root, @NonNull String dir) {
|
||||||
File f = new File(root, dir);
|
File f = new File(root, dir);
|
||||||
if (!f.isDirectory())
|
if (!f.isDirectory())
|
||||||
f.mkdirs();
|
if (!f.mkdirs())
|
||||||
|
Log.e("Utils", "Directory " + dir + " cannot be created");
|
||||||
|
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @Nullable File getUserDataDirectory(Context context) {
|
@NonNull
|
||||||
File extDir = context.getExternalFilesDir(null);
|
public static File getUserDataDirectory(@NonNull Context context) {
|
||||||
if (extDir == null) {
|
File extDir = Objects.requireNonNull(
|
||||||
return null;
|
context.getExternalFilesDir(null),
|
||||||
}
|
"Cannot get external file directory"
|
||||||
|
);
|
||||||
return createDirs(extDir, "Minetest");
|
return createDirs(extDir, "Minetest");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @Nullable File getCacheDirectory(Context context) {
|
@NonNull
|
||||||
return context.getCacheDir();
|
public static File getCacheDirectory(@NonNull Context context) {
|
||||||
|
return Objects.requireNonNull(
|
||||||
|
context.getCacheDir(),
|
||||||
|
"Cannot get cache directory"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isInstallValid(Context context) {
|
public static boolean isInstallValid(@NonNull Context context) {
|
||||||
File userDataDirectory = getUserDataDirectory(context);
|
File userDataDirectory = getUserDataDirectory(context);
|
||||||
return userDataDirectory != null && userDataDirectory.isDirectory() &&
|
return userDataDirectory.isDirectory() &&
|
||||||
new File(userDataDirectory, "games").isDirectory() &&
|
new File(userDataDirectory, "games").isDirectory() &&
|
||||||
new File(userDataDirectory, "builtin").isDirectory() &&
|
new File(userDataDirectory, "builtin").isDirectory() &&
|
||||||
new File(userDataDirectory, "client").isDirectory() &&
|
new File(userDataDirectory, "client").isDirectory() &&
|
||||||
|
@ -1421,7 +1421,6 @@ bool Game::createClient(const GameStartData &start_data)
|
|||||||
if (g_touchscreengui) {
|
if (g_touchscreengui) {
|
||||||
g_touchscreengui->init(texture_src);
|
g_touchscreengui->init(texture_src);
|
||||||
g_touchscreengui->hide();
|
g_touchscreengui->hide();
|
||||||
g_touchscreengui->setUseCrosshair(!isNoCrosshairAllowed());
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!connectToServer(start_data, &could_connect, &connect_aborted))
|
if (!connectToServer(start_data, &could_connect, &connect_aborted))
|
||||||
@ -1458,6 +1457,11 @@ bool Game::createClient(const GameStartData &start_data)
|
|||||||
if (client->modsLoaded())
|
if (client->modsLoaded())
|
||||||
client->getScript()->on_camera_ready(camera);
|
client->getScript()->on_camera_ready(camera);
|
||||||
client->setCamera(camera);
|
client->setCamera(camera);
|
||||||
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
if (g_touchscreengui) {
|
||||||
|
g_touchscreengui->setUseCrosshair(!isNoCrosshairAllowed());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Clouds
|
/* Clouds
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user