UI improvements

This commit is contained in:
dvdandroid 2016-08-23 11:39:18 +02:00
parent 5baa2e9069
commit 56f10e238b
12 changed files with 476 additions and 138 deletions

View File

@ -0,0 +1,181 @@
package com.topjohnwu.magisk;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.Switch;
import android.widget.TextView;
import com.topjohnwu.magisk.utils.Utils;
import java.io.File;
import butterknife.BindColor;
import butterknife.BindView;
import butterknife.ButterKnife;
public class MagiskFragment extends Fragment {
@BindView(R.id.rootSwitchView) View rootToggleView;
@BindView(R.id.root_toggle) Switch rootToggle;
@BindView(R.id.selinuxSwitchView) View selinuxToggleView;
@BindView(R.id.selinux_toggle) Switch selinuxToggle;
@BindView(R.id.magisk_status_container) View magiskStatusContainer;
@BindView(R.id.magisk_status_icon) ImageView magiskStatusIcon;
@BindView(R.id.magisk_version) TextView magiskVersion;
@BindView(R.id.root_status_container) View rootStatusContainer;
@BindView(R.id.root_status_icon) ImageView rootStatusIcon;
@BindView(R.id.root_status) TextView rootStatus;
@BindView(R.id.selinux_status_container) View selinuxStatusContainer;
@BindView(R.id.selinux_status_icon) ImageView selinuxStatusIcon;
@BindView(R.id.selinux_status) TextView selinuxStatus;
@BindView(R.id.safety_net_status) TextView safetyNetStatus;
@BindView(R.id.safety_net_icon) ImageView safetyNetStatusIcon;
@BindColor(R.color.red500) int red500;
@BindColor(R.color.green500) int green500;
@BindColor(R.color.grey500) int grey500;
int statusOK = R.drawable.ic_check_circle;
int statusError = R.drawable.ic_error;
int statusUnknown = R.drawable.ic_help;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.magisk_fragment, container, false);
ButterKnife.bind(this, view);
updateStatus();
rootToggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
Utils.su(b ? "setprop magisk.root 1" : "setprop magisk.root 0");
updateStatus();
}
});
selinuxToggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
Utils.su(b ? "setenforce 1" : "setenforce 0");
updateStatus();
}
});
new android.os.Handler().postDelayed(new Runnable() {
@Override
public void run() {
updateStatus(); // update status again
}
}, 1000);
return view;
}
private void updateStatus() {
String selinux = Utils.sh("getenforce");
String version = Utils.sh("getprop magisk.version");
if (TextUtils.isEmpty(version)) {
magiskStatusContainer.setBackgroundColor(grey500);
magiskStatusIcon.setImageResource(statusUnknown);
magiskVersion.setTextColor(grey500);
magiskVersion.setText("?");
} else {
magiskStatusContainer.setBackgroundColor(green500);
magiskStatusIcon.setImageResource(statusOK);
magiskVersion.setTextColor(green500);
magiskVersion.setText(getString(R.string.magisk_version, version));
}
if (selinux.equals("Enforcing")) {
selinuxStatusContainer.setBackgroundColor(green500);
selinuxStatusIcon.setImageResource(statusOK);
selinuxStatus.setText(R.string.selinux_enforcing_info);
selinuxStatus.setTextColor(green500);
selinuxToggle.setChecked(true);
} else {
selinuxStatusContainer.setBackgroundColor(red500);
selinuxStatusIcon.setImageResource(statusError);
selinuxStatus.setText(R.string.selinux_permissive_info);
selinuxStatus.setTextColor(red500);
selinuxToggle.setChecked(false);
}
if (new File("/system/framework/twframework.jar").exists()) {
selinuxToggleView.setVisibility(View.GONE);
selinuxStatus.append("\n" + getString(R.string.selinux_samsung));
}
if (new File("/system/xbin/su").exists()) {
rootStatusContainer.setBackgroundColor(red500);
rootStatusIcon.setImageResource(statusError);
rootStatus.setTextColor(red500);
rootToggle.setChecked(true);
safetyNetStatusIcon.setImageResource(statusError);
if (!Utils.rootAccess) {
rootStatusContainer.setBackgroundColor(red500);
rootStatusIcon.setImageResource(statusError);
rootStatus.setTextColor(red500);
rootStatus.setText(R.string.root_system);
rootToggleView.setVisibility(View.GONE);
selinuxToggleView.setVisibility(View.GONE);
safetyNetStatus.setText(R.string.root_system_info);
} else {
rootStatusContainer.setBackgroundColor(green500);
rootStatusIcon.setImageResource(statusOK);
rootStatus.setTextColor(green500);
rootStatus.setText(R.string.root_mounted);
safetyNetStatus.setText(R.string.root_mounted_info);
}
} else {
rootStatusContainer.setBackgroundColor(green500);
rootStatusIcon.setImageResource(red500);
rootStatus.setTextColor(green500);
rootToggle.setChecked(false);
safetyNetStatusIcon.setImageResource(statusOK);
if (!Utils.rootAccess) {
rootStatusContainer.setBackgroundColor(red500);
rootStatusIcon.setImageResource(statusError);
rootStatus.setTextColor(red500);
rootStatus.setText(R.string.root_none);
rootToggleView.setVisibility(View.GONE);
selinuxToggleView.setVisibility(View.GONE);
safetyNetStatusIcon.setImageResource(statusError);
safetyNetStatus.setText(R.string.root_none_info);
} else {
rootStatus.setText(R.string.root_unmounted);
safetyNetStatus.setText(R.string.root_unmounted_info);
}
}
}
}

View File

@ -1,112 +1,7 @@
package com.topjohnwu.magisk;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Utils;
import java.io.File;
public class RootFragment extends Fragment {
private Switch rootToggle, selinuxToggle;
private TextView magiskVersion, rootStatus, selinuxStatus, safetyNet, permissive;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.root_fragment, container, false);
magiskVersion = (TextView) view.findViewById(R.id.magisk_version);
rootToggle = (Switch) view.findViewById(R.id.root_toggle);
selinuxToggle = (Switch) view.findViewById(R.id.selinux_toggle);
rootStatus = (TextView) view.findViewById(R.id.root_status);
selinuxStatus = (TextView) view.findViewById(R.id.selinux_status);
safetyNet = (TextView) view.findViewById(R.id.safety_net);
permissive = (TextView) view.findViewById(R.id.permissive);
updateStatus();
rootToggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
Utils.su(b ? "setprop magisk.root 1" : "setprop magisk.root 0");
updateStatus();
}
});
selinuxToggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
Utils.su(b ? "setenforce 1" : "setenforce 0");
updateStatus();
}
});
return view;
}
private void updateStatus() {
String selinux = Utils.sh("getenforce");
String version = Utils.sh("getprop magisk.version");
magiskVersion.setText(getString(R.string.magisk_version, version));
selinuxStatus.setText(selinux);
if (selinux.equals("Enforcing")) {
selinuxStatus.setTextColor(Color.GREEN);
selinuxToggle.setChecked(true);
permissive.setText(R.string.selinux_enforcing_info);
permissive.setTextColor(Color.GREEN);
} else {
selinuxStatus.setTextColor(Color.RED);
selinuxToggle.setChecked(false);
permissive.setText(R.string.selinux_permissive_info);
permissive.setTextColor(Color.RED);
}
if (new File("/system/framework/twframework.jar").exists()) {
selinuxToggle.setEnabled(false);
permissive.setText(R.string.selinux_samsung);
}
if (new File("/system/xbin/su").exists()) {
rootStatus.setTextColor(Color.RED);
safetyNet.setTextColor(Color.RED);
rootToggle.setChecked(true);
if (!Utils.rootAccess) {
rootStatus.setText(R.string.root_system);
safetyNet.setText(R.string.root_system_info);
rootToggle.setEnabled(false);
selinuxToggle.setEnabled(false);
} else {
rootStatus.setText(R.string.root_mounted);
safetyNet.setText(R.string.root_mounted_info);
}
} else {
rootStatus.setTextColor(Color.GREEN);
safetyNet.setTextColor(Color.GREEN);
rootToggle.setChecked(false);
if (!Utils.rootAccess) {
rootStatus.setText(R.string.root_none);
safetyNet.setText(R.string.root_none_info);
rootToggle.setEnabled(false);
selinuxToggle.setEnabled(false);
} else {
rootStatus.setText(R.string.root_unmounted);
safetyNet.setText(R.string.root_unmounted_info);
}
}
}
}

View File

@ -26,39 +26,15 @@ import butterknife.ButterKnife;
public class WelcomeActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
private static final String SELECTED_ITEM_ID = "SELECTED_ITEM_ID";
private final Handler mDrawerHandler = new Handler();
public static Init initialize;
public static View view;
private final Handler mDrawerHandler = new Handler();
@BindView(R.id.toolbar) Toolbar toolbar;
@BindView(R.id.drawer_layout) DrawerLayout drawer;
@BindView(R.id.nav_view) NavigationView navigationView;
@IdRes
private int mSelectedId = R.id.modules;// for now
public static class Init extends AsyncTask<Void, Integer, Void> {
@Override
protected Void doInBackground(Void... voids) {
// Check root access
Utils.checkRoot();
// Permission for java code to read /cache files
if (Utils.rootAccess) {
Utils.su("chmod 755 /cache", "chmod 644 /cache/magisk.log");
}
return null;
}
@Override
protected void onPostExecute(Void v) {
super.onPostExecute(v);
if (!Utils.rootAccess) {
Snackbar.make(view, R.string.no_root_access, Snackbar.LENGTH_LONG).show();
}
}
}
private int mSelectedId = R.id.magisk;
@Override
protected void onCreate(final Bundle savedInstanceState) {
@ -73,7 +49,6 @@ public class WelcomeActivity extends AppCompatActivity implements NavigationView
initialize.execute();
setSupportActionBar(toolbar);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) {
@ -143,6 +118,10 @@ public class WelcomeActivity extends AppCompatActivity implements NavigationView
private void navigate(final int itemId) {
Fragment navFragment = null;
switch (itemId) {
case R.id.magisk:
setTitle(R.string.magisk);
navFragment = new MagiskFragment();
break;
case R.id.root:
setTitle(R.string.root);
navFragment = new RootFragment();
@ -168,4 +147,27 @@ public class WelcomeActivity extends AppCompatActivity implements NavigationView
}
}
}
public static class Init extends AsyncTask<Void, Integer, Void> {
@Override
protected Void doInBackground(Void... voids) {
// Check root access
Utils.checkRoot();
// Permission for java code to read /cache files
if (Utils.rootAccess) {
Utils.su("chmod 755 /cache", "chmod 644 /cache/magisk.log");
}
return null;
}
@Override
protected void onPostExecute(Void v) {
super.onPostExecute(v);
if (!Utils.rootAccess) {
Snackbar.make(view, R.string.no_root_access, Snackbar.LENGTH_LONG).show();
}
}
}
}

View File

@ -66,7 +66,7 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
module.deleteRemoveFile();
holder.warning.setVisibility(module.willBeRemoved() ? View.VISIBLE : View.GONE);
return false;
return true;
}
});

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#fff"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#fff"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-2h2v2zM13,13h-2L11,7h2v6z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#fff"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,19h-2v-2h2v2zM15.07,11.25l-0.9,0.92C13.45,12.9 13,13.5 13,15h-2v-0.5c0,-1.1 0.45,-2.1 1.17,-2.83l1.24,-1.26c0.37,-0.36 0.59,-0.86 0.59,-1.41 0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2L8,9c0,-2.21 1.79,-4 4,-4s4,1.79 4,4c0,0.88 -0.36,1.68 -0.93,2.25z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="512.0"
android:viewportWidth="512.0">
<path
android:fillAlpha="1.00"
android:fillColor="#757575"
android:pathData="M115.3,44.4C118.4,43.8 121.4,45.2 123.2,47.7C129.2,55.3 132.3,64.9 139.5,71.5C153.7,86.7 171.8,98.8 180.8,118.1C186.7,130.3 188.5,143.8 192.4,156.6C194.2,162.9 201.7,163.3 207.1,162.8C227.7,161.1 248.4,159.2 269,161.4C279.3,161 289.6,162.1 300,162.7C304,162.8 309.1,162.1 310.8,157.9C314.8,147.3 315.4,135.8 319.1,125.1C326.4,104.6 343.2,90 359,76C366.7,69.2 371.1,59.7 375.9,50.8C377.7,47 382,44 386.4,45.6C390.7,49 391.2,54.9 392.2,60C394.5,79.2 397.6,98.6 394.8,118C394,129 391.4,140.4 384.2,149.1C380,155.7 371.5,160.1 371.7,168.7C369.7,193.1 372.1,217.6 372.4,242C372.4,258.3 372.7,274.7 372.4,291C370.5,304.6 372.9,318.4 370.7,332C371.1,338.8 370,345.8 367.1,352C355,372.9 336.9,389.2 321.1,407.1C314.7,413.8 313,423.2 309.4,431.4C304.4,442.5 298.9,454.5 288.6,461.6C278.7,466 267.9,469 257,469.7C242.9,469.1 228.8,466.6 215.7,461.3C211.7,457.9 208.2,453.9 205.4,449.5C202.8,439 198.2,429 194.2,418.9C191.8,412.2 185.6,408.1 181.4,402.5C172.4,392.9 163.1,383.5 154.1,373.9C145.2,363.4 135.3,351.6 135.2,337C132.4,317.5 133.9,297.6 132.6,278C132.6,245.3 132.8,212.6 132.2,180C131,174.5 133,168.2 129.5,163.4C125.3,156.8 118.6,152.2 114.8,145.3C108.7,135.7 107.1,124.2 105.6,113.1C104.1,94 106.1,74.8 109.9,56C111.2,52.1 111.6,46.8 115.3,44.4Z"/>
</vector>

View File

@ -0,0 +1,214 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="8dp"
android:layout_marginTop="?attr/actionBarSize">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:id="@+id/rootSwitchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="2dp"
app:cardCornerRadius="0dp">
<Switch
android:id="@+id/root_toggle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="12dp"
android:checked="true"
android:text="@string/root_toggle"
android:textSize="16sp"/>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:id="@+id/selinuxSwitchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:elevation="2dp"
app:cardCornerRadius="0dp">
<Switch
android:id="@+id/selinux_toggle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="12dp"
android:checked="true"
android:text="@string/selinux_toggle"
android:textSize="16sp"/>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:layout_marginTop="6dp"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout
android:id="@+id/magisk_status_container"
android:layout_width="match_parent"
android:layout_height="100dp"
android:foregroundGravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/magisk_status_icon"
android:layout_width="84dp"
android:layout_height="84dp"
android:layout_gravity="center"/>
</FrameLayout>
<TextView
android:id="@+id/magisk_version"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:padding="6dp"
android:textStyle="bold"/>
</LinearLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:layout_marginTop="6dp"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout
android:id="@+id/root_status_container"
android:layout_width="match_parent"
android:layout_height="100dp"
android:foregroundGravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/root_status_icon"
android:layout_width="84dp"
android:layout_height="84dp"
android:layout_gravity="center"/>
</FrameLayout>
<TextView
android:id="@+id/root_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:padding="6dp"
android:textStyle="bold"/>
</LinearLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:layout_marginTop="6dp"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="4dp">
<ImageView
android:id="@+id/safety_net_icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:tint="#757575"/>
<TextView
android:id="@+id/safety_net_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="6dp"
android:textStyle="bold"/>
</LinearLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:layout_marginTop="6dp"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout
android:id="@+id/selinux_status_container"
android:layout_width="match_parent"
android:layout_height="100dp"
android:foregroundGravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/selinux_status_icon"
android:layout_width="84dp"
android:layout_height="84dp"
android:layout_gravity="center"/>
</FrameLayout>
<TextView
android:id="@+id/selinux_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:padding="6dp"
android:textStyle="bold"/>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
</ScrollView>

View File

@ -3,6 +3,11 @@
<group android:checkableBehavior="single">
<item
android:id="@+id/magisk"
android:icon="@drawable/magisk"
android:title="@string/magisk"/>
<item
android:id="@+id/root"
android:icon="@drawable/root"

View File

@ -9,6 +9,9 @@
<color name="secondary_text">#757575</color>
<color name="icons">#FFFFFF</color>
<color name="divider">#BDBDBD</color>
<color name="red500">#F44336</color>
<color name="green500">#4CAF50</color>
<color name="grey500">#9E9E9E</color>
</resources>

View File

@ -1,17 +1,17 @@
<resources>
<string name="app_name">Magisk Manager</string>
<string name="root_mounted">Mounted</string>
<string name="root_mounted">Root mounted</string>
<string name="root_mounted_info">Root mounted and enabled. Safety Net (Android Pay) will NOT work</string>
<string name="root_unmounted">Not Mounted</string>
<string name="root_unmounted">Root not mounted</string>
<string name="root_unmounted_info">Safety Net (Android Pay) should work, but no root temporarily</string>
<string name="selinux_enforcing_info">SELinux is enforced</string>
<string name="selinux_permissive_info">Only turn off SELinux if necessary!</string>
<string name="selinux_permissive_info">SELinux is permissive\nOnly turn off SELinux if necessary!</string>
<string name="unavailable">(unavailable)</string>
<string name="magisk_label">Boot Version:</string>
<string name="root_label">Root Status:</string>
<string name="selinux_label">Selinux Status:</string>
<string name="selinux_label">SeLinux is %s</string>
<string name="root_toggle">Root Toggle</string>
<string name="selinux_toggle">Selinux Toggle</string>
<string name="selinux_toggle">SeLinux Toggle</string>
<string name="root_system">Improperly Installed</string>
<string name="root_system_info">Root improperly installed. Safety Net (Android Pay) will NOT work, and impossible to toggle</string>
<string name="root_none">Not Rooted</string>
@ -42,5 +42,6 @@
<string name="logs_save_failed">Could not write log to SD card:</string>
<string name="permissionNotGranted">This feature will not work without permission to write external storage.</string>
<string name="disable_file_removed">Module will be enabled at next reboot</string>
<string name="magisk">Magisk</string>
</resources>