diff --git a/app/src/main/assets/SMAPI/StardewModdingAPI.dll b/app/src/main/assets/SMAPI/StardewModdingAPI.dll index 29ee8a0..f7cfe0f 100644 Binary files a/app/src/main/assets/SMAPI/StardewModdingAPI.dll and b/app/src/main/assets/SMAPI/StardewModdingAPI.dll differ diff --git a/app/src/main/java/com/MartyrPher/smapiandroidinstaller/ApkExtractor.java b/app/src/main/java/com/MartyrPher/smapiandroidinstaller/ApkExtractor.java index f7cdc8d..25e3e71 100644 --- a/app/src/main/java/com/MartyrPher/smapiandroidinstaller/ApkExtractor.java +++ b/app/src/main/java/com/MartyrPher/smapiandroidinstaller/ApkExtractor.java @@ -16,26 +16,50 @@ import android.util.Log; public class ApkExtractor{ - private static final String PACKAGE_NAME = "com.chucklefish.stardewvalley"; private static final String TAG = "ApkExtractor"; + private static final String[] PACKAGE_NAMES = {"com.martyrpher.stardewvalley", "com.chucklefish.stardewvalley"}; private final Context context; + private ApplicationInfo mApplicationInfo; + private PackageManager mPackageManager; + private PackageInfo mPackageInfo; + public ApkExtractor(Context appContext) { this.context = appContext; } + public boolean[] checkForInstallOrUpgrade() + { + mPackageManager = context.getPackageManager(); + boolean[] foundApk = {false, false}; + for (int i = 0; i < foundApk.length; i++) + { + try + { + mPackageInfo = mPackageManager.getPackageInfo(PACKAGE_NAMES[i], 0); + mApplicationInfo = getApplicationInfoFrom(mPackageManager, mPackageInfo); + + File file = new File(mApplicationInfo.publicSourceDir); + if (file.exists()) + { + foundApk[i] = true; + } + } + catch (PackageManager.NameNotFoundException e) + { + //Do NOTHING + } + } + return foundApk; + } + //Extracts the APK to a local directory where it can access the files - public boolean extractAPK(Context context) { - try { - PackageManager packageManager = context.getPackageManager(); - PackageInfo packageInfo = packageManager.getPackageInfo(PACKAGE_NAME, 0); - - ApplicationInfo applicationInfo; - applicationInfo = getApplicationInfoFrom(packageManager, packageInfo); - - File apkFile = new File(applicationInfo.publicSourceDir); + public boolean extractAPK() { + try + { + File apkFile = new File(mApplicationInfo.publicSourceDir); File dest = new File(Environment.getExternalStorageDirectory() + "/SMAPI Installer/"); if (apkFile.exists()) { try { @@ -48,7 +72,7 @@ public class ApkExtractor{ Log.e(TAG, e.getLocalizedMessage()); } } - } catch (PackageManager.NameNotFoundException ex) { + } catch (Exception ex) { Log.e(TAG, ex.getLocalizedMessage()); return false; } diff --git a/app/src/main/java/com/MartyrPher/smapiandroidinstaller/BackgroundTask.java b/app/src/main/java/com/MartyrPher/smapiandroidinstaller/BackgroundTask.java index 0b19cd1..6563690 100644 --- a/app/src/main/java/com/MartyrPher/smapiandroidinstaller/BackgroundTask.java +++ b/app/src/main/java/com/MartyrPher/smapiandroidinstaller/BackgroundTask.java @@ -19,20 +19,32 @@ public class BackgroundTask extends AsyncTask { private static final String DIR_MODS_VK_ASSET = "/StardewValley/Mods/VirtualKeyboard/assets"; private static final String MOD_DIR = Environment.getExternalStorageDirectory() + "/StardewValley/Mods/"; + private static final String STARDEW_VALLEY_DIR = Environment.getExternalStorageDirectory() + "/StardewValley/"; + private final Context contextActivity; private ApkInstall apkInstall; + private ApkExtractor extractor; + private boolean updating; - public BackgroundTask(Context context) + public BackgroundTask(Context context, ApkExtractor apkExtractor, boolean update) { this.contextActivity = context; + this.extractor = apkExtractor; + this.updating = update; } @Override protected void onPreExecute() { super.onPreExecute(); - DialogFrag.showDialog(contextActivity, R.string.modify_apk, 0); + int dialogString; + if (updating) + dialogString = R.string.update_apk; + else + dialogString = R.string.modify_apk; + + DialogFrag.showDialog(contextActivity, dialogString, 0); } @Override @@ -45,32 +57,53 @@ public class BackgroundTask extends AsyncTask { try { + extractor.extractAPK(); + publishProgress(9); + + File saveFolder = new File(STARDEW_VALLEY_DIR); + if (!saveFolder.exists()) + saveFolder.mkdir(); + + File modDir = new File(MOD_DIR); if (!modDir.exists()) - { modDir.mkdir(); - } copy.copyAssets(ASSET_APK_FILES, DIR_APK_FILES); - copy.copyAssets(ASSET_STARDEW_FILES, DIR_STARDEW_FILES); - copy.copyAssets(MOD_FILES_VK, DIR_MODS_VK); - copy.copyAssets(MOD_FILES_VK_ASSET, DIR_MODS_VK_ASSET); + publishProgress(18); - File[] moddingAPI = {new File( Environment.getExternalStorageDirectory() + DIR_APK_FILES + "StardewModdingAPI.dll"), + copy.copyAssets(ASSET_STARDEW_FILES, DIR_STARDEW_FILES); + publishProgress(27); + + copy.copyAssets(MOD_FILES_VK, DIR_MODS_VK); + publishProgress(36); + + copy.copyAssets(MOD_FILES_VK_ASSET, DIR_MODS_VK_ASSET); + publishProgress(45); + + File[] moddingAPI = {new File(Environment.getExternalStorageDirectory() + DIR_APK_FILES + "AndroidManifest.xml"), + new File( Environment.getExternalStorageDirectory() + DIR_APK_FILES + "classes.dex"), + new File( Environment.getExternalStorageDirectory() + DIR_APK_FILES + "StardewModdingAPI.dll"), new File(Environment.getExternalStorageDirectory() + DIR_APK_FILES + "StardewModdingAPI.Toolkit.CoreInterfaces.dll"), new File( Environment.getExternalStorageDirectory() + DIR_APK_FILES + "StardewModdingAPI.Toolkit.dll"), new File( Environment.getExternalStorageDirectory() + DIR_APK_FILES + "Newtonsoft.json.dll"), new File( Environment.getExternalStorageDirectory() + DIR_APK_FILES + "System.Data.dll"), new File( Environment.getExternalStorageDirectory() + DIR_APK_FILES + "System.Numerics.dll")}; - publishProgress(1); - writeApk.addFilesToApk(new File(Environment.getExternalStorageDirectory() + "/SMAPI Installer/base.apk"), moddingAPI, "assemblies/", false, 0); - File[] resources = {new File(Environment.getExternalStorageDirectory() + DIR_APK_FILES + "AndroidManifest.xml"), - new File( Environment.getExternalStorageDirectory() + DIR_APK_FILES + "classes.dex")}; - writeApk.addFilesToApk(new File(Environment.getExternalStorageDirectory() + "/SMAPI Installer/base.apk_patched0.apk"), resources, "", true, 1); + boolean[] compressed = {true, true, false, false, false, false, false, false}; + String[] paths = {"", "", "assemblies/", "assemblies/", "assemblies/", "assemblies/", "assemblies/", "assemblies/"}; + publishProgress(54); + + writeApk.addFilesToApk(new File(Environment.getExternalStorageDirectory() + "/SMAPI Installer/base.apk"), moddingAPI, paths, compressed); + publishProgress(63); + signApk.commitSignApk(); + publishProgress(81); + File filesToDelete = new File(Environment.getExternalStorageDirectory() + DIR_APK_FILES); - File deleteOldApk = new File(Environment.getExternalStorageDirectory() + "/SMAPI Installer/base.apk_patched0.apk_patched1.apk"); + File deleteOldApk = new File(Environment.getExternalStorageDirectory() + "/SMAPI Installer/base.apk_patched.apk"); deleteOldApk.delete(); + publishProgress(90); + if (filesToDelete.isDirectory()) { String[] child = filesToDelete.list(); @@ -80,6 +113,7 @@ public class BackgroundTask extends AsyncTask { } filesToDelete.delete(); } + publishProgress(100); return true; } catch(Exception e) @@ -92,6 +126,35 @@ public class BackgroundTask extends AsyncTask { @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); + int message; + switch(values[0]) + { + case 9: + message = R.string.install_abigail_rocks; + break; + case 18: + message = R.string.install_rock_crab; + break; + case 27: + message = R.string.install_squid_ocean; + break; + case 34: + message = R.string.install_dino_egg; + break; + case 54: + message = R.string.installing_pufferchicks; + break; + case 63: + message = R.string.install_milk_cows; + break; + case 81: + message = R.string.install_feeding_juminos; + break; + default: + message = R.string.blank; + break; + } + DialogFrag.updateProgressBar(values[0], message); } @Override @@ -99,7 +162,7 @@ public class BackgroundTask extends AsyncTask { super.onPostExecute(aBoolean); if (aBoolean) { - DialogFrag.dismissDialog(contextActivity); + DialogFrag.dismissDialog(); apkInstall.installNewStardew(); } } diff --git a/app/src/main/java/com/MartyrPher/smapiandroidinstaller/DialogFrag.java b/app/src/main/java/com/MartyrPher/smapiandroidinstaller/DialogFrag.java index 6c7d226..cfa8398 100644 --- a/app/src/main/java/com/MartyrPher/smapiandroidinstaller/DialogFrag.java +++ b/app/src/main/java/com/MartyrPher/smapiandroidinstaller/DialogFrag.java @@ -8,12 +8,31 @@ import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.DialogFragment; +import android.view.LayoutInflater; import android.view.View; +import android.widget.ProgressBar; +import android.widget.TextView; + +import java.util.Random; +import java.util.concurrent.TimeUnit; public class DialogFrag extends DialogFragment { public static AlertDialog mAlertDialog; + private static ProgressBar mProgressBar; + private static TextView mTextView; + + //Test array to cycle through different messages + private static int[] messages = { R.string.installing_pufferchicks, + R.string.install_milk_cows, + R.string.install_ancient_fruit , + R.string.install_abigail_rocks, + R.string.install_feeding_juminos, + R.string.install_squid_ocean, + R.string.install_dino_egg, + R.string.install_rock_crab }; + public DialogFrag() { } @@ -24,10 +43,15 @@ public class DialogFrag extends DialogFragment { switch(tag) { case 0: + LayoutInflater mLayoutInflater = LayoutInflater.from(context); + View dialogView = mLayoutInflater.inflate(R.layout.progress_bar_dialog, null); + builder.setView(dialogView); builder.setMessage(message); builder.setCancelable(false); mAlertDialog = builder.create(); mAlertDialog.show(); + mProgressBar = dialogView.findViewById(R.id.progressBar); + mTextView = dialogView.findViewById(R.id.install_message); break; case 1: builder.setMessage(message); @@ -37,30 +61,18 @@ public class DialogFrag extends DialogFragment { } } - public static void dismissDialog(Context context) + public static void updateProgressBar(int progress, int message) + { + mProgressBar.setProgress(progress); + mTextView.setText(message); + } + + public static void dismissDialog() { if (mAlertDialog.isShowing()) mAlertDialog.dismiss(); } - public static void dismissDialogInt(Context context, int message) - { - if(mAlertDialog.isShowing()) - { - mAlertDialog.dismiss(); - } - AlertDialog.Builder builder = new AlertDialog.Builder(context); - - builder.setMessage(message); - builder.setPositiveButton("Awesome", new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.dismiss(); - } - }); - builder.show(); - } - public static void dismissDialogString(Context context, String message) { if(mAlertDialog.isShowing()) @@ -70,7 +82,7 @@ public class DialogFrag extends DialogFragment { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setMessage(message); - builder.setPositiveButton("Awesome", new DialogInterface.OnClickListener() { + builder.setPositiveButton("Oh No", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); diff --git a/app/src/main/java/com/MartyrPher/smapiandroidinstaller/MainActivity.java b/app/src/main/java/com/MartyrPher/smapiandroidinstaller/MainActivity.java index f3caf3c..b98fe8b 100644 --- a/app/src/main/java/com/MartyrPher/smapiandroidinstaller/MainActivity.java +++ b/app/src/main/java/com/MartyrPher/smapiandroidinstaller/MainActivity.java @@ -31,17 +31,16 @@ public class MainActivity extends AppCompatActivity { @Override public void onClick(View v) { start_button.setBackgroundColor(getResources().getColor(R.color.colorAccent)); - Toast.makeText(MainActivity.this, R.string.start_install, Toast.LENGTH_SHORT).show(); if (hasPermissions) { - boolean foundGame; + boolean[] foundGame; ApkExtractor apkExtractor = new ApkExtractor(MainActivity.this); - BackgroundTask backgroundTask = new BackgroundTask(MainActivity.this); - foundGame = apkExtractor.extractAPK(getApplicationContext()); + foundGame = apkExtractor.checkForInstallOrUpgrade(); - if(foundGame) + if((foundGame[0] || foundGame[1])) { + BackgroundTask backgroundTask = new BackgroundTask(MainActivity.this, apkExtractor, foundGame[0]); backgroundTask.execute(); } else @@ -59,6 +58,8 @@ public class MainActivity extends AppCompatActivity { }); } + + //Request permissions to be able to read/write external storage public void requestPermissions() { if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) diff --git a/app/src/main/java/com/MartyrPher/smapiandroidinstaller/SignApk.java b/app/src/main/java/com/MartyrPher/smapiandroidinstaller/SignApk.java index 8844d5b..753d6ce 100644 --- a/app/src/main/java/com/MartyrPher/smapiandroidinstaller/SignApk.java +++ b/app/src/main/java/com/MartyrPher/smapiandroidinstaller/SignApk.java @@ -17,11 +17,10 @@ import java.security.cert.X509Certificate; public class SignApk { private static final String TAG = "SignApk"; - private static final String APK_LOCATION = Environment.getExternalStorageDirectory() + "/SMAPI Installer/base.apk_patched0.apk_patched1.apk"; + private static final String APK_LOCATION = Environment.getExternalStorageDirectory() + "/SMAPI Installer/base.apk_patched.apk"; private static final String KEYSTORE_LOCATION = Environment.getExternalStorageDirectory() + "/SMAPI Installer/ApkFiles/debug.keystore"; private static final String KEYSTORE_PASSWORD = "android"; - public SignApk() { } diff --git a/app/src/main/java/com/MartyrPher/smapiandroidinstaller/WriteApk.java b/app/src/main/java/com/MartyrPher/smapiandroidinstaller/WriteApk.java index 373c4f1..e454f3f 100644 --- a/app/src/main/java/com/MartyrPher/smapiandroidinstaller/WriteApk.java +++ b/app/src/main/java/com/MartyrPher/smapiandroidinstaller/WriteApk.java @@ -7,6 +7,7 @@ import java.io.FileOutputStream; import java.io.InputStream; import java.util.zip.CRC32; import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; @@ -20,15 +21,18 @@ public class WriteApk { { } - public void addFilesToApk(File source, File[] files, String path, boolean compression, int count){ - try{ + public void addFilesToApk(File source, File[] files, String[] path, boolean[] compression){ + try + { byte[] buffer = new byte[4096]; + ZipFile zipFile = new ZipFile(source); + ZipInputStream zin = new ZipInputStream(new FileInputStream(source)); - ZipOutputStream out = new ZipOutputStream(new FileOutputStream( source + "_patched" + count + ".apk")); + ZipOutputStream out = new ZipOutputStream(new FileOutputStream( source + "_patched.apk")); for(int i = 0; i < files.length; i++){ CRC32 crc = new CRC32(); - if (!compression) + if (!compression[i]) { int bytesRead; BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(files[i])); @@ -40,9 +44,9 @@ public class WriteApk { } InputStream in = new FileInputStream(files[i]); - ZipEntry compress = new ZipEntry(path + files[i].getName()); + ZipEntry compress = new ZipEntry(path[i] + files[i].getName()); - if (!compression) + if (!compression[i]) { compress.setMethod(ZipEntry.STORED); compress.setCompressedSize(files[i].length()); @@ -50,7 +54,7 @@ public class WriteApk { compress.setCrc(crc.getValue()); } - out.putNextEntry(new ZipEntry(compress)); + out.putNextEntry(compress); for(int read = in.read(buffer); read > -1; read = in.read(buffer)){ out.write(buffer, 0, read); } @@ -74,9 +78,9 @@ public class WriteApk { } } - private boolean apkEntryMatch(String zeName, File[] files, String path){ + private boolean apkEntryMatch(String zeName, File[] files, String[] path){ for(int i = 0; i < files.length; i++){ - if((path + files[i].getName()).equals(zeName)){ + if((path[i] + files[i].getName()).equals(zeName)){ return true; } } diff --git a/app/src/main/res/drawable/layout_background.xml b/app/src/main/res/drawable/layout_background.xml new file mode 100644 index 0000000..255246b --- /dev/null +++ b/app/src/main/res/drawable/layout_background.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 700d70a..295545c 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -4,6 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" + android:background="@drawable/layout_background" tools:context=".MainActivity">