[WIP] Mojang auth
This commit is contained in:
1 parent
c2e4e993ab
commit
aef99100ef
15 files changed
+178
-129
No files matched your search
@@ -15,7 +15,6 @@ public class PLaunchApp {
|
||||
private static float currProgress, maxProgress;
|
||||
|
||||
public static JMinecraftVersionList mVersionList;
|
||||
public static volatile MinecraftAccount mAccount;
|
||||
public static volatile JMinecraftVersionList.Version mVersion;
|
||||
public static boolean mIsAssetsProcessing = false;
|
||||
|
||||
@@ -24,8 +23,7 @@ public class PLaunchApp {
|
||||
try {
|
||||
File mcDir = new File("/var/mobile/Documents/minecraft");
|
||||
mcDir.mkdirs();
|
||||
File pojavDir = new File("/var/mobile/Documents/.pojavlauncher/accounts");
|
||||
pojavDir.mkdirs();
|
||||
new File(DIR_ACCOUNT_NEW).mkdirs();
|
||||
if (!new File(mcDir, "config_ver.txt").exists()) {
|
||||
Tools.write(mcDir.getAbsolutePath() + "/config_ver.txt", "1.16.5");
|
||||
}
|
||||
@@ -51,9 +49,9 @@ public class PLaunchApp {
|
||||
|
||||
System.out.println("Launching Minecraft " + mVersion.id);
|
||||
try {
|
||||
Tools.launchMinecraft(mAccount, mVersion);
|
||||
Tools.launchMinecraft(AccountJNI.CURRENT_ACCOUNT, mVersion);
|
||||
} catch (Throwable th) {
|
||||
throw new RuntimeException(th);
|
||||
Tools.showError(th);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,10 +76,6 @@ public class PLaunchApp {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {}
|
||||
|
||||
// dummy account
|
||||
MinecraftAccount acc = new MinecraftAccount();
|
||||
acc.selectedVersion = mcver;
|
||||
|
||||
new File(Tools.DIR_HOME_VERSION + "/" + mcver).mkdirs();
|
||||
|
||||
JMinecraftVersionList.Version verInfo = null;
|
||||
@@ -175,8 +169,6 @@ public class PLaunchApp {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
mAccount = acc;
|
||||
|
||||
UIKit.launchMinecraftSurface(mVersion.arguments != null);
|
||||
|
||||
}).start();
|
||||
|
||||
+36
-35
@@ -9,28 +9,36 @@ import net.kdt.pojavlaunch.value.MinecraftAccount;
|
||||
|
||||
public class PojavProfile
|
||||
{
|
||||
private static String PROFILE_PREF = "pojav_profile";
|
||||
private static String PROFILE_PREF_FILE = "file";
|
||||
private static String PROFILE_PREF_TEMP_CONTENT = "tempContent";
|
||||
|
||||
private static SharedPreferences getPrefs(Context ctx) {
|
||||
return ctx.getSharedPreferences(PROFILE_PREF, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
public static MinecraftAccount getCurrentProfileContent(Context ctx) throws IOException, JsonSyntaxException {
|
||||
MinecraftAccount build = MinecraftAccount.load(getCurrentProfileName(ctx));
|
||||
if (build == null) {
|
||||
return getTempProfileContent(ctx);
|
||||
private static final File currAccFile;
|
||||
static {
|
||||
try {
|
||||
File currAccFile = new File(Tools.DIR_APP_DATA, "curr_account.txt");
|
||||
currAccFile.getParentFile().mkdir();
|
||||
// currAccFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return build;
|
||||
}
|
||||
}
|
||||
|
||||
public static MinecraftAccount getCurrentProfileContent() throws IOException, JsonSyntaxException {
|
||||
MinecraftAccount build = MinecraftAccount.load(getCurrentProfileName());
|
||||
if (build == null) {
|
||||
return getTempProfileContent();
|
||||
}
|
||||
return MinecraftAccount.load(getCurrentProfileName());
|
||||
}
|
||||
/*
|
||||
public static MinecraftAccount getTempProfileContent(Context ctx) {
|
||||
return MinecraftAccount.parse(getPrefs(ctx).getString(PROFILE_PREF_TEMP_CONTENT, ""));
|
||||
}
|
||||
|
||||
public static String getCurrentProfileName(Context ctx) {
|
||||
String name = getPrefs(ctx).getString(PROFILE_PREF_FILE, "");
|
||||
*/
|
||||
public static String getCurrentProfileName() {
|
||||
String name = "";
|
||||
try {
|
||||
name = Tools.read(currAccFile.getAbsolutePath());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// A dirty fix
|
||||
if (!name.isEmpty() && name.startsWith(Tools.DIR_ACCOUNT_NEW) && name.endsWith(".json")) {
|
||||
name = name.substring(0, name.length() - 5).replace(Tools.DIR_ACCOUNT_NEW, "").replace(".json", "");
|
||||
@@ -39,43 +47,36 @@ public class PojavProfile
|
||||
return name;
|
||||
}
|
||||
|
||||
public static boolean setCurrentProfile(Context ctx, Object obj) {
|
||||
SharedPreferences.Editor pref = getPrefs(ctx).edit();
|
||||
|
||||
public static boolean setCurrentProfile(Object obj) {
|
||||
try {
|
||||
if (obj instanceof MinecraftAccount) {
|
||||
/*
|
||||
try {
|
||||
MinecraftAccount.saveTempAccount((MinecraftAccount) obj);
|
||||
} catch (IOException e) {
|
||||
Tools.showError(ctx, e);
|
||||
}
|
||||
*/
|
||||
throw new UnsupportedOperationException("Temp account is not supported yet");
|
||||
} else if (obj instanceof String) {
|
||||
String acc = (String) obj;
|
||||
pref.putString(PROFILE_PREF_FILE, acc);
|
||||
Tools.write(currAccFile.getAbsolutePath(), acc);
|
||||
MinecraftAccount.clearTempAccount();
|
||||
} else if (obj == null) {
|
||||
pref.putString(PROFILE_PREF_FILE, "");
|
||||
} else {
|
||||
throw new IllegalArgumentException("Profile must be MinecraftAccount.class, String.class or null");
|
||||
}
|
||||
} finally {
|
||||
return pref.commit();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isFileType(Context ctx) {
|
||||
return new File(Tools.DIR_ACCOUNT_NEW + "/" + PojavProfile.getCurrentProfileName(ctx) + ".json").exists();
|
||||
public static boolean isFileType() {
|
||||
return new File(Tools.DIR_ACCOUNT_NEW + "/" + getCurrentProfileName() + ".json").exists();
|
||||
}
|
||||
|
||||
|
||||
public static void launch(Activity ctx, Object o) {
|
||||
PojavProfile.setCurrentProfile(ctx, o);
|
||||
|
||||
Intent intent = new Intent(ctx, PojavV2ActivityManager.getLauncherRemakeVer(ctx)); //MCLauncherActivity.class);
|
||||
ctx.startActivity(intent);
|
||||
}
|
||||
|
||||
public static void updateTokens(final Activity ctx, final String name, RefreshListener listen) throws Exception {
|
||||
new RefreshTokenTask(ctx, listen).execute(Tools.DIR_ACCOUNT_NEW + "/" + name + ".json");
|
||||
public static void updateTokens(final String name, RefreshListener listen) throws Exception {
|
||||
new RefreshTokenTask(listen).run(name);
|
||||
}
|
||||
}
|
||||
@@ -31,12 +31,12 @@ public final class Tools
|
||||
public static String DIR_DATA = "/Applications/PojavLauncher.app";
|
||||
public static String CURRENT_ARCHITECTURE;
|
||||
|
||||
// New since 3.3.1
|
||||
public static String DIR_ACCOUNT_NEW;
|
||||
public static String DIR_ACCOUNT_OLD;
|
||||
public static final String DIR_GAME_HOME = "/var/mobile/Documents";
|
||||
public static final String DIR_GAME_NEW = DIR_GAME_HOME + "/minecraft";
|
||||
|
||||
public static final String DIR_APP_DATA = DIR_GAME_HOME + "/.pojavlauncher";
|
||||
public static final String DIR_ACCOUNT_NEW = DIR_APP_DATA + "/accounts";
|
||||
|
||||
// New since 3.0.0
|
||||
public static String DIR_HOME_JRE = "/usr/lib/jvm/java-16-openjdk";
|
||||
public static String DIRNAME_HOME_JRE = "lib";
|
||||
@@ -94,7 +94,7 @@ public final class Tools
|
||||
|
||||
System.out.println("It went past main(). Should not reach here!");
|
||||
} catch (Throwable th) {
|
||||
throw new RuntimeException(th);
|
||||
showError(th);
|
||||
}
|
||||
|
||||
}).start();
|
||||
@@ -406,6 +406,9 @@ public final class Tools
|
||||
pw.flush();
|
||||
|
||||
System.err.println(sw.toString());
|
||||
|
||||
UIKit.showError(title, sw.toString(), exitIfOk);
|
||||
|
||||
/*
|
||||
Platform.getPlatform().runOnUIThread(() -> {
|
||||
WindowAlertController alertController = new WindowAlertController(title, sw.toString(), UIAlertControllerStyle.Alert);
|
||||
|
||||
+6
-19
@@ -8,37 +8,24 @@ import java.util.*;
|
||||
import net.kdt.pojavlaunch.*;
|
||||
import net.kdt.pojavlaunch.value.*;
|
||||
|
||||
public class InvalidateTokenTask extends AsyncTask<String, Void, Throwable> {
|
||||
public class InvalidateTokenTask {
|
||||
private YggdrasilAuthenticator authenticator = new YggdrasilAuthenticator();
|
||||
//private Gson gson = new Gson();
|
||||
private MinecraftAccount profilePath;
|
||||
|
||||
private Context ctx;
|
||||
private String path;
|
||||
|
||||
public InvalidateTokenTask(Context ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
private String name;
|
||||
|
||||
@Override
|
||||
public Throwable doInBackground(String... args) {
|
||||
path = args[0];
|
||||
public Throwable run(String name) {
|
||||
this.name = name;
|
||||
try {
|
||||
this.profilePath = MinecraftAccount.load(args[0]);
|
||||
this.profilePath = MinecraftAccount.load(name);
|
||||
this.authenticator.invalidate(profilePath.accessToken,
|
||||
UUID.fromString(profilePath.isMicrosoft ? profilePath.profileId : profilePath.clientToken /* should be? */));
|
||||
new File(Tools.DIR_ACCOUNT_NEW, name + ".json").delete();
|
||||
return null;
|
||||
} catch (Throwable e) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostExecute(Throwable result) {
|
||||
if (result != null) {
|
||||
Tools.showError(ctx, result);
|
||||
}
|
||||
new File(path).delete();
|
||||
}
|
||||
}
|
||||
|
||||
+3
-15
@@ -6,17 +6,11 @@ import java.io.*;
|
||||
import java.util.*;
|
||||
import net.kdt.pojavlaunch.*;
|
||||
|
||||
public class LoginTask extends AsyncTask<String, Void, String[]>
|
||||
{
|
||||
public class LoginTask {
|
||||
private YggdrasilAuthenticator authenticator = new YggdrasilAuthenticator();
|
||||
//private String TAG = "MojangAuth-login";
|
||||
private LoginListener listener;
|
||||
|
||||
public LoginTask setLoginListener(LoginListener listener) {
|
||||
this.listener = listener;
|
||||
return this;
|
||||
}
|
||||
|
||||
private UUID getRandomUUID() {
|
||||
return UUID.randomUUID();
|
||||
}
|
||||
@@ -29,12 +23,12 @@ public class LoginTask extends AsyncTask<String, Void, String[]>
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] doInBackground(String[] args) {
|
||||
protected String[] run(String username, String password) {
|
||||
ArrayList<String> str = new ArrayList<String>();
|
||||
str.add("ERROR");
|
||||
try{
|
||||
try{
|
||||
AuthenticateResponse response = authenticator.authenticate(args[0], args[1], getRandomUUID());
|
||||
AuthenticateResponse response = authenticator.authenticate(username, password, getRandomUUID());
|
||||
if (response.selectedProfile == null) {
|
||||
str.add("Can't login a demo account!\n");
|
||||
} else {
|
||||
@@ -59,10 +53,4 @@ public class LoginTask extends AsyncTask<String, Void, String[]>
|
||||
}
|
||||
return str.toArray(new String[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String[] result) {
|
||||
listener.onLoginDone(result);
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
}
|
||||
+3
-35
@@ -1,41 +1,19 @@
|
||||
package net.kdt.pojavlaunch.authenticator.mojang;
|
||||
|
||||
import android.content.*;
|
||||
import android.os.*;
|
||||
import com.google.gson.*;
|
||||
import java.util.*;
|
||||
import net.kdt.pojavlaunch.*;
|
||||
import net.kdt.pojavlaunch.authenticator.mojang.yggdrasil.*;
|
||||
import android.app.*;
|
||||
import net.kdt.pojavlaunch.value.*;
|
||||
|
||||
public class RefreshTokenTask extends AsyncTask<String, Void, Throwable> {
|
||||
public class RefreshTokenTask {
|
||||
private YggdrasilAuthenticator authenticator = new YggdrasilAuthenticator();
|
||||
//private Gson gson = new Gson();
|
||||
private RefreshListener listener;
|
||||
private MinecraftAccount profilePath;
|
||||
|
||||
private Context ctx;
|
||||
private ProgressDialog build;
|
||||
|
||||
public RefreshTokenTask(Context ctx, RefreshListener listener) {
|
||||
this.ctx = ctx;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreExecute() {
|
||||
build = new ProgressDialog(ctx);
|
||||
build.setMessage(ctx.getString(R.string.global_waiting));
|
||||
build.setProgressStyle(ProgressDialog.STYLE_SPINNER);
|
||||
build.setCancelable(false);
|
||||
build.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Throwable doInBackground(String... args) {
|
||||
public Throwable run(String name) {
|
||||
try {
|
||||
this.profilePath = MinecraftAccount.load(args[0]);
|
||||
this.profilePath = MinecraftAccount.load(name);
|
||||
int responseCode = 400;
|
||||
responseCode = this.authenticator.validate(profilePath.accessToken).statusCode;
|
||||
if (responseCode >= 200 && responseCode < 300) {
|
||||
@@ -61,15 +39,5 @@ public class RefreshTokenTask extends AsyncTask<String, Void, Throwable> {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostExecute(Throwable result) {
|
||||
build.dismiss();
|
||||
if (result == null) {
|
||||
listener.onSuccess(null);
|
||||
} else {
|
||||
listener.onFailed(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package net.kdt.pojavlaunch.uikit;
|
||||
|
||||
import net.kdt.pojavlaunch.PojavProfile;
|
||||
import net.kdt.pojavlaunch.authenticator.mojang.*;
|
||||
import net.kdt.pojavlaunch.value.MinecraftAccount;
|
||||
|
||||
public class AccountJNI {
|
||||
public static final int TYPE_SELECTACC = 0;
|
||||
public static final int TYPE_MICROSOFT = 0;
|
||||
public static final int TYPE_MOJANG = 0;
|
||||
public static final int TYPE_OFFLINE = 0;
|
||||
|
||||
public static volatile MinecraftAccount CURRENT_ACCOUNT;
|
||||
|
||||
// Call back about account credentials for login
|
||||
public static boolean loginAccount(int type,
|
||||
String username, // Mojang or offline username
|
||||
String password, // Mojang password or Microsoft token
|
||||
) {
|
||||
try {
|
||||
switch (type) {
|
||||
case TYPE_SELECTACC:
|
||||
PojavProfile.updateTokens(username);
|
||||
CURRENT_ACCOUNT = MinecraftAccount.load(username);
|
||||
return true;
|
||||
|
||||
case TYPE_MICROSOFT:
|
||||
// TODO
|
||||
break;
|
||||
|
||||
case TYPE_MOJANG:
|
||||
String[] retArr = new LoginTask().run(username, password);
|
||||
if (!retArr[0].equals("NORMAL")) {
|
||||
StringBuilder full = new StringBuilder();
|
||||
for (int i = 1; i < retArr.length; i++) {
|
||||
full.append(retArr[i] + "\n");
|
||||
}
|
||||
UIKit.showError("Error", full.toString());
|
||||
return false;
|
||||
} else {
|
||||
CURRENT_ACCOUNT = new MinecraftAccount();
|
||||
CURRENT_ACCOUNT.accessToken = retArr[1];
|
||||
CURRENT_ACCOUNT.clientToken = retArr[2];
|
||||
CURRENT_ACCOUNT.profileId = retArr[3];
|
||||
CURRENT_ACCOUNT.username = retArr[4];
|
||||
CURRENT_ACCOUNT.save();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_OFFLINE:
|
||||
CURRENT_ACCOUNT = new MinecraftAccount();
|
||||
CURRENT_ACCOUNT.username = username;
|
||||
CURRENT_ACCOUNT.save();
|
||||
return true;
|
||||
}
|
||||
} catch (Throwable th) {
|
||||
Tools.showError(th);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static {
|
||||
// System.loadLibrary("pojavexec");
|
||||
}
|
||||
}
|
||||
@@ -76,6 +76,8 @@ public class UIKit {
|
||||
public static native int launchUI(String[] uiArgs);
|
||||
// public static native void runOnUIThread(UIKitCallback callback);
|
||||
|
||||
public static native void showError(String title, String message, boolean exitIfOk);
|
||||
|
||||
private static native void updateMCGuiScale(int scale);
|
||||
|
||||
// Update progress
|
||||
|
||||
@@ -13,7 +13,7 @@ set_target_properties(PojavLauncher PROPERTIES
|
||||
MACOSX_FRAMEWORK_IDENTIFIER org.cmake.ExecutableTarget
|
||||
MACOSX_BUNDLE_INFO_PLIST "../Info.plist")
|
||||
|
||||
add_library(pojavexec SHARED log.m AppDelegate.m SceneDelegate.m UILauncher.m LauncherViewController.m LoginViewController.m SurfaceViewController.m egl_bridge_ios.m ios_uikit_bridge.m login_bridge.m egl_bridge.c input_bridge_v3.c utils.c)
|
||||
add_library(pojavexec SHARED log.m AppDelegate.m SceneDelegate.m UILauncher.m LauncherViewController.m LoginViewController.m SurfaceViewController.m egl_bridge_ios.m ios_uikit_bridge.m egl_bridge.c input_bridge_v3.c utils.c)
|
||||
target_link_libraries(pojavexec
|
||||
"-Fresources/Frameworks"
|
||||
"-framework UIKit"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface LoginViewController : UIViewController
|
||||
|
||||
- (void)enterLauncher;
|
||||
@end
|
||||
|
||||
@interface LoginListViewController : UITableViewController
|
||||
|
||||
@@ -6,6 +6,21 @@
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
void loginAccount(LoginViewController *controller, int type, char* username_c, char* password_c) {
|
||||
JNIEnv *env;
|
||||
(*runtimeJavaVMPtr)->GetEnv(runtimeJavaVMPtr, (void**) &env, JNI_VERSION_1_4);
|
||||
|
||||
jstring username = (*env)->NewStringUTF(env, username_c);
|
||||
jstring password = (*env)->NewStringUTF(env, password_c);
|
||||
|
||||
jclass clazz = (*env)->FindClass(env, "net/kdt/pojavlaunch/uikit/AccountJNI");
|
||||
jmethodID method = (*env)->GetStaticMethodID(env, clazz, "loginAccount", "(ILjava/lang/String;Ljava/lang/String)Z");
|
||||
jboolean result = (*env)->CallStaticBooleanMethod(env, clazz, method, type, username, password);
|
||||
if (result == JNI_TRUE) {
|
||||
[controller enterLauncher];
|
||||
}
|
||||
}
|
||||
|
||||
@interface LoginViewController () {
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ set -e
|
||||
|
||||
CFLAGS="-fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -Wno-trigraphs -fpascal-strings -O3 -Wno-missing-field-initializers -Wno-missing-prototypes -Wno-return-type -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wno-unused-variable -Wunused-value -Wno-empty-body -Wno-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wno-constant-conversion -Wno-int-conversion -Wno-bool-conversion -Wno-enum-conversion -Wno-float-conversion -Wno-non-literal-null-conversion -Wno-objc-literal-conversion -Wshorten-64-to-32 -Wpointer-sign -Wno-newline-eof"
|
||||
|
||||
clang -Wl,-rpath,/Applications/PojavLauncher.app/Frameworks -fobjc-arc -x objective-c -Fresources/Frameworks -framework UIKit -framework MetalANGLE -framework CoreGraphics -Iresources/Frameworks/MetalANGLE.framework/Headers -dynamiclib -isysroot /var/mobile/theos/sdks/iPhoneOS13.4.sdk $CFLAGS -o libpojavexec.dylib log.m AppDelegate.m SceneDelegate.m UILauncher.m LauncherViewController.m LoginViewController.m SurfaceViewController.m egl_bridge_ios.m ios_uikit_bridge.m login_bridge.m egl_bridge.c input_bridge_v3.c utils.c -DGLES_TESTZ -DUSE_EGLZ
|
||||
clang -Wl,-rpath,/Applications/PojavLauncher.app/Frameworks -fobjc-arc -x objective-c -Fresources/Frameworks -framework UIKit -framework MetalANGLE -framework CoreGraphics -Iresources/Frameworks/MetalANGLE.framework/Headers -dynamiclib -isysroot /var/mobile/theos/sdks/iPhoneOS13.4.sdk $CFLAGS -o libpojavexec.dylib log.m AppDelegate.m SceneDelegate.m UILauncher.m LauncherViewController.m LoginViewController.m SurfaceViewController.m egl_bridge_ios.m ios_uikit_bridge.m egl_bridge.c input_bridge_v3.c utils.c -DGLES_TESTZ -DUSE_EGLZ
|
||||
|
||||
ldid -S../entitlements.xml libpojavexec.dylib
|
||||
|
||||
|
||||
@@ -10,6 +10,39 @@
|
||||
|
||||
jboolean skipDownloadAssets;
|
||||
|
||||
JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_uikit_UIKit_showError(JNIEnv* env_unused, jclass clazz, jstring title, jstring message, jboolean exitIfOk) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
JNIEnv *env;
|
||||
(*runtimeJavaVMPtr)->GetEnv(runtimeJavaVMPtr, (void**) &env, JNI_VERSION_1_4);
|
||||
const char* title_c = (*env)->GetStringUTFChars(env, title, 0);
|
||||
const char* message_c = (*env)->GetStringUTFChars(env, message, 0);
|
||||
|
||||
UIViewController *viewController = nil;
|
||||
if (@available(iOS 13.0, *)) {
|
||||
viewController = UIApplication.sharedApplication.windows.lastObject.rootViewController;
|
||||
} else {
|
||||
viewController = [[(AppDelegate*) [[UIApplication sharedApplication]delegate] window] rootViewController];
|
||||
}
|
||||
|
||||
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@(title_c)
|
||||
message:@(message_c)
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
if (exitIfOk == JNI_TRUE) {
|
||||
exit(-1);
|
||||
}
|
||||
}];
|
||||
|
||||
[alert addAction:defaultAction];
|
||||
[viewController presentViewController:alert animated:YES completion:nil];
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, title, title_c);
|
||||
(*env)->ReleaseStringUTFChars(env, message, message_c);
|
||||
});
|
||||
}
|
||||
|
||||
jboolean UIKit_updateProgress(float progress, const char* message) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
install_progress_bar.progress = progress;
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
#include "jni.h"
|
||||
#include "login_bridge.h"
|
||||
|
||||
|
||||
Reference in new issue
Block a user