diff --git a/app/build.gradle b/app/build.gradle index d3eebbbba..f0fe1579d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,7 +26,8 @@ android { } } repositories { - + jcenter() + maven { url "https://jitpack.io" } } dependencies { @@ -35,6 +36,6 @@ dependencies { compile 'com.android.support:cardview-v7:24.2.0' compile 'com.android.support:design:24.2.0' compile 'com.jakewharton:butterknife:8.4.0' - compile 'com.github.angads25:filepicker:1.0.6' + compile 'com.github.michalis-vitos:aFileChooser:master' annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0' } diff --git a/app/src/main/java/com/topjohnwu/magisk/ModulesFragment.java b/app/src/main/java/com/topjohnwu/magisk/ModulesFragment.java index 3404bd956..93110915b 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ModulesFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/ModulesFragment.java @@ -5,8 +5,6 @@ import android.content.Intent; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; -import android.os.Environment; -import android.provider.DocumentsContract; import android.support.annotation.Nullable; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.TabLayout; @@ -14,7 +12,6 @@ import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; -import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -36,10 +33,9 @@ import butterknife.ButterKnife; public class ModulesFragment extends Fragment { + private static final int FETCH_ZIP_CODE = 2; public static List listModules = new ArrayList<>(); public static List listModulesCache = new ArrayList<>(); - private int viewPagePosition; - @BindView(R.id.progressBar) ProgressBar progressBar; @BindView(R.id.fab) @@ -48,8 +44,8 @@ public class ModulesFragment extends Fragment { ViewPager viewPager; @BindView(R.id.tab_layout) TabLayout tabLayout; + private int viewPagePosition; private RepoHelper.TaskDelegate mTaskDelegate; - private static final int RQS_OPEN_DOCUMENT_TREE = 2; @Nullable @Override @@ -58,17 +54,16 @@ public class ModulesFragment extends Fragment { ButterKnife.bind(this, view); fabio.setOnClickListener(v -> { - Intent fileintent = new Intent(Intent.ACTION_GET_CONTENT); - fileintent.setType("application/zip"); - startActivityForResult(fileintent, RQS_OPEN_DOCUMENT_TREE); - + Intent fileIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + fileIntent.setType("application/zip"); + fileIntent.addCategory(Intent.CATEGORY_OPENABLE); + startActivityForResult(fileIntent, FETCH_ZIP_CODE); }); new Utils.LoadModules(getActivity(), false).execute(); mTaskDelegate = result -> { if (result.equals("OK")) { - Log.d("Magisk", "ModulesFragment: We dun got the result, hur hur."); RefreshUI(); } @@ -78,31 +73,14 @@ public class ModulesFragment extends Fragment { return view; } - - public static boolean isExternalStorageDocument(Uri uri) { - return "com.android.externalstorage.documents".equals(uri.getAuthority()); - } - - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - String file = ""; - if (resultCode == Activity.RESULT_OK && requestCode == RQS_OPEN_DOCUMENT_TREE) { - if (isExternalStorageDocument(data.getData())) { - final String docId = DocumentsContract.getDocumentId(data.getData()); - final String[] split = docId.split(":"); - final String type = split[0]; - - if ("primary".equalsIgnoreCase(type)) { - file = Environment.getExternalStorageDirectory() + "/" + split[1]; - } - - // TODO handle non-primary volumes - } - String shit = data.getDataString(); - - Log.d("Magisk", "ModulesFragment: Got a result, " + shit + " and " + data.getData().getAuthority() + " and " + file); - + Uri mUri = data.getData(); + final int takeFlags = data.getFlags() + & (Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + if (resultCode == Activity.RESULT_OK && requestCode == FETCH_ZIP_CODE) { + new Utils.FlashZIP(getActivity(), mUri, takeFlags).execute(); } } @@ -111,10 +89,8 @@ public class ModulesFragment extends Fragment { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.menu_module, menu); - } - private void RefreshUI() { viewPagePosition = tabLayout.getSelectedTabPosition(); listModules.clear(); @@ -129,7 +105,6 @@ public class ModulesFragment extends Fragment { new updateUI().execute(); } - void selectPage(int pageIndex) { tabLayout.setScrollPosition(pageIndex, 0f, true); viewPager.setCurrentItem(pageIndex); @@ -153,7 +128,6 @@ public class ModulesFragment extends Fragment { } - private class updateUI extends AsyncTask { @Override diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java index 52b74550f..e4616718f 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java @@ -5,6 +5,7 @@ import android.app.Activity; import android.app.DownloadManager; import android.app.ProgressDialog; import android.content.BroadcastReceiver; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -13,6 +14,7 @@ import android.database.Cursor; import android.net.Uri; import android.os.AsyncTask; import android.os.Environment; +import android.provider.DocumentsContract; import android.support.design.widget.Snackbar; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AlertDialog; @@ -33,16 +35,18 @@ import org.json.JSONObject; import java.io.BufferedReader; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; -import java.util.Collections; -import java.util.Comparator; import java.util.List; import javax.crypto.BadPaddingException; @@ -483,30 +487,106 @@ public class Utils { return null; } - } public static class FlashZIP extends AsyncTask { private String mPath, mName; + private Uri mUri; private ProgressDialog progress; + private File mFile; private Context mContext; private List ret; + private boolean deleteFileAfter; public FlashZIP(Context context, String name, String path) { mContext = context; mName = name; mPath = path; + deleteFileAfter = false; + } + + public FlashZIP(Context context, Uri uRi, int flags) { + mContext = context; + mUri = uRi; + deleteFileAfter = true; + String file = ""; + final String docId = DocumentsContract.getDocumentId(mUri); + + Log.d("Magisk","Utils: FlashZip Running, " + docId + " and " + mUri.toString()); + String[] split = docId.split(":"); + mName = split[1]; + if (mName.contains("/")) { + split = mName.split("/"); + } + if (split[1].contains(".zip")) { + file = mContext.getFilesDir() + "/" + split[1]; + Log.d("Magisk", "Utils: FlashZip running for uRI " + mUri.toString()); + } else { + Log.e("Magisk", "Utils: error parsing Zipfile " + mUri.getPath()); + this.cancel(true); + } + ContentResolver contentResolver = mContext.getContentResolver(); + contentResolver.takePersistableUriPermission(mUri, flags); + try { + InputStream in = contentResolver.openInputStream(mUri); + Log.d("Magisk", "Firing inputStream"); + mFile = createFileFromInputStream(in, file, mContext); + if (mFile != null) { + mPath = mFile.getPath(); + Log.d("Magisk", "Utils: Mpath is " + mPath); + } else { + Log.e("Magisk", "Utils: error creating file " + mUri.getPath()); + this.cancel(true); + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + + // TODO handle non-primary volumes + + } + + private static File createFileFromInputStream(InputStream inputStream, String fileName, Context context) { + + try { + File f = new File(fileName); + f.setWritable(true, false); + OutputStream outputStream = new FileOutputStream(f); + byte buffer[] = new byte[1024]; + int length; + + while ((length = inputStream.read(buffer)) > 0) { + outputStream.write(buffer, 0, length); + } + + outputStream.close(); + inputStream.close(); + Log.d("Magisk", "Holy balls, I think it worked. File is " + f.getPath()); + return f; + + } catch (IOException e) { + System.out.println("error in creating a file"); + e.printStackTrace(); + } + + return null; } @Override protected void onPreExecute() { super.onPreExecute(); + progress = ProgressDialog.show(mContext, mContext.getString(R.string.zip_install_progress_title), mContext.getString(R.string.zip_install_progress_msg, mName)); } @Override protected Boolean doInBackground(Void... voids) { + if (mPath != null) { + Log.e("Magisk", "Utils: Error, flashZIP called without a valid zip file to flash."); + this.cancel(true); + return false; + } if (!Shell.rootAccess()) { return false; } else { @@ -518,7 +598,7 @@ public class Utils { "BOOTMODE=true sh /data/tmp/META-INF/com/google/android/update-binary dummy 1 /data/tmp/install.zip", "if [ $? -eq 0 ]; then echo true; else echo false; fi" ); - return Boolean.parseBoolean(ret.get(ret.size() - 1)); + return ret != null && Boolean.parseBoolean(ret.get(ret.size() - 1)); } } @@ -526,6 +606,10 @@ public class Utils { protected void onPostExecute(Boolean result) { super.onPostExecute(result); Shell.su("rm -rf /data/tmp"); + if (deleteFileAfter) { + Shell.su("rm -rf " + mPath); + Log.d("Magisk", "Utils: Deleting file " + mPath); + } progress.dismiss(); if (!result) { Toast.makeText(mContext, mContext.getString(R.string.manual_install, mPath), Toast.LENGTH_LONG).show(); @@ -550,5 +634,4 @@ public class Utils { } - }