From 5f2feffaec86b511a74719ab506af7ee70206828 Mon Sep 17 00:00:00 2001 From: RainbowC0 <15760207563@139.com> Date: Wed, 4 Sep 2024 11:25:19 +0800 Subject: [PATCH] Add setup guidance & request permission action --- app/build.gradle | 6 +- app/src/main/assets/init | 22 +++ .../main/java/cn/rbc/termuc/Application.java | 80 +-------- .../main/java/cn/rbc/termuc/EditFragment.java | 19 +-- app/src/main/java/cn/rbc/termuc/Lsp.java | 2 +- .../main/java/cn/rbc/termuc/MainActivity.java | 39 +++-- .../java/cn/rbc/termuc/SettingsActivity.java | 6 +- app/src/main/java/cn/rbc/termuc/Utils.java | 153 ++++++++++++++++-- app/src/main/res/values-zh/strings.xml | 5 + app/src/main/res/values/strings.xml | 15 +- app/src/main/res/xml/settings.xml | 4 + .../common/OnTextChangeListener.java | 2 + .../view/FreeScrollingTextField.java | 2 - .../codeeditor/view/TextFieldController.java | 2 - 14 files changed, 226 insertions(+), 131 deletions(-) create mode 100644 app/src/main/assets/init diff --git a/app/build.gradle b/app/build.gradle index 63a4247..0c1076a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,7 +6,7 @@ android { defaultConfig { applicationId "cn.rbc.termuc" minSdkVersion 21 - targetSdkVersion 29 + targetSdkVersion 30 versionCode 3 versionName "0.1.2" } @@ -18,8 +18,8 @@ android { } } compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_1_7 + targetCompatibility = JavaVersion.VERSION_1_7 } lintOptions { checkReleaseBuilds false diff --git a/app/src/main/assets/init b/app/src/main/assets/init new file mode 100644 index 0000000..afb4114 --- /dev/null +++ b/app/src/main/assets/init @@ -0,0 +1,22 @@ +echo 设置存储 Setup storage +termux-setup-storage +DATA=package:com.termux +echo -n 设置悬浮窗权限 Setup draw over apps \(请按回车 Press Enter\);read _ +am start -a android.settings.action.MANAGE_OVERLAY_PERMISSION -d $DATA>/dev/null +echo -n 设置禁用电池优化 Setup ignore battery optimizations \(请按回车 Press Enter\);read _ +am start -a android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS>/dev/null +echo -n 设置关联启动与后台弹出权限 Setup Startup \& Background pop-ups permissions \(请按回车 Press Enter\);read _ +am start -a android.settings.APPLICATION_DETAILS_SETTINGS -d $DATA>/dev/null +echo 设置allow-external-app为\`true' Setup allow-external-app to \`true\' +fl=/data/data/com.termux/files/home/.termux/termux.properties +if [ -f $fl ];then +awk '/^#/{print;next }/^\s*allow-external-apps/{gsub(/allow-external-apps.*/,"allow-external-apps=true");found=1}{print $0}END{if(!found)print "allow-external-apps=true"}' $fl>$TMPDIR/a.tmp && mv $TMPDIR/a.tmp $fl +else +mkdir -p `dirname $fl` +echo 'allow-external-apps=true'>$fl +fi +echo 安装Clang Install Clang +pkg i clang -y +apt autoremove --purge +apt clean +echo ok diff --git a/app/src/main/java/cn/rbc/termuc/Application.java b/app/src/main/java/cn/rbc/termuc/Application.java index 1f4de60..3dd888f 100644 --- a/app/src/main/java/cn/rbc/termuc/Application.java +++ b/app/src/main/java/cn/rbc/termuc/Application.java @@ -22,6 +22,7 @@ public class Application extends android.app.Application KEY_TEXTSIZE = "textsize", KEY_SHOW_HIDDEN = "showhidden", KEY_CHECKAPP = "checkapp", + KEY_INITAPP = "initapp", KEY_CFLAGS = "cflags", KEY_COMPLETION = "completion", KEY_LSP_HOST = "lsphost", @@ -50,83 +51,4 @@ private void initConfs() { lsp_host = sp.getString(KEY_LSP_HOST, "127.0.0.1"); lsp_port = Integer.parseInt(sp.getString(KEY_LSP_PORT, "48455")); } - - public static void testApp(Activity ctx, boolean manually) { - PackageManager pm = ctx.getPackageManager(); - try { - pm.getPackageInfo("com.termux", PackageManager.GET_GIDS); - if (manually) - HelperUtils.show(Toast.makeText(ctx, R.string.installed, Toast.LENGTH_SHORT)); - } catch (PackageManager.NameNotFoundException e) { - Builder bd = new Builder(ctx); - bd.setTitle(R.string.install_app); - bd.setMessage(R.string.confirm_install); - bd.setNegativeButton(android.R.string.cancel, null); - Install oc = new Install(ctx); - bd.setPositiveButton(android.R.string.ok, oc); - if (!manually) - bd.setNeutralButton(R.string.no_remind, oc); - bd.create().show(); - } - } - - private static class Install - implements DialogInterface.OnClickListener, SimpleAdapter.ViewBinder { - Activity mApp; - Install(Activity app) { - mApp = app; - } - public boolean setViewValue(View v, Object o, String k) { - if (v instanceof ImageView && o instanceof Drawable) { - ((ImageView)v).setImageDrawable((Drawable)o); - return true; - } - return false; - } - public void onClick(DialogInterface d, int p) { - Activity app = mApp; - if (p==DialogInterface.BUTTON_NEUTRAL) { - app.getPreferences(MODE_PRIVATE).edit().putBoolean(MainActivity.TESTAPP, false).commit(); - return; - } - Uri uri = Uri.parse("market://details?id=com.termux"); - Intent it = new Intent(Intent.ACTION_VIEW, uri); - PackageManager pm = app.getPackageManager(); - List lst = pm.queryIntentActivities(it, 0); - List> list = new ArrayList<>(); - Map m; - final Intent[] its = new Intent[lst.size()+2]; - int i = 0; - for (ResolveInfo ri:lst) { - m = new ArrayMap<>(); - m.put("i", ri.loadIcon(pm)); - m.put("n", ri.loadLabel(pm)); - list.add(m); - it = new Intent(Intent.ACTION_VIEW, uri); - it.setPackage(ri.activityInfo.packageName); - its[i++] = it; - } - m = new ArrayMap<>(); - m.put("i", null); - m.put("n", "Github Release website"); - list.add(m); - its[i++] = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/termux/termux-app/releases")); - m = new ArrayMap<>(); - m.put("i", null); - m.put("n", "F-Droid website"); - list.add(m); - its[i] = new Intent(Intent.ACTION_VIEW, Uri.parse("https://f-droid.org/packages/com.termux")); - Builder bd = new Builder(app); - bd.setTitle(R.string.install_via); - bd.setNegativeButton(android.R.string.cancel, null); - SimpleAdapter sadp = new SimpleAdapter(app, list, R.layout.file_item, new String[]{"i", "n"}, new int[]{R.id.file_icon, R.id.file_name}); - sadp.setViewBinder(this); - bd.setAdapter(sadp, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface d, int p) { - mApp.startActivity(its[p]); - } - }); - bd.create().show(); - } - } } diff --git a/app/src/main/java/cn/rbc/termuc/EditFragment.java b/app/src/main/java/cn/rbc/termuc/EditFragment.java index 8ffa020..b05baba 100644 --- a/app/src/main/java/cn/rbc/termuc/EditFragment.java +++ b/app/src/main/java/cn/rbc/termuc/EditFragment.java @@ -16,7 +16,7 @@ import android.util.TypedValue; public class EditFragment extends Fragment -implements OnTextChangeListener, DialogInterface.OnClickListener, Formatter, Runnable +implements OnTextChangeListener, DialogInterface.OnClickListener, Formatter { public final static int TYPE_C = 1; public final static int TYPE_CPP = 2; @@ -119,7 +119,7 @@ public CharSequence format(CharSequence txt, int width) { } private int mVer; - private long mSendTime; + //private long mSendTime; public void onChanged(CharSequence c, int start, int ver, boolean ins, boolean typ) { TextEditor editor = ed; @@ -151,29 +151,26 @@ public void onChanged(CharSequence c, int start, int ver, boolean ins, boolean t } range.msg = (String)c; changes.add(range); - //lastStr = (String)c; - //if (lastVer != ver) { + //HelperUtils.show(Toast.makeText(getContext()), text.isBatchEdit(), + //if (text.isBatchEdit()) Lsp lsp = MainActivity.lsp; lsp.didChange(fl, ver, changes); - //lastStart = s; - //lastVer = ver; // when inserting text and typing, call for completion if (ins && typ && c.length()==1) lsp.completionTry(fl, range.enl, range.enc+1, c.charAt(0)); changes.clear(); mVer = ver; - mSendTime = System.currentTimeMillis(); - editor.postDelayed(this, 1000L); - //} + //mSendTime = System.currentTimeMillis(); + //editor.postDelayed(this, 1000L); } - +/* public void run() { Lsp lsp = MainActivity.lsp; if (lsp.lastReceivedTime() hda; private FileAdapter adp; private EditFragment lastFrag = null; @@ -106,16 +107,21 @@ protected void onCreate(Bundle savedInstanceState) { l.setOnItemClickListener(this); l.setOnItemLongClickListener(this); mSearchAction = new SearchAction(this); - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { + int sdk = android.os.Build.VERSION.SDK_INT; + if (sdk >= android.os.Build.VERSION_CODES.R && !Environment.isExternalStorageManager()) { + Intent it = new Intent(); + it.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); + it.setData(Uri.parse("package:"+getPackageName())); + startActivityForResult(it, ACCESS_FILE); + } else if (sdk >= android.os.Build.VERSION_CODES.M) requestPermissions(new String[]{ android.Manifest.permission.READ_EXTERNAL_STORAGE, - android.Manifest.permission.WRITE_EXTERNAL_STORAGE, - android.Manifest.permission.MANAGE_EXTERNAL_STORAGE + android.Manifest.permission.WRITE_EXTERNAL_STORAGE }, PackageManager.PERMISSION_GRANTED); - } - if (!pref.getBoolean(TESTAPP, true)) - return; - Application.testApp(this, false); + if (pref.getBoolean(TESTAPP, true)) + Utils.testApp(this, false); + if (pref.getBoolean(INITAPP, true)) + Utils.initBack(this, false); } @Override @@ -123,9 +129,10 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PackageManager.PERMISSION_GRANTED && grantResults[0] == requestCode - && grantResults[1] == requestCode - && grantResults[2] == requestCode) + && grantResults[1] == requestCode) refresh(); + else + toast(getText(R.string.request_failed)); } private void refresh() { @@ -412,7 +419,8 @@ protected void onResume() { @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - if (requestCode == SETTING) { + switch (requestCode) { + case SETTING: if (resultCode == RESULT_OK) { FragmentManager fm = getFragmentManager(); for (int i=getActionBar().getNavigationItemCount() - 1;i >= 0;i--) { @@ -425,6 +433,13 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { } else if (resultCode == RESULT_FIRST_USER) { recreate(); } + break; + case ACCESS_FILE: + if (resultCode == RESULT_OK) + refresh(); + else + toast(getText(R.string.request_failed)); + break; } } diff --git a/app/src/main/java/cn/rbc/termuc/SettingsActivity.java b/app/src/main/java/cn/rbc/termuc/SettingsActivity.java index 6e373be..497ad0e 100644 --- a/app/src/main/java/cn/rbc/termuc/SettingsActivity.java +++ b/app/src/main/java/cn/rbc/termuc/SettingsActivity.java @@ -36,6 +36,7 @@ protected void onCreate(Bundle savedInstanceState) { mHost = (EditTextPreference)findPreference(Application.KEY_LSP_HOST); mPort = (EditTextPreference)findPreference(Application.KEY_LSP_PORT); findPreference(Application.KEY_CHECKAPP).setOnPreferenceClickListener(this); + findPreference(Application.KEY_INITAPP).setOnPreferenceClickListener(this); mDark = Application.dark_mode; mWrap = Application.wordwrap; @@ -55,7 +56,10 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public boolean onPreferenceClick(Preference p1) { - Application.testApp(this, true); + if (Application.KEY_CHECKAPP.equals(p1.getKey())) + Utils.testApp(this, true); + else + Utils.initBack(this, true); return true; } diff --git a/app/src/main/java/cn/rbc/termuc/Utils.java b/app/src/main/java/cn/rbc/termuc/Utils.java index 9f9789a..2b88a18 100644 --- a/app/src/main/java/cn/rbc/termuc/Utils.java +++ b/app/src/main/java/cn/rbc/termuc/Utils.java @@ -5,6 +5,14 @@ import java.nio.charset.*; import android.util.*; import java.util.*; +import android.widget.*; +import android.app.*; +import android.view.*; +import android.graphics.drawable.*; +import android.net.*; +import android.content.pm.*; +import cn.rbc.codeeditor.util.*; +import android.app.AlertDialog.Builder; public class Utils { public final static File ROOT = Environment.getExternalStorageDirectory(); @@ -12,16 +20,16 @@ public class Utils { private final static String PREFC = "com.termux.RUN_COMMAND_"; public static void run(Context cont, String cmd, String[] args, String pwd, boolean background) { - Intent intent = new Intent() - .setClassName("com.termux", "com.termux.app.RunCommandService") - .setAction("com.termux.RUN_COMMAND") - .putExtra(new StringBuilder(PREFC).append("PATH").toString(), cmd) - .putExtra(new StringBuilder(PREFC).append("RUNNER").toString(), "app-shell") - .putExtra(new StringBuilder(PREFC).append("ARGUMENTS").toString(), args) - .putExtra(new StringBuilder(PREFC).append("WORKDIR").toString(), pwd) - .putExtra(new StringBuilder(PREFC).append("BACKGROUND").toString(), background) - .putExtra(new StringBuilder(PREFC).append("SESSION_ACTION").toString(), "0"); - cont.startService(intent); + Intent it = new Intent(); + it.setClassName("com.termux", "com.termux.app.RunCommandService"); + it.setAction("com.termux.RUN_COMMAND"); + it.putExtra(new StringBuilder(PREFC).append("PATH").toString(), cmd); + it.putExtra(new StringBuilder(PREFC).append("RUNNER").toString(), "app-shell"); + it.putExtra(new StringBuilder(PREFC).append("ARGUMENTS").toString(), args); + it.putExtra(new StringBuilder(PREFC).append("WORKDIR").toString(), pwd); + it.putExtra(new StringBuilder(PREFC).append("BACKGROUND").toString(), background); + it.putExtra(new StringBuilder(PREFC).append("SESSION_ACTION").toString(), "0"); + cont.startService(it); } public static String escape(String str) { @@ -52,4 +60,129 @@ public static boolean removeFiles(File dir) { removeFiles(f); return dir.delete(); } + + public static void testApp(Activity ctx, boolean manually) { + PackageManager pm = ctx.getPackageManager(); + try { + pm.getPackageInfo("com.termux", PackageManager.GET_GIDS); + if (manually) + HelperUtils.show(Toast.makeText(ctx, R.string.installed, Toast.LENGTH_SHORT)); + } catch (PackageManager.NameNotFoundException e) { + Builder bd = new Builder(ctx); + bd.setTitle(R.string.install_app); + bd.setMessage(R.string.confirm_install); + bd.setNegativeButton(android.R.string.cancel, null); + Install oc = new Install(ctx); + bd.setPositiveButton(android.R.string.ok, oc); + if (!manually) + bd.setNeutralButton(R.string.no_remind, oc); + bd.create().show(); + } + } + + private static class Install + implements DialogInterface.OnClickListener, SimpleAdapter.ViewBinder { + Activity mApp; + Install(Activity app) { + mApp = app; + } + public boolean setViewValue(View v, Object o, String k) { + if (v instanceof ImageView && o instanceof Drawable) { + ((ImageView)v).setImageDrawable((Drawable)o); + return true; + } + return false; + } + public void onClick(DialogInterface d, int p) { + Activity app = mApp; + if (p==DialogInterface.BUTTON_NEUTRAL) { + app.getPreferences(Activity.MODE_PRIVATE).edit().putBoolean(MainActivity.TESTAPP, false).commit(); + return; + } + Uri uri = Uri.parse("market://details?id=com.termux"); + Intent it = new Intent(Intent.ACTION_VIEW, uri); + PackageManager pm = app.getPackageManager(); + List lst = pm.queryIntentActivities(it, 0); + List> list = new ArrayList<>(); + Map m; + final Intent[] its = new Intent[lst.size()+2]; + int i = 0; + for (ResolveInfo ri:lst) { + m = new ArrayMap<>(); + m.put("i", ri.loadIcon(pm)); + m.put("n", ri.loadLabel(pm)); + list.add(m); + it = new Intent(Intent.ACTION_VIEW, uri); + it.setPackage(ri.activityInfo.packageName); + its[i++] = it; + } + m = new ArrayMap<>(); + m.put("i", null); + m.put("n", "Github Release website"); + list.add(m); + its[i++] = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/termux/termux-app/releases")); + m = new ArrayMap<>(); + m.put("i", null); + m.put("n", "F-Droid website"); + list.add(m); + its[i] = new Intent(Intent.ACTION_VIEW, Uri.parse("https://f-droid.org/packages/com.termux")); + Builder bd = new Builder(app); + bd.setTitle(R.string.install_via); + bd.setNegativeButton(android.R.string.cancel, null); + SimpleAdapter sadp = new SimpleAdapter(app, list, R.layout.file_item, new String[]{"i", "n"}, new int[]{R.id.file_icon, R.id.file_name}); + sadp.setViewBinder(this); + bd.setAdapter(sadp, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface d, int p) { + mApp.startActivity(its[p]); + } + }); + bd.create().show(); + } + } + + public static void initBack(Activity ctx, boolean manually) { + Builder bd = new Builder(ctx); + bd.setTitle(R.string.init_termux); + bd.setMessage(R.string.init_inform); + Init it = new Init(ctx); + bd.setPositiveButton(R.string.copy_jump, it); + bd.setNegativeButton(android.R.string.cancel, null); + if (!manually) + bd.setNeutralButton(R.string.initialized, it); + bd.create().show(); + } + + public static void copyJump(Context ctx) { + ClipboardManager cm = (ClipboardManager)ctx.getSystemService(Context.CLIPBOARD_SERVICE); + try { + BufferedInputStream is = new BufferedInputStream(ctx.getAssets().open("init")); + StringBuilder sb = new StringBuilder(); + int i; + byte[] bt = new byte[1024]; + while ((i=is.read(bt))>0) + sb.append(new String(bt, 0, i)); + is.close(); + ClipData cd = ClipData.newPlainText("Label", sb.toString()); + cm.setPrimaryClip(cd); + Intent it = new Intent(Intent.ACTION_MAIN); + it.setPackage("com.termux"); + ctx.startActivity(it); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + + private static class Init implements DialogInterface.OnClickListener { + Activity mCtx; + public Init(Activity ctx) { + mCtx = ctx; + } + public void onClick(DialogInterface p1, int p2) { + if (p2 == DialogInterface.BUTTON_POSITIVE) { + copyJump(mCtx); + } else { + mCtx.getPreferences(Activity.MODE_PRIVATE).edit().putBoolean(MainActivity.INITAPP, false).commit(); + } + } + } } diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 11e7379..f0199c2 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -48,4 +48,9 @@ 未检测到 Termux,是否现在安装? 不再提醒 安装途径 + 初始化 Termux + 为完成配置,请复制指令并跳转 Termux 粘贴运行。\n运行时需要在所有系统设置页面手动为 Termux 配置权限。 + 复制并跳转 + 已配置 + 申请权限失败 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1bbee47..85f6c01 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -48,6 +48,11 @@ Termux is not detected. Do you want install it now? Never remind Install via + Initialize Termux + To complete the configuration, please copy the instructions and jump to Termux paste run.\nDuring runtime, it is necessary to manually configure permissions for Termux on all system settings pages. + Copy & jump + Initialized + Request permissions failed @string/lang_serv @string/local @@ -85,14 +90,4 @@ 31 32 - diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index 0e99029..64efce6 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -43,6 +43,10 @@ android:key="checkapp" android:title="@string/check_app" /> +