Добавил mpcore
This commit is contained in:
Generated
+1
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
|
||||
Generated
-1
@@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
||||
|
||||
@@ -51,5 +51,6 @@ dependencies {
|
||||
implementation("com.parse.bolts:bolts-tasks:1.4.0")
|
||||
implementation("org.apache.httpcomponents:httpclient-android:4.3.5.1")
|
||||
implementation("com.google.code.gson:gson:2.7")
|
||||
implementation(project(":mpcore"))
|
||||
//implementation("com.android.support:support-v4:28.0.0")
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
package com.ea.InAppWebBrowser;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Paint;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.RelativeLayout;
|
||||
import java.util.UUID;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
public class BrowserAndroid {
|
||||
public static int gInstanceCount;
|
||||
public static Activity mActivity;
|
||||
public static ViewGroup mViewGroup;
|
||||
public RelativeLayout mLayout;
|
||||
public WebView mWebView;
|
||||
public InAppWebBrowserWebViewClient mWebViewClient;
|
||||
public final int SCROLLBAR_VISIBLE = 0;
|
||||
public final int SCROLLBAR_INVISIBLE = 1;
|
||||
public final int JAVASCRIPT_DISABLE = 0;
|
||||
public final int JAVASCRIPT_ENABLE = 1;
|
||||
public final int SCROLLBARSTYLE_DEFAULT = 0;
|
||||
public final int SCROLLBARSTYLE_INSIDE_OVERLAY = 1;
|
||||
public final int SCROLLBARSTYLE_INSIDE_INSET = 2;
|
||||
public final int SCROLLBARSTYLE_OUTSIDE_OVERLAY = 3;
|
||||
public final int SCROLLBARSTYLE_OUTSIDE_INSET = 4;
|
||||
public int mInstanceID = 0;
|
||||
|
||||
private static native void ShutdownNativeImpl();
|
||||
|
||||
private static native void StartupNativeImpl();
|
||||
|
||||
public void BrowserAndroid() {
|
||||
}
|
||||
|
||||
public static void Startup(Activity activity, ViewGroup viewGroup) {
|
||||
mActivity = activity;
|
||||
mViewGroup = viewGroup;
|
||||
StartupNativeImpl();
|
||||
}
|
||||
|
||||
public static void Shutdown() {
|
||||
ShutdownNativeImpl();
|
||||
}
|
||||
|
||||
public void init(final int i, final int i2, final int i3, final int i4, final int i5, final int i6, final int i7, final boolean z, final boolean z2) {
|
||||
int i8 = gInstanceCount;
|
||||
gInstanceCount = i8 + 1;
|
||||
this.mInstanceID = i8;
|
||||
mActivity.runOnUiThread(new Runnable() { // from class: com.ea.InAppWebBrowser.BrowserAndroid.1
|
||||
@Override // java.lang.Runnable
|
||||
public void run() {
|
||||
BrowserAndroid.this.mLayout = new RelativeLayout(BrowserAndroid.mActivity);
|
||||
BrowserAndroid.this.mWebView = new WebView(BrowserAndroid.mActivity);
|
||||
BrowserAndroid.this.mWebViewClient = new InAppWebBrowserWebViewClient();
|
||||
BrowserAndroid.this.mWebViewClient.mInstanceID = BrowserAndroid.this.mInstanceID;
|
||||
BrowserAndroid.this.mWebView.setWebViewClient(BrowserAndroid.this.mWebViewClient);
|
||||
if (z2) {
|
||||
BrowserAndroid.this.mWebView.setBackgroundColor(0);
|
||||
Class<?> cls = BrowserAndroid.this.mWebView.getClass();
|
||||
try {
|
||||
cls.getMethod("setLayerType", Integer.TYPE, Paint.class).invoke(BrowserAndroid.this.mWebView, Integer.valueOf(((Integer) cls.getField("LAYER_TYPE_SOFTWARE").get(BrowserAndroid.this.mWebView)).intValue()), null);
|
||||
} catch (Exception unused) {
|
||||
}
|
||||
}
|
||||
if (!z) {
|
||||
Class<?> cls2 = BrowserAndroid.this.mWebView.getClass();
|
||||
try {
|
||||
cls2.getMethod("setOverScrollMode", Integer.TYPE).invoke(BrowserAndroid.this.mWebView, Integer.valueOf(((Integer) cls2.getField("OVER_SCROLL_NEVER").get(BrowserAndroid.this.mWebView)).intValue()));
|
||||
} catch (Exception unused2) {
|
||||
}
|
||||
}
|
||||
BrowserAndroid.this.mWebView.requestFocus(130);
|
||||
BrowserAndroid.this.mWebView.setOnTouchListener(new View.OnTouchListener() { // from class: com.ea.InAppWebBrowser.BrowserAndroid.1.1
|
||||
@Override // android.view.View.OnTouchListener
|
||||
public boolean onTouch(View view, MotionEvent motionEvent) {
|
||||
switch (motionEvent.getAction()) {
|
||||
case 0:
|
||||
case 1:
|
||||
if (!view.hasFocus()) {
|
||||
view.requestFocus();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (i5 == 1) {
|
||||
BrowserAndroid.this.mWebView.getSettings().setJavaScriptEnabled(true);
|
||||
}
|
||||
BrowserAndroid.this.mWebView.setVerticalScrollBarEnabled(i6 == 0);
|
||||
BrowserAndroid.this.mWebView.setHorizontalScrollBarEnabled(i6 == 0);
|
||||
BrowserAndroid.this.mWebView.addJavascriptInterface(new JavascriptInterface(BrowserAndroid.this.mWebViewClient), "JavascriptCallback");
|
||||
switch (i7) {
|
||||
case 1:
|
||||
BrowserAndroid.this.mWebView.setScrollBarStyle(0);
|
||||
break;
|
||||
case 2:
|
||||
BrowserAndroid.this.mWebView.setScrollBarStyle(16777216);
|
||||
break;
|
||||
case 3:
|
||||
BrowserAndroid.this.mWebView.setScrollBarStyle(33554432);
|
||||
break;
|
||||
case 4:
|
||||
BrowserAndroid.this.mWebView.setScrollBarStyle(50331648);
|
||||
break;
|
||||
}
|
||||
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(i3, i4);
|
||||
layoutParams.leftMargin = i;
|
||||
layoutParams.topMargin = i2;
|
||||
BrowserAndroid.this.mLayout.addView(BrowserAndroid.this.mWebView, layoutParams);
|
||||
BrowserAndroid.mViewGroup.addView(BrowserAndroid.this.mLayout);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void OpenUrl(final String str) {
|
||||
mActivity.runOnUiThread(new Runnable() { // from class: com.ea.InAppWebBrowser.BrowserAndroid.2
|
||||
@Override // java.lang.Runnable
|
||||
public void run() {
|
||||
BrowserAndroid.this.mWebView.loadUrl(str);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void LoadHTML(final String str) {
|
||||
mActivity.runOnUiThread(new Runnable() { // from class: com.ea.InAppWebBrowser.BrowserAndroid.3
|
||||
@Override // java.lang.Runnable
|
||||
public void run() {
|
||||
BrowserAndroid.this.mWebView.loadData(str, "text/html", null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void SetViewFrame(final int i, final int i2, final int i3, final int i4) {
|
||||
if (this.mWebView == null) {
|
||||
return;
|
||||
}
|
||||
mActivity.runOnUiThread(new Runnable() { // from class: com.ea.InAppWebBrowser.BrowserAndroid.4
|
||||
@Override // java.lang.Runnable
|
||||
public void run() {
|
||||
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(i3, i4);
|
||||
layoutParams.leftMargin = i;
|
||||
layoutParams.topMargin = i2;
|
||||
BrowserAndroid.this.mLayout.updateViewLayout(BrowserAndroid.this.mWebView, layoutParams);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void EvaluateJavaScript(final String str) {
|
||||
mActivity.runOnUiThread(new Runnable() { // from class: com.ea.InAppWebBrowser.BrowserAndroid.5
|
||||
@Override // java.lang.Runnable
|
||||
public void run() {
|
||||
UUID randomUUID;
|
||||
do {
|
||||
randomUUID = UUID.randomUUID();
|
||||
} while (!BrowserAndroid.this.mWebViewClient.addUUID(randomUUID));
|
||||
BrowserAndroid.this.mWebView.loadUrl("javascript: JavascriptCallback.ReceiveResult(eval(" + str + "), '" + randomUUID.toString() + "');");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
mActivity.runOnUiThread(new Runnable() { // from class: com.ea.InAppWebBrowser.BrowserAndroid.6
|
||||
@Override // java.lang.Runnable
|
||||
public void run() {
|
||||
BrowserAndroid.this.mWebView.stopLoading();
|
||||
BrowserAndroid.this.mWebView.setWebViewClient(null);
|
||||
BrowserAndroid.this.mWebViewClient = null;
|
||||
BrowserAndroid.this.mLayout.removeView(BrowserAndroid.this.mWebView);
|
||||
BrowserAndroid.mViewGroup.removeView(BrowserAndroid.this.mLayout);
|
||||
BrowserAndroid.this.mWebView = null;
|
||||
BrowserAndroid.this.mLayout = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package com.ea.InAppWebBrowser;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import java.util.Collections;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.UUID;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
public class InAppWebBrowserWebViewClient extends WebViewClient {
|
||||
public int mInstanceID = 0;
|
||||
private SortedSet<UUID> mJavascriptIds = Collections.synchronizedSortedSet(new TreeSet());
|
||||
|
||||
public native void OnJavascriptResult(String str, int i);
|
||||
|
||||
public native void OnLoadError(String str, int i);
|
||||
|
||||
public native void OnLoadFinished(String str, int i);
|
||||
|
||||
public native void OnLoadStarted(String str, int i);
|
||||
|
||||
public native boolean ShouldLoadURL(String str, int i);
|
||||
|
||||
@Override // android.webkit.WebViewClient
|
||||
public boolean shouldOverrideUrlLoading(WebView webView, String str) {
|
||||
Log.e("InAppWebBrowserWebViewClient", "shouldOverrideUrlLoading: " + str);
|
||||
return !ShouldLoadURL(str, this.mInstanceID);
|
||||
}
|
||||
|
||||
@Override // android.webkit.WebViewClient
|
||||
public void onLoadResource(WebView webView, String str) {
|
||||
Log.e("InAppWebBrowserWebViewClient", "onLoadResource: " + str);
|
||||
OnLoadStarted(str, this.mInstanceID);
|
||||
}
|
||||
|
||||
@Override // android.webkit.WebViewClient
|
||||
public void onPageStarted(WebView webView, String str, Bitmap bitmap) {
|
||||
Log.e("InAppWebBrowserWebViewClient", "onPageStarted: " + str);
|
||||
OnLoadStarted(str, this.mInstanceID);
|
||||
}
|
||||
|
||||
@Override // android.webkit.WebViewClient
|
||||
public void onPageFinished(WebView webView, String str) {
|
||||
Log.e("InAppWebBrowserWebViewClient", "onPageFinished: " + str);
|
||||
OnLoadFinished(str, this.mInstanceID);
|
||||
}
|
||||
|
||||
@Override // android.webkit.WebViewClient
|
||||
public void onReceivedError(WebView webView, int i, String str, String str2) {
|
||||
Log.e("InAppWebBrowserWebViewClient", "onReceivedError");
|
||||
OnLoadError("Loading Error. URL: " + str2 + " ErrorCode: " + i + " Description: " + str, this.mInstanceID);
|
||||
}
|
||||
|
||||
public void onJavascriptResult(String str, String str2) throws Exception {
|
||||
UUID fromString = UUID.fromString(str2);
|
||||
if (fromString != null && this.mJavascriptIds.contains(fromString)) {
|
||||
this.mJavascriptIds.remove(fromString);
|
||||
OnJavascriptResult(str, this.mInstanceID);
|
||||
return;
|
||||
}
|
||||
throw new Exception("Unable to verify validity of script result.");
|
||||
}
|
||||
|
||||
public boolean addUUID(UUID uuid) {
|
||||
if (this.mJavascriptIds.contains(uuid)) {
|
||||
return false;
|
||||
}
|
||||
this.mJavascriptIds.add(uuid);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.ea.InAppWebBrowser;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
public class JavascriptInterface {
|
||||
private InAppWebBrowserWebViewClient mWebViewClient;
|
||||
|
||||
public JavascriptInterface(InAppWebBrowserWebViewClient inAppWebBrowserWebViewClient) {
|
||||
this.mWebViewClient = inAppWebBrowserWebViewClient;
|
||||
}
|
||||
|
||||
public void ReceiveResult(String str, String str2) throws Exception {
|
||||
this.mWebViewClient.onJavascriptResult(str, str2);
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package com.ea.InputMan;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
public class InputMan {
|
||||
private boolean gbMotionEvent_GetSource;
|
||||
|
||||
private static int GetEventType(int i) {
|
||||
switch (i) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static native boolean InputMan_OnMotionEvent(int i, int i2, float f, float f2, int i3, float f3);
|
||||
|
||||
public InputMan() {
|
||||
this.gbMotionEvent_GetSource = false;
|
||||
try {
|
||||
MotionEvent.class.getMethod("getSource", new Class[0]);
|
||||
this.gbMotionEvent_GetSource = true;
|
||||
} catch (Exception unused) {
|
||||
}
|
||||
}
|
||||
|
||||
private int GetSource(MotionEvent motionEvent) {
|
||||
if (!this.gbMotionEvent_GetSource) {
|
||||
return 0;
|
||||
}
|
||||
int source = motionEvent.getSource();
|
||||
if ((source & 2) != 0) {
|
||||
return (source == 8194 || source != 1048584) ? 0 : 10;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public boolean onTouchEvent(int i, MotionEvent motionEvent) {
|
||||
int historySize = motionEvent.getHistorySize();
|
||||
int pointerCount = motionEvent.getPointerCount();
|
||||
int GetSource = GetSource(motionEvent);
|
||||
int GetEventType = GetEventType(motionEvent.getAction() & 255);
|
||||
if (GetSource < 0) {
|
||||
return false;
|
||||
}
|
||||
for (int i2 = 0; i2 < historySize; i2++) {
|
||||
for (int i3 = 0; i3 < pointerCount; i3++) {
|
||||
InputMan_OnMotionEvent(i, motionEvent.getPointerId(i3), motionEvent.getHistoricalX(i3, i2), motionEvent.getHistoricalY(i3, i2), GetEventType, motionEvent.getHistoricalPressure(i3, i2));
|
||||
}
|
||||
}
|
||||
boolean z = false;
|
||||
for (int i4 = 0; i4 < pointerCount; i4++) {
|
||||
z = InputMan_OnMotionEvent(i, motionEvent.getPointerId(i4), motionEvent.getX(i4), motionEvent.getY(i4), GetEventType, motionEvent.getPressure(i4));
|
||||
}
|
||||
return z;
|
||||
}
|
||||
}
|
||||
@@ -68,6 +68,8 @@ import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
import org.fmod.FMODAudioDevice;
|
||||
|
||||
import nfs.mod.mpcore.MultiplayerCore;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
public class GameActivityMain extends AppCompatActivity implements DrawFrameListener {
|
||||
private static final String DOWNLOAD_PROPERTIES = "downloadcontent/config.properties";
|
||||
@@ -310,6 +312,7 @@ public class GameActivityMain extends AppCompatActivity implements DrawFrameList
|
||||
System.loadLibrary("c++_shared");
|
||||
System.loadLibrary(Global.NIMBLE_ID);
|
||||
System.loadLibrary("app");
|
||||
MultiplayerCore.INSTANCE.loadCore();
|
||||
Log.d(TAG, "Init EAIO/EAMIO");
|
||||
EAIO.Startup(this);
|
||||
StorageDirectory.Startup(this);
|
||||
|
||||
@@ -1,112 +1,167 @@
|
||||
package com.ea.ironmonkey;
|
||||
|
||||
import static android.os.Build.VERSION_CODES.R;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import android.os.Build;
|
||||
import android.widget.Toast;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
|
||||
/* loaded from: classes.dex */
|
||||
public class PermissionsActivity extends Activity {
|
||||
private static final int PERMISSIONS_REQUEST = 3;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
protected void onCreate() {
|
||||
public class PermissionsActivity extends AppCompatActivity {
|
||||
private static final int SETTINGS_REQUEST_CODE = 100;
|
||||
private final ActivityResultLauncher<String[]> requestPermissionLauncher =
|
||||
registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), result -> {
|
||||
if (areAllPermissionsGranted()) {
|
||||
initActivity();
|
||||
} else {
|
||||
handlePermissionsDenied();
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
checkPermissions();
|
||||
}
|
||||
|
||||
public void checkPermissions() {
|
||||
if (ContextCompat.checkSelfPermission(this, "android.permission.WRITE_EXTERNAL_STORAGE") != 0) {
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(this, "android.permission.WRITE_EXTERNAL_STORAGE")) {
|
||||
showPermissionDialog(false);
|
||||
} else {
|
||||
requestSecurityPermissions();
|
||||
}
|
||||
return;
|
||||
}
|
||||
initActivity();
|
||||
return;
|
||||
}
|
||||
|
||||
@Override // android.app.Activity
|
||||
public void onRequestPermissionsResult(int i, String[] strArr, int[] iArr) {
|
||||
if (i != 3) {
|
||||
return;
|
||||
}
|
||||
if (iArr.length == 1 && iArr[0] == 0) {
|
||||
private void checkPermissions() {
|
||||
if (areAllPermissionsGranted()) {
|
||||
initActivity();
|
||||
} else {
|
||||
showPermissionDialog(true);
|
||||
requestPermissions();
|
||||
}
|
||||
}
|
||||
|
||||
private void showPermissionDialog(final boolean z) {
|
||||
Context context = this;
|
||||
runOnUiThread(new Runnable() { // from class: com.ea.ironmonkey.PermissionsActivity.1
|
||||
@Override // java.lang.Runnable
|
||||
public void run() {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setMessage("DIALOG");
|
||||
builder.setPositiveButton("OK", (dialogInterface, i) -> {
|
||||
if (!z) {
|
||||
PermissionsActivity.this.requestSecurityPermissions();
|
||||
return;
|
||||
}
|
||||
Intent intent = new Intent("android.settings.APPLICATION_DETAILS_SETTINGS", Uri.parse("package:" + PermissionsActivity.this.getPackageName()));
|
||||
private boolean areAllPermissionsGranted() {
|
||||
for (String permission : getRequiredPermissions()) {
|
||||
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
PermissionsActivity.this.startActivityForResult(intent, 3);
|
||||
});
|
||||
private String[] getRequiredPermissions() {
|
||||
List<String> permissions = new ArrayList<>();
|
||||
|
||||
builder.setNegativeButton("DIALOG", (dialogInterface, i) -> PermissionsActivity.this.finish());
|
||||
AlertDialog create = builder.create();
|
||||
create.setCanceledOnTouchOutside(false);
|
||||
create.setOnKeyListener((dialogInterface, i, keyEvent) -> {
|
||||
if (i != 4) {
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
|
||||
// Android 9 (Pie) и ниже - нужны оба разрешения
|
||||
permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
|
||||
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
||||
} else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
|
||||
// Android 10 (Q) - только чтение
|
||||
permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
// Android 13+ - новые раздельные разрешения для медиа
|
||||
permissions.add(Manifest.permission.READ_MEDIA_IMAGES);
|
||||
permissions.add(Manifest.permission.READ_MEDIA_VIDEO);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
// Android 14+ - дополнительно для аудио
|
||||
permissions.add(Manifest.permission.READ_MEDIA_AUDIO);
|
||||
}
|
||||
} else {
|
||||
// Android 11-12 - только чтение
|
||||
permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
|
||||
}
|
||||
|
||||
return permissions.toArray(new String[0]);
|
||||
}
|
||||
|
||||
private void requestPermissions() {
|
||||
String[] permissions = getRequiredPermissions();
|
||||
boolean shouldShowRationale = false;
|
||||
|
||||
for (String permission : permissions) {
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
|
||||
shouldShowRationale = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldShowRationale) {
|
||||
showPermissionRationaleDialog();
|
||||
} else {
|
||||
requestPermissionLauncher.launch(permissions);
|
||||
}
|
||||
}
|
||||
|
||||
private void showPermissionRationaleDialog() {
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle("Требуются разрешения")
|
||||
.setMessage("Для корректной работы приложения необходимы разрешения на доступ к хранилищу. Пожалуйста, предоставьте запрашиваемые разрешения.")
|
||||
.setPositiveButton("OK", (dialog, which) -> requestPermissionLauncher.launch(getRequiredPermissions()))
|
||||
.setNegativeButton("Отмена", (dialog, which) -> finish())
|
||||
.setCancelable(false)
|
||||
.setOnKeyListener((dialog, keyCode, event) -> {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
PermissionsActivity.this.finish();
|
||||
dialogInterface.dismiss();
|
||||
return true;
|
||||
});
|
||||
create.show();
|
||||
}
|
||||
});
|
||||
return false;
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
public void requestSecurityPermissions() {
|
||||
ActivityCompat.requestPermissions(this, new String[]{"android.permission.WRITE_EXTERNAL_STORAGE"}, 3);
|
||||
ActivityCompat.requestPermissions(this, new String[]{"android.permission.READ_EXTERNAL_STORAGE"}, 3);
|
||||
private void handlePermissionsDenied() {
|
||||
if (areSomePermissionsPermanentlyDenied()) {
|
||||
showPermanentlyDeniedDialog();
|
||||
} else {
|
||||
Toast.makeText(this, "Разрешения необходимы для работы приложения", Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override // android.app.Activity
|
||||
public void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
onCreate();
|
||||
private boolean areSomePermissionsPermanentlyDenied() {
|
||||
for (String permission : getRequiredPermissions()) {
|
||||
if (!ActivityCompat.shouldShowRequestPermissionRationale(this, permission) &&
|
||||
ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override // android.app.Activity
|
||||
public void onActivityResult(int i, int i2, Intent intent) {
|
||||
super.onActivityResult(i, i2, intent);
|
||||
if (i == 3) {
|
||||
if (ContextCompat.checkSelfPermission(this, "android.permission.WRITE_EXTERNAL_STORAGE") == 0
|
||||
&& ContextCompat.checkSelfPermission(this, "android.permission.READ_EXTERNAL_STORAGE") == 0
|
||||
) {
|
||||
private void showPermanentlyDeniedDialog() {
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle("Разрешения отклонены")
|
||||
.setMessage("Вы навсегда отклонили некоторые разрешения. Чтобы использовать приложение, предоставьте разрешения в настройках.")
|
||||
.setPositiveButton("Настройки", (dialog, which) -> openAppSettings())
|
||||
.setNegativeButton("Выход", (dialog, which) -> finish())
|
||||
.setCancelable(false)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void openAppSettings() {
|
||||
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||
intent.setData(Uri.parse("package:" + getPackageName()));
|
||||
startActivityForResult(intent, SETTINGS_REQUEST_CODE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (requestCode == SETTINGS_REQUEST_CODE) {
|
||||
if (areAllPermissionsGranted()) {
|
||||
initActivity();
|
||||
return;
|
||||
} else {
|
||||
showPermissionDialog(true);
|
||||
return;
|
||||
handlePermissionsDenied();
|
||||
}
|
||||
}
|
||||
initActivity();
|
||||
}
|
||||
|
||||
private void initActivity() {
|
||||
@@ -115,6 +170,8 @@ public class PermissionsActivity extends Activity {
|
||||
finish();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(this, "Ошибка запуска приложения", Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,15 +9,6 @@ public class NimbleApplicationConfiguration {
|
||||
private static final String LOG_TITLE = "AppConfig";
|
||||
|
||||
public static boolean configValueExists(String str) {
|
||||
Log.Helper.LOGPUBLICFUNCS(LOG_TITLE);
|
||||
try {
|
||||
Activity currentActivity = ApplicationEnvironment.getCurrentActivity();
|
||||
if (currentActivity != null) {
|
||||
return currentActivity.getPackageManager().getApplicationInfo(currentActivity.getPackageName(), 128).metaData.containsKey(str);
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException unused) {
|
||||
Log.Helper.LOGES(LOG_TITLE, "Config value of key '%s' cannot be retrieved.", str);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -28,14 +19,6 @@ public class NimbleApplicationConfiguration {
|
||||
|
||||
public static String getConfigValueAsString(String str, String str2) {
|
||||
Log.Helper.LOGPUBLICFUNCS(LOG_TITLE);
|
||||
try {
|
||||
Activity currentActivity = ApplicationEnvironment.getCurrentActivity();
|
||||
if (currentActivity != null) {
|
||||
return currentActivity.getPackageManager().getApplicationInfo(currentActivity.getPackageName(), 128).metaData.getString(str);
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException unused) {
|
||||
Log.Helper.LOGES(LOG_TITLE, "Config value of key '%s' cannot be retrieved.", str);
|
||||
}
|
||||
return str2;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,45 +25,7 @@ public class NimbleLocalNotificationsImpl extends Component implements INimbleLo
|
||||
|
||||
@Override // com.ea.nimble.Component
|
||||
public void restore() {
|
||||
Log.Helper.LOGPUBLICFUNC(this);
|
||||
Persistence persistenceForNimbleComponent = PersistenceService.getPersistenceForNimbleComponent(getComponentId(), Persistence.Storage.CACHE);
|
||||
if (persistenceForNimbleComponent.hasKey(PERSISTENCE_ENABLED_KEY)) {
|
||||
this.m_enabled = persistenceForNimbleComponent.getBoolValue(PERSISTENCE_ENABLED_KEY);
|
||||
} else {
|
||||
this.m_enabled = true;
|
||||
}
|
||||
if (persistenceForNimbleComponent.hasKey(PERSISTENCE_NOTIFICATION_MAP_KEY)) {
|
||||
this.m_notificationMap = (HashMap) persistenceForNimbleComponent.getValue(PERSISTENCE_NOTIFICATION_MAP_KEY);
|
||||
Iterator<String> it = this.m_notificationMap.keySet().iterator();
|
||||
Date date = new Date();
|
||||
while (it.hasNext()) {
|
||||
String next = it.next();
|
||||
Date date2 = this.m_notificationMap.get(next);
|
||||
if (date2.before(date)) {
|
||||
Log.Helper.LOGV(this, "restore(): Removed notification list key " + next + " from map because its date (" + date2.toString() + ") is in the past!", new Object[0]);
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
saveNotificationMap();
|
||||
} else {
|
||||
this.m_notificationMap = new HashMap<>();
|
||||
}
|
||||
Context applicationContext = ApplicationEnvironment.getComponent().getApplicationContext();
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
NotificationManager notificationManager = (NotificationManager) applicationContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
if (NimbleApplicationConfiguration.configValueExists(Global.NOTIFICATION_CHANNEL_LOCAL_NOTIFICATION_ID_KEY)) {
|
||||
return;
|
||||
}
|
||||
String str = Global.NOTIFICATION_CHANNEL_DEFAULT_NAME_VALUE;
|
||||
if (NimbleApplicationConfiguration.configValueExists(Global.NOTIFICATION_CHANNEL_DEFAULT_NAME_KEY)) {
|
||||
str = applicationContext.getResources().getString(NimbleApplicationConfiguration.getConfigValueAsInt(Global.NOTIFICATION_CHANNEL_DEFAULT_NAME_KEY));
|
||||
}
|
||||
NotificationChannel notificationChannel = new NotificationChannel(Global.NOTIFICATION_CHANNEL_DEFAULT_ID, str, NotificationManager.IMPORTANCE_DEFAULT);
|
||||
if (NimbleApplicationConfiguration.configValueExists(Global.NOTIFICATION_CHANNEL_DEFAULT_DESCRIPTION_KEY)) {
|
||||
notificationChannel.setDescription(applicationContext.getResources().getString(NimbleApplicationConfiguration.getConfigValueAsInt(Global.NOTIFICATION_CHANNEL_DEFAULT_DESCRIPTION_KEY)));
|
||||
}
|
||||
notificationManager.createNotificationChannel(notificationChannel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override // com.ea.nimble.INimbleLocalNotifications
|
||||
|
||||
Binary file not shown.
@@ -2,4 +2,5 @@
|
||||
plugins {
|
||||
alias(libs.plugins.android.application) apply false
|
||||
alias(libs.plugins.kotlin.android) apply false
|
||||
alias(libs.plugins.android.library) apply false
|
||||
}
|
||||
@@ -18,5 +18,6 @@ material = { group = "com.google.android.material", name = "material", version.r
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
android-library = { id = "com.android.library", version.ref = "agp" }
|
||||
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
/build
|
||||
@@ -0,0 +1,54 @@
|
||||
plugins {
|
||||
alias(libs.plugins.android.library)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "nfs.mod.mpcore"
|
||||
compileSdk = 35
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 27
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles("consumer-rules.pro")
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
cppFlags("-std=c++17")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path("src/main/cpp/CMakeLists.txt")
|
||||
version = "3.22.1"
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation(libs.androidx.core.ktx)
|
||||
implementation(libs.androidx.appcompat)
|
||||
implementation(libs.material)
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
androidTestImplementation(libs.androidx.espresso.core)
|
||||
}
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,24 @@
|
||||
package nfs.mod.mpcore
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("nfs.mod.mpcore.test", appContext.packageName)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,12 @@
|
||||
cmake_minimum_required(VERSION 3.22.1)
|
||||
|
||||
project("mpcore")
|
||||
|
||||
add_library(${CMAKE_PROJECT_NAME} SHARED
|
||||
main.cpp
|
||||
util/util.cpp
|
||||
util/armhook.cpp)
|
||||
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME}
|
||||
android
|
||||
log)
|
||||
@@ -0,0 +1,7 @@
|
||||
package nfs.mod.mpcore
|
||||
|
||||
object MultiplayerCore {
|
||||
|
||||
fun loadCore() = System.loadLibrary("mpcore")
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package nfs.mod.mpcore
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
class ExampleUnitTest {
|
||||
@Test
|
||||
fun addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -21,4 +21,4 @@ dependencyResolutionManagement {
|
||||
|
||||
rootProject.name = "NFS Most Wanted"
|
||||
include(":app")
|
||||
|
||||
include(":mpcore")
|
||||
|
||||
Reference in New Issue
Block a user