├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── io │ │ └── bambosan │ │ └── iseng │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ ├── launcher.dex │ │ ├── launcher_draco.dex │ │ └── launcher_mbl2.dex │ ├── java │ │ └── io │ │ │ └── bambosan │ │ │ └── mbloader │ │ │ ├── CrashActivity.java │ │ │ ├── Fallback.java │ │ │ ├── HomeFragment.java │ │ │ ├── IntentHandler.java │ │ │ ├── MBLoaderApp.java │ │ │ ├── MainActivity.java │ │ │ ├── SettingsFragment.java │ │ │ └── SplashActivity.java │ ├── jni │ │ ├── Android.mk │ │ ├── Application.mk │ │ └── mc-init.cpp │ ├── jniLibs │ │ ├── arm64-v8a │ │ │ ├── libdraco.so │ │ │ └── libmtbinloader2.so │ │ └── armeabi-v7a │ │ │ ├── libdraco.so │ │ │ └── libmtbinloader2.so │ └── res │ │ ├── anim │ │ ├── fade_in.xml │ │ ├── fade_out.xml │ │ ├── logo_pulse.xml │ │ ├── logo_rotate.xml │ │ ├── logo_zoom_in.xml │ │ ├── slide_in_left.xml │ │ ├── slide_in_right.xml │ │ ├── slide_out_left.xml │ │ ├── slide_out_right.xml │ │ ├── slide_up_fade_in.xml │ │ └── text_slide_up.xml │ │ ├── animator │ │ └── nav_item_animation.xml │ │ ├── color │ │ └── nav_item_color.xml │ │ ├── drawable │ │ ├── beta_label_background.xml │ │ ├── button_container_background.xml │ │ ├── ic_baseline_home_24.xml │ │ ├── ic_baseline_settings_24.xml │ │ ├── ic_launcher_foreground.xml │ │ ├── ic_launcher_monochrome.xml │ │ ├── nav_background.xml │ │ ├── rounded_background.xml │ │ ├── rounded_corner_background.xml │ │ └── splash_highlight.xml │ │ ├── layout │ │ ├── activity_crash.xml │ │ ├── activity_fallback.xml │ │ ├── activity_main.xml │ │ ├── activity_splash.xml │ │ ├── fragment_home.xml │ │ └── fragment_settings.xml │ │ ├── menu │ │ └── bottom_nav_menu.xml │ │ ├── mipmap-anydpi-v26 │ │ └── ic_launcher.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ │ └── xml │ │ ├── file_provider_paths.xml │ │ └── network_security_config.xml │ └── test │ └── java │ └── io │ └── bambosan │ └── mbloader │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle ├── libs.versions.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── minecraft ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── mojang │ └── minecraftpe │ ├── FilePickerManagerHandler.java │ ├── Launcher.java │ ├── MainActivity.java │ ├── NotificationListenerService.java │ └── store │ ├── ExtraLicenseResponseData.java │ ├── Product.java │ ├── Purchase.java │ ├── Store.java │ ├── StoreListener.java │ ├── amazonappstore │ └── AmazonAppStore.java │ └── googleplay │ └── GooglePlayStore.java ├── my-release-key.jks └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .idea 3 | .gradle 4 | /local.properties 5 | /.idea/caches 6 | /.idea/libraries 7 | /.idea/modules.xml 8 | /.idea/workspace.xml 9 | /.idea/navEditor.xml 10 | /.idea/assetWizardSettings.xml 11 | .DS_Store 12 | /build 13 | /captures 14 | .externalNativeBuild 15 | .cxx 16 | local.properties 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MB Loader (Unofficial) 2 | 3 | **Not distributed by us**, modified by The NoxPE Team. 4 | 5 | ORIGINAL APP: https://github.com/bambosan/MaterialBinLoader-Apk -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.android.application) 3 | alias(libs.plugins.kotlin.android) 4 | } 5 | 6 | android { 7 | namespace 'io.bambosan.mbloader' 8 | compileSdk 35 9 | buildToolsVersion = "35.0.0" 10 | defaultConfig { 11 | applicationId "io.bambosan.mbloader" 12 | minSdk 26 13 | targetSdk 35 14 | versionCode 17 15 | versionName "1.6" 16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 17 | ndk { 18 | abiFilters 'arm64-v8a', 'armeabi-v7a' 19 | } 20 | } 21 | 22 | signingConfigs { 23 | release { 24 | storeFile file("../my-release-key.jks") 25 | storePassword "lyssadev" 26 | keyAlias "my-alias" 27 | keyPassword "lyssadev" 28 | } 29 | } 30 | 31 | buildTypes { 32 | release { 33 | minifyEnabled false 34 | shrinkResources false 35 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 36 | signingConfig signingConfigs.release 37 | } 38 | } 39 | compileOptions { 40 | sourceCompatibility JavaVersion.VERSION_1_8 41 | targetCompatibility JavaVersion.VERSION_1_8 42 | } 43 | externalNativeBuild { 44 | ndkBuild { 45 | path "src/main/jni/Android.mk" 46 | } 47 | } 48 | ndkVersion "27.1.12297006" 49 | } 50 | 51 | dependencies { 52 | implementation libs.appcompat 53 | implementation libs.constraintlayout 54 | implementation 'com.google.android.material:material:1.12.0' 55 | implementation 'com.google.android.material:material:1.9.0' 56 | implementation 'androidx.fragment:fragment:1.6.0' 57 | implementation 'com.github.skydoves:colorpickerview:2.3.0' 58 | testImplementation libs.junit 59 | androidTestImplementation libs.ext.junit 60 | androidTestImplementation libs.espresso.core 61 | } 62 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/io/bambosan/iseng/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package io.bambosan.mbloader; 2 | 3 | import android.content.Context; 4 | import androidx.test.platform.app.InstrumentationRegistry; 5 | import androidx.test.ext.junit.runners.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 23 | assertEquals("io.bambosan.iseng", appContext.getPackageName()); 24 | } 25 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 40 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 54 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 103 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 141 | 143 | 145 | 146 | 147 | 158 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 196 | 198 | 200 | 201 | 202 | 208 | 209 | 211 | 214 | 216 | 218 | 219 | 220 | 226 | 232 | 237 | 240 | 241 | 242 | 243 | 244 | 248 | 249 | 250 | -------------------------------------------------------------------------------- /app/src/main/assets/launcher.dex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyssadev/mb-loader-unofficial/fe6a30125e6baefa396c8853cd4a6bdfab4942eb/app/src/main/assets/launcher.dex -------------------------------------------------------------------------------- /app/src/main/assets/launcher_draco.dex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyssadev/mb-loader-unofficial/fe6a30125e6baefa396c8853cd4a6bdfab4942eb/app/src/main/assets/launcher_draco.dex -------------------------------------------------------------------------------- /app/src/main/assets/launcher_mbl2.dex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyssadev/mb-loader-unofficial/fe6a30125e6baefa396c8853cd4a6bdfab4942eb/app/src/main/assets/launcher_mbl2.dex -------------------------------------------------------------------------------- /app/src/main/java/io/bambosan/mbloader/CrashActivity.java: -------------------------------------------------------------------------------- 1 | package io.bambosan.mbloader; 2 | 3 | import android.content.ClipData; 4 | import android.content.ClipboardManager; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.os.Bundle; 8 | import android.widget.Button; 9 | import android.widget.TextView; 10 | import android.widget.Toast; 11 | 12 | import androidx.appcompat.app.AppCompatActivity; 13 | 14 | public class CrashActivity extends AppCompatActivity { 15 | 16 | public static final String EXTRA_STACK_TRACE = "stack_trace"; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | setContentView(R.layout.activity_crash); 22 | 23 | // Get the stack trace from the intent 24 | String stackTraceStr = getIntent().getStringExtra(EXTRA_STACK_TRACE); 25 | if (stackTraceStr == null) { 26 | stackTraceStr = "No stack trace available"; 27 | } 28 | 29 | final String stackTrace = stackTraceStr; 30 | 31 | // Display the stack trace 32 | TextView stackTraceTextView = findViewById(R.id.crash_stack_trace); 33 | stackTraceTextView.setText(stackTrace); 34 | 35 | // Copy button functionality 36 | Button copyButton = findViewById(R.id.btn_copy); 37 | copyButton.setOnClickListener(v -> { 38 | ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE); 39 | ClipData clip = ClipData.newPlainText("Stack Trace", stackTrace); 40 | clipboard.setPrimaryClip(clip); 41 | Toast.makeText(this, "Stack trace copied to clipboard", Toast.LENGTH_SHORT).show(); 42 | }); 43 | 44 | // Restart button functionality 45 | Button restartButton = findViewById(R.id.btn_restart); 46 | restartButton.setOnClickListener(v -> { 47 | Intent intent = new Intent(this, SplashActivity.class); 48 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 49 | startActivity(intent); 50 | finish(); 51 | }); 52 | } 53 | } -------------------------------------------------------------------------------- /app/src/main/java/io/bambosan/mbloader/Fallback.java: -------------------------------------------------------------------------------- 1 | package io.bambosan.mbloader; 2 | 3 | import android.os.Bundle; 4 | 5 | import android.widget.TextView; 6 | import androidx.appcompat.app.AppCompatActivity; 7 | 8 | public class Fallback extends AppCompatActivity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_fallback); 14 | TextView logOut = findViewById(R.id.logOut); 15 | String log = getIntent().getStringExtra("LOG_STR"); 16 | logOut.setText(log); 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/io/bambosan/mbloader/HomeFragment.java: -------------------------------------------------------------------------------- 1 | package io.bambosan.mbloader; 2 | 3 | import android.os.Bundle; 4 | import android.os.Handler; 5 | import android.os.Looper; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.Button; 10 | import android.widget.ScrollView; 11 | import android.widget.TextView; 12 | 13 | import androidx.fragment.app.Fragment; 14 | 15 | public class HomeFragment extends Fragment { 16 | 17 | private TextView listener; 18 | private ScrollView logScrollView; 19 | private Handler handler; 20 | 21 | @Override 22 | public void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | } 25 | 26 | @Override 27 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 28 | View view = inflater.inflate(R.layout.fragment_home, container, false); 29 | 30 | listener = view.findViewById(R.id.listener); 31 | Button mbl2_button = view.findViewById(R.id.mbl2_load); 32 | Button draco_button = view.findViewById(R.id.draco_load); 33 | logScrollView = view.findViewById(R.id.log_scroll_view); 34 | handler = new Handler(Looper.getMainLooper()); 35 | 36 | mbl2_button.setOnClickListener(v -> { 37 | ((MainActivity) requireActivity()).startLauncher(handler, listener, logScrollView, "launcher_mbl2.dex", MainActivity.MC_PACKAGE_NAME); 38 | }); 39 | 40 | draco_button.setOnClickListener(v -> { 41 | ((MainActivity) requireActivity()).startLauncher(handler, listener, logScrollView, "launcher_draco.dex", MainActivity.MC_PACKAGE_NAME); 42 | }); 43 | 44 | return view; 45 | } 46 | } -------------------------------------------------------------------------------- /app/src/main/java/io/bambosan/mbloader/IntentHandler.java: -------------------------------------------------------------------------------- 1 | package io.bambosan.mbloader; 2 | 3 | 4 | import android.content.Intent; 5 | import android.app.Activity; 6 | import android.os.Bundle; 7 | 8 | public class IntentHandler extends Activity 9 | { 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) 12 | { 13 | super.onCreate(savedInstanceState); 14 | patiencepls(getIntent()); 15 | //setContentView(R.layout.main); 16 | 17 | } 18 | void patiencepls(Intent intention) { 19 | if (isMcLoaded()) { 20 | intention.setClassName(getApplicationContext(), "com.mojang.minecraftpe.Launcher"); 21 | } else { 22 | intention.setClassName(getApplicationContext(), "io.bambosan.mbloader.MainActivity"); 23 | } 24 | startActivity(intention); 25 | } 26 | Boolean isMcLoaded() { 27 | try { 28 | Class.forName("com.mojang.minecraftpe.Launcher", false, getClassLoader()); 29 | return true; 30 | } catch (Exception e) { 31 | return false; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/io/bambosan/mbloader/MBLoaderApp.java: -------------------------------------------------------------------------------- 1 | package io.bambosan.mbloader; 2 | 3 | import android.app.Application; 4 | import android.content.Intent; 5 | import android.os.Process; 6 | 7 | import java.io.PrintWriter; 8 | import java.io.StringWriter; 9 | 10 | public class MBLoaderApp extends Application { 11 | 12 | @Override 13 | public void onCreate() { 14 | super.onCreate(); 15 | 16 | // Set up the default uncaught exception handler 17 | Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> { 18 | StringWriter sw = new StringWriter(); 19 | PrintWriter pw = new PrintWriter(sw); 20 | throwable.printStackTrace(pw); 21 | String stackTraceString = sw.toString(); 22 | 23 | // Start the crash activity with the stack trace 24 | Intent intent = new Intent(MBLoaderApp.this, CrashActivity.class); 25 | intent.putExtra(CrashActivity.EXTRA_STACK_TRACE, stackTraceString); 26 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 27 | startActivity(intent); 28 | 29 | // Force close the app 30 | Process.killProcess(Process.myPid()); 31 | System.exit(1); 32 | }); 33 | } 34 | } -------------------------------------------------------------------------------- /app/src/main/java/io/bambosan/mbloader/MainActivity.java: -------------------------------------------------------------------------------- 1 | package io.bambosan.mbloader; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.app.ActivityManager; 5 | import android.app.AlertDialog; 6 | import android.content.DialogInterface; 7 | import android.content.Intent; 8 | import android.content.pm.ApplicationInfo; 9 | import android.content.pm.PackageManager; 10 | import android.net.Uri; 11 | import android.os.Build; 12 | import android.os.Bundle; 13 | import android.os.Handler; 14 | import android.os.Looper; 15 | import android.os.SystemClock; 16 | import android.util.Log; 17 | import android.view.Gravity; 18 | import android.view.View; 19 | import android.widget.ScrollView; 20 | import android.widget.TextView; 21 | import androidx.fragment.app.Fragment; 22 | import androidx.appcompat.app.AppCompatActivity; 23 | 24 | import com.google.android.material.bottomnavigation.BottomNavigationView; 25 | 26 | import org.jetbrains.annotations.NotNull; 27 | 28 | import java.io.BufferedInputStream; 29 | import java.io.BufferedOutputStream; 30 | import java.io.File; 31 | import java.io.FileInputStream; 32 | import java.io.FileOutputStream; 33 | import java.io.IOException; 34 | import java.io.InputStream; 35 | import java.io.OutputStream; 36 | import java.lang.reflect.Field; 37 | import java.lang.reflect.Method; 38 | import java.nio.file.Files; 39 | import java.util.ArrayList; 40 | import java.util.Collection; 41 | import java.util.Collections; 42 | import java.util.HashMap; 43 | import java.util.List; 44 | import java.util.Objects; 45 | import java.util.concurrent.Executors; 46 | import java.util.zip.ZipEntry; 47 | import java.util.zip.ZipFile; 48 | import java.util.zip.ZipInputStream; 49 | 50 | public class MainActivity extends AppCompatActivity { 51 | 52 | public static final String MC_PACKAGE_NAME = "com.mojang.minecraftpe"; 53 | 54 | @Override 55 | protected void onCreate(Bundle savedInstanceState) { 56 | super.onCreate(savedInstanceState); 57 | 58 | // Support for shared element transition from splash screen 59 | postponeEnterTransition(); 60 | 61 | // Add entry animation 62 | View rootView = findViewById(android.R.id.content); 63 | rootView.startAnimation(android.view.animation.AnimationUtils.loadAnimation(this, R.anim.slide_up_fade_in)); 64 | 65 | // Complete the postponed shared element transition 66 | startPostponedEnterTransition(); 67 | 68 | if (savedInstanceState == null) { 69 | // --- Apply custom window flags --- 70 | getWindow().setStatusBarColor(getColor(R.color.background)); 71 | getWindow().setNavigationBarColor(getColor(R.color.background)); 72 | 73 | // --- Set content view and attach navigation --- 74 | setContentView(R.layout.activity_main); 75 | setupNavigation(); 76 | 77 | // --- Set default fragment --- 78 | getSupportFragmentManager().beginTransaction() 79 | .replace(R.id.fragment_container, new HomeFragment()) 80 | .commit(); 81 | } 82 | } 83 | 84 | public void startLauncher(Handler handler, TextView listener, ScrollView logScrollView, String launcherDexName, String mcPackageName) { 85 | Executors.newSingleThreadExecutor().execute(() -> { 86 | try { 87 | File cacheDexDir = new File(getCodeCacheDir(), "dex"); 88 | handleCacheCleaning(cacheDexDir, handler, listener, logScrollView); 89 | ApplicationInfo mcInfo = null; 90 | try { 91 | mcInfo = getPackageManager().getApplicationInfo(mcPackageName, PackageManager.GET_META_DATA); 92 | } catch(Exception e) { 93 | handler.post(() -> alertAndExit("Minecraft not found", "Perhaps you don't have it installed?")); 94 | return; 95 | } 96 | Object pathList = getPathList(getClassLoader()); 97 | processDexFiles(mcInfo, cacheDexDir, pathList, handler, listener, logScrollView, launcherDexName); 98 | if (!processNativeLibraries(mcInfo, pathList, handler, listener, logScrollView)) { 99 | return; 100 | } 101 | launchMinecraft(mcInfo); 102 | } catch (Exception e) { 103 | String logMessage = e.getCause() != null ? e.getCause().toString() : e.toString(); 104 | handler.post(() -> { 105 | listener.setText("Launching failed: " + logMessage); 106 | logScrollView.post(() -> logScrollView.fullScroll(View.FOCUS_DOWN)); 107 | }); 108 | } 109 | }); 110 | } 111 | @SuppressLint("SetTextI18n") 112 | private void handleCacheCleaning(@NotNull File cacheDexDir, Handler handler, TextView listener, ScrollView logScrollView) { 113 | if (cacheDexDir.exists() && cacheDexDir.isDirectory()) { 114 | handler.post(() -> { 115 | listener.setText("-> " + cacheDexDir.getAbsolutePath() + " not empty, do cleaning"); 116 | logScrollView.post(() -> logScrollView.fullScroll(View.FOCUS_DOWN)); 117 | }); 118 | for (File file : Objects.requireNonNull(cacheDexDir.listFiles())) { 119 | if (file.delete()) { 120 | handler.post(() -> { 121 | listener.append("\n-> " + file.getName() + " deleted"); 122 | logScrollView.post(() -> logScrollView.fullScroll(View.FOCUS_DOWN)); 123 | }); 124 | } 125 | } 126 | } else { 127 | handler.post(() -> { 128 | listener.setText("-> " + cacheDexDir.getAbsolutePath() + " is empty, skip cleaning"); 129 | logScrollView.post(() -> logScrollView.fullScroll(View.FOCUS_DOWN)); 130 | }); 131 | } 132 | } 133 | 134 | private Object getPathList(@NotNull ClassLoader classLoader) throws Exception { 135 | Field pathListField = Objects.requireNonNull(classLoader.getClass().getSuperclass()).getDeclaredField("pathList"); 136 | pathListField.setAccessible(true); 137 | return pathListField.get(classLoader); 138 | } 139 | 140 | private void processDexFiles(ApplicationInfo mcInfo, File cacheDexDir, @NotNull Object pathList, @NotNull Handler handler, TextView listener, ScrollView logScrollView, String launcherDexName) throws Exception { 141 | Method addDexPath = pathList.getClass().getDeclaredMethod("addDexPath", String.class, File.class); 142 | File launcherDex = new File(cacheDexDir, launcherDexName); 143 | 144 | copyFile(getAssets().open(launcherDexName), launcherDex); 145 | handler.post(() -> { 146 | listener.append("\n-> " + launcherDexName + " copied to " + launcherDex.getAbsolutePath()); 147 | logScrollView.post(() -> logScrollView.fullScroll(View.FOCUS_DOWN)); 148 | }); 149 | 150 | if (launcherDex.setReadOnly()) { 151 | addDexPath.invoke(pathList, launcherDex.getAbsolutePath(), null); 152 | handler.post(() -> { 153 | listener.append("\n-> " + launcherDexName + " added to dex path list"); 154 | logScrollView.post(() -> logScrollView.fullScroll(View.FOCUS_DOWN)); 155 | }); 156 | } 157 | 158 | try (ZipFile zipFile = new ZipFile(mcInfo.sourceDir)) { 159 | for (int i = 10; i >= 0; i--) { 160 | String dexName = "classes" + (i == 0 ? "" : i) + ".dex"; 161 | ZipEntry dexFile = zipFile.getEntry(dexName); 162 | if (dexFile != null) { 163 | File mcDex = new File(cacheDexDir, dexName); 164 | copyFile(zipFile.getInputStream(dexFile), mcDex); 165 | handler.post(() -> { 166 | listener.append("\n-> " + mcInfo.sourceDir + "/" + dexName + " copied to " + mcDex.getAbsolutePath()); 167 | logScrollView.post(() -> logScrollView.fullScroll(View.FOCUS_DOWN)); 168 | }); 169 | if (mcDex.setReadOnly()) { 170 | addDexPath.invoke(pathList, mcDex.getAbsolutePath(), null); 171 | handler.post(() -> { 172 | listener.append("\n-> " + dexName + " added to dex path list"); 173 | logScrollView.post(() -> logScrollView.fullScroll(View.FOCUS_DOWN)); 174 | }); 175 | } 176 | } 177 | } 178 | } catch (Throwable th) {} 179 | handler.post(() -> { 180 | listener.append("\n-> Processed dex files."); 181 | logScrollView.post(() -> logScrollView.fullScroll(View.FOCUS_DOWN)); 182 | }); 183 | } 184 | 185 | @SuppressLint("SoonBlockedPrivateApi") 186 | private boolean processNativeLibraries(ApplicationInfo mcInfo, @NotNull Object pathList, @NotNull Handler handler, TextView listener, ScrollView logScrollView) throws Exception { 187 | FileInputStream inStream = new FileInputStream(getApkWithLibs(mcInfo)); 188 | BufferedInputStream bufInStream = new BufferedInputStream(inStream); 189 | ZipInputStream inZipStream = new ZipInputStream(bufInStream); 190 | if (!checkLibCompatibility(inZipStream)) { 191 | handler.post(() -> alertAndExit("Wrong Minecraft architecture", "The Minecraft you have installed does not support the same main architecture (" + Build.SUPPORTED_ABIS[0] + ") your device uses, MBLoader can't work with it")); 192 | return false; 193 | } 194 | Method addNativePath = pathList.getClass().getDeclaredMethod("addNativePath", Collection.class); 195 | ArrayList libDirList = new ArrayList<>(); 196 | File libdir = new File(mcInfo.nativeLibraryDir); 197 | if (libdir.list() == null || libdir.list().length == 0 198 | || (mcInfo.flags & ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS) != ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS) { 199 | loadUnextractedLibs(mcInfo); 200 | libDirList.add(getCodeCacheDir().getAbsolutePath() + "/"); 201 | } else { 202 | libDirList.add(mcInfo.nativeLibraryDir); 203 | } 204 | addNativePath.invoke(pathList, libDirList); 205 | handler.post(() -> { 206 | listener.append("\n-> " + mcInfo.nativeLibraryDir + " added to native library directory path"); 207 | logScrollView.post(() -> logScrollView.fullScroll(View.FOCUS_DOWN)); 208 | }); 209 | return true; 210 | } 211 | 212 | private static Boolean checkLibCompatibility(ZipInputStream zip) throws Exception{ 213 | ZipEntry ze = null; 214 | String requiredLibDir = "lib/" + Build.SUPPORTED_ABIS[0] + "/"; 215 | while ((ze = zip.getNextEntry()) != null) { 216 | if (ze.getName().startsWith(requiredLibDir)) { 217 | return true; 218 | } 219 | } 220 | zip.close(); 221 | return false; 222 | } 223 | 224 | private void alertAndExit(String issue, String description) { 225 | AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create(); 226 | alertDialog.setTitle(issue); 227 | alertDialog.setMessage(description); 228 | alertDialog.setCancelable(false); 229 | alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "Exit", 230 | new DialogInterface.OnClickListener() { 231 | public void onClick(DialogInterface dialog, int which) { 232 | finish(); 233 | } 234 | }); 235 | alertDialog.show(); 236 | } 237 | 238 | private void loadUnextractedLibs(ApplicationInfo appInfo) throws Exception { 239 | FileInputStream inStream = new FileInputStream(getApkWithLibs(appInfo)); 240 | BufferedInputStream bufInStream = new BufferedInputStream(inStream); 241 | ZipInputStream inZipStream = new ZipInputStream(bufInStream); 242 | String zipPath = "lib/" + Build.SUPPORTED_ABIS[0] + "/"; 243 | String outPath = getCodeCacheDir().getAbsolutePath() + "/"; 244 | File dir = new File(outPath); 245 | dir.mkdir(); 246 | extractDir(appInfo, inZipStream, zipPath, outPath); 247 | } 248 | 249 | public String getApkWithLibs(ApplicationInfo pkg) throws PackageManager.NameNotFoundException { 250 | // get installed split's Names 251 | String[] sn=pkg.splitSourceDirs; 252 | 253 | // check whether if it's really split or not 254 | if (sn != null && sn.length > 0) { 255 | String cur_abi = Build.SUPPORTED_ABIS[0].replace('-','_'); 256 | // search installed splits 257 | for(String n:sn){ 258 | //check whether is the one required 259 | if(n.contains(cur_abi)){ 260 | // yes, it's installed! 261 | return n; 262 | } 263 | } 264 | } 265 | // couldn't find! 266 | return pkg.sourceDir; 267 | } 268 | 269 | private static void extractDir(ApplicationInfo mcInfo, ZipInputStream zip, String zip_folder, String out_folder) throws Exception { 270 | ZipEntry ze = null; 271 | while ((ze = zip.getNextEntry()) != null) { 272 | if (ze.getName().startsWith(zip_folder) && !ze.getName().contains("c++_shared")) { 273 | String strippedName = ze.getName().substring(zip_folder.length()); 274 | String path = out_folder + "/" + strippedName; 275 | OutputStream out = new FileOutputStream(path); 276 | BufferedOutputStream outBuf = new BufferedOutputStream(out); 277 | byte[] buffer = new byte[9000]; 278 | int len; 279 | while ((len = zip.read(buffer)) != -1) { 280 | outBuf.write(buffer, 0, len); 281 | } 282 | outBuf.close(); 283 | } 284 | } 285 | zip.close(); 286 | } 287 | 288 | private void launchMinecraft(@NotNull ApplicationInfo mcInfo) throws ClassNotFoundException { 289 | Class launcherClass = getClassLoader().loadClass("com.mojang.minecraftpe.Launcher"); 290 | // We do this to preserve data that apps like file managers pass 291 | Intent mcActivity = getIntent().setClass(this, launcherClass); 292 | mcActivity.putExtra("MC_SRC", mcInfo.sourceDir); 293 | 294 | if (mcInfo.splitSourceDirs != null) { 295 | ArrayList listSrcSplit = new ArrayList<>(); 296 | Collections.addAll(listSrcSplit, mcInfo.splitSourceDirs); 297 | mcActivity.putExtra("MC_SPLIT_SRC", listSrcSplit); 298 | } 299 | 300 | startActivity(mcActivity); 301 | finish(); 302 | } 303 | 304 | private void handleException(@NotNull Exception e, @NotNull Intent fallbackActivity) { 305 | String logMessage = e.getCause() != null ? e.getCause().toString() : e.toString(); 306 | fallbackActivity.putExtra("LOG_STR", logMessage); 307 | startActivity(fallbackActivity); 308 | finish(); 309 | } 310 | 311 | private static void copyFile(InputStream from, @NotNull File to) throws IOException { 312 | File parentDir = to.getParentFile(); 313 | if (parentDir != null && !parentDir.exists() && !parentDir.mkdirs()) { 314 | throw new IOException("Failed to create directories"); 315 | } 316 | if (!to.exists() && !to.createNewFile()) { 317 | throw new IOException("Failed to create new file"); 318 | } 319 | try (BufferedInputStream input = new BufferedInputStream(from); 320 | BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(to.toPath()))) { 321 | byte[] buffer = new byte[8192]; 322 | int bytesRead; 323 | while ((bytesRead = input.read(buffer)) != -1) { 324 | output.write(buffer, 0, bytesRead); 325 | } 326 | } 327 | } 328 | 329 | private void setupNavigation() { 330 | // Setup bottom navigation 331 | BottomNavigationView bottomNav = findViewById(R.id.bottom_navigation); 332 | 333 | // Set initial fragment 334 | if (getSupportFragmentManager().findFragmentById(R.id.fragment_container) == null) { 335 | getSupportFragmentManager().beginTransaction() 336 | .replace(R.id.fragment_container, new HomeFragment()) 337 | .commit(); 338 | 339 | // Select home item initially 340 | bottomNav.setSelectedItemId(R.id.navigation_home); 341 | } 342 | 343 | // Animate nav items using state list animator 344 | bottomNav.setItemIconTintList(getColorStateList(R.color.nav_item_color)); 345 | bottomNav.setItemTextColor(getColorStateList(R.color.nav_item_color)); 346 | bottomNav.setStateListAnimator(android.animation.AnimatorInflater.loadStateListAnimator( 347 | this, R.animator.nav_item_animation)); 348 | 349 | // Track the current selected item to determine animation direction 350 | final int[] currentItem = {R.id.navigation_home}; 351 | 352 | // Handle navigation item selection 353 | bottomNav.setOnItemSelectedListener(item -> { 354 | Fragment selectedFragment = null; 355 | int enterAnim = R.anim.slide_in_right; 356 | int exitAnim = R.anim.slide_out_left; 357 | 358 | // Determine animation direction based on item position 359 | if (getNavigationItemIndex(item.getItemId()) < getNavigationItemIndex(currentItem[0])) { 360 | enterAnim = R.anim.slide_in_left; 361 | exitAnim = R.anim.slide_out_right; 362 | } 363 | 364 | // Create appropriate fragment 365 | if (item.getItemId() == R.id.navigation_home) { 366 | selectedFragment = new HomeFragment(); 367 | } else if (item.getItemId() == R.id.navigation_settings) { 368 | selectedFragment = new SettingsFragment(); 369 | } 370 | 371 | if (selectedFragment != null) { 372 | // Update current item 373 | currentItem[0] = item.getItemId(); 374 | 375 | // Perform fragment transition with animations 376 | getSupportFragmentManager().beginTransaction() 377 | .setCustomAnimations( 378 | enterAnim, 379 | exitAnim 380 | ) 381 | .replace(R.id.fragment_container, selectedFragment) 382 | .commit(); 383 | return true; 384 | } 385 | return false; 386 | }); 387 | } 388 | 389 | // Helper method to get the index of navigation items 390 | private int getNavigationItemIndex(int itemId) { 391 | if (itemId == R.id.navigation_home) return 0; 392 | if (itemId == R.id.navigation_settings) return 1; 393 | return 0; 394 | } 395 | } 396 | -------------------------------------------------------------------------------- /app/src/main/java/io/bambosan/mbloader/SettingsFragment.java: -------------------------------------------------------------------------------- 1 | package io.bambosan.mbloader; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.os.Bundle; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.EditText; 10 | import androidx.fragment.app.Fragment; 11 | import com.google.android.material.button.MaterialButton; 12 | import com.google.android.material.textfield.TextInputEditText; 13 | 14 | public class SettingsFragment extends Fragment { 15 | private SharedPreferences prefs; 16 | private View rootView; 17 | 18 | @Override 19 | public void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | prefs = requireActivity().getSharedPreferences("app_settings", Context.MODE_PRIVATE); 22 | } 23 | 24 | @Override 25 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 26 | rootView = inflater.inflate(R.layout.fragment_settings, container, false); 27 | 28 | TextInputEditText mcPackageName = rootView.findViewById(R.id.mc_pkgname); 29 | mcPackageName.setText(MainActivity.MC_PACKAGE_NAME); 30 | 31 | // Set up crash test button 32 | MaterialButton testCrashButton = rootView.findViewById(R.id.test_crash_button); 33 | testCrashButton.setOnClickListener(v -> { 34 | throw new RuntimeException("Test crash to verify crash handler"); 35 | }); 36 | 37 | return rootView; 38 | } 39 | } -------------------------------------------------------------------------------- /app/src/main/java/io/bambosan/mbloader/SplashActivity.java: -------------------------------------------------------------------------------- 1 | package io.bambosan.mbloader; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorListenerAdapter; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.os.Handler; 8 | import android.view.View; 9 | import android.view.animation.Animation; 10 | import android.view.animation.AnimationUtils; 11 | import android.widget.ImageView; 12 | import android.widget.TextView; 13 | import androidx.appcompat.app.AppCompatActivity; 14 | import androidx.core.app.ActivityOptionsCompat; 15 | 16 | public class SplashActivity extends AppCompatActivity { 17 | 18 | private static final int SPLASH_DURATION = 3000; // 3 seconds 19 | 20 | private ImageView logoView; 21 | private TextView titleView; 22 | private TextView subtitleView; 23 | private View highlightView; 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_splash); 29 | 30 | // Find views 31 | logoView = findViewById(R.id.splash_logo); 32 | titleView = findViewById(R.id.splash_title); 33 | subtitleView = findViewById(R.id.splash_subtitle); 34 | highlightView = findViewById(R.id.splash_highlight); 35 | 36 | // Start animations 37 | startAnimations(); 38 | 39 | // Delay transition to MainActivity 40 | new Handler().postDelayed(this::startMainActivity, SPLASH_DURATION); 41 | } 42 | 43 | private void startAnimations() { 44 | // Logo animation 45 | Animation zoomIn = AnimationUtils.loadAnimation(this, R.anim.logo_zoom_in); 46 | Animation rotate = AnimationUtils.loadAnimation(this, R.anim.logo_rotate); 47 | 48 | logoView.startAnimation(zoomIn); 49 | 50 | zoomIn.setAnimationListener(new Animation.AnimationListener() { 51 | @Override 52 | public void onAnimationStart(Animation animation) {} 53 | 54 | @Override 55 | public void onAnimationEnd(Animation animation) { 56 | logoView.startAnimation(rotate); 57 | } 58 | 59 | @Override 60 | public void onAnimationRepeat(Animation animation) {} 61 | }); 62 | 63 | // Text animations 64 | Animation textAnim = AnimationUtils.loadAnimation(this, R.anim.text_slide_up); 65 | titleView.startAnimation(textAnim); 66 | 67 | Animation subtitleAnim = AnimationUtils.loadAnimation(this, R.anim.text_slide_up); 68 | subtitleAnim.setStartOffset(1300); // Slight delay for subtitle 69 | subtitleView.startAnimation(subtitleAnim); 70 | 71 | // Highlight animation 72 | Animation pulseAnim = AnimationUtils.loadAnimation(this, R.anim.logo_pulse); 73 | highlightView.startAnimation(pulseAnim); 74 | } 75 | 76 | private void startMainActivity() { 77 | Intent intent = new Intent(this, MainActivity.class); 78 | 79 | // Create a shared element transition 80 | ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation( 81 | this, logoView, "app_logo"); 82 | 83 | startActivity(intent, options.toBundle()); 84 | 85 | // Delayed finish to allow smooth transition 86 | new Handler().postDelayed(this::finish, 500); 87 | } 88 | } -------------------------------------------------------------------------------- /app/src/main/jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | LOCAL_MODULE := mc 5 | LOCAL_SRC_FILES := mc-init.cpp 6 | include $(BUILD_SHARED_LIBRARY) 7 | -------------------------------------------------------------------------------- /app/src/main/jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_ABI := arm64-v8a 2 | APP_STL := c++_shared 3 | -------------------------------------------------------------------------------- /app/src/main/jni/mc-init.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | static void (*android_main_minecraft)(struct android_app *app); 8 | static void (*ANativeActivity_onCreate_minecraft)(ANativeActivity *activity, void *savedState, size_t savedStateSize); 9 | 10 | extern "C" void android_main(struct android_app *app) { 11 | android_main_minecraft(app); 12 | } 13 | 14 | extern "C" void ANativeActivity_onCreate(ANativeActivity *activity, void *savedState, size_t savedStateSize) { 15 | ANativeActivity_onCreate_minecraft(activity, savedState, savedStateSize); 16 | } 17 | 18 | JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) { 19 | void *handle = dlopen("libminecraftpe.so", RTLD_LAZY); 20 | android_main_minecraft = (void (*)(struct android_app *)) (dlsym(handle, "android_main")); 21 | ANativeActivity_onCreate_minecraft = (void (*)(ANativeActivity *, void *, size_t)) (dlsym(handle, "ANativeActivity_onCreate")); 22 | return JNI_VERSION_1_6; 23 | } -------------------------------------------------------------------------------- /app/src/main/jniLibs/arm64-v8a/libdraco.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyssadev/mb-loader-unofficial/fe6a30125e6baefa396c8853cd4a6bdfab4942eb/app/src/main/jniLibs/arm64-v8a/libdraco.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/arm64-v8a/libmtbinloader2.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyssadev/mb-loader-unofficial/fe6a30125e6baefa396c8853cd4a6bdfab4942eb/app/src/main/jniLibs/arm64-v8a/libmtbinloader2.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi-v7a/libdraco.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyssadev/mb-loader-unofficial/fe6a30125e6baefa396c8853cd4a6bdfab4942eb/app/src/main/jniLibs/armeabi-v7a/libdraco.so -------------------------------------------------------------------------------- /app/src/main/jniLibs/armeabi-v7a/libmtbinloader2.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyssadev/mb-loader-unofficial/fe6a30125e6baefa396c8853cd4a6bdfab4942eb/app/src/main/jniLibs/armeabi-v7a/libmtbinloader2.so -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_in.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_out.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/anim/logo_pulse.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/anim/logo_rotate.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/anim/logo_zoom_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 14 | 15 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_in_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_in_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_out_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_out_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 10 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_up_fade_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/anim/text_slide_up.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/animator/nav_item_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/color/nav_item_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/beta_label_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/button_container_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_home_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_settings_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 8 | 13 | 18 | 23 | 28 | 33 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_monochrome.xml: -------------------------------------------------------------------------------- 1 | 8 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/nav_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/rounded_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/rounded_corner_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 9 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/splash_highlight.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_crash.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 | 21 | 22 | 26 | 27 | 33 | 34 | 35 | 41 | 42 |