mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-24 19:47:38 +00:00
Move settings out of separate Activity
This commit is contained in:
parent
0c247110a0
commit
5c483745ff
@ -28,9 +28,6 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".AboutActivity"
|
android:name=".AboutActivity"
|
||||||
android:theme="@style/AppTheme.StatusBar" />
|
android:theme="@style/AppTheme.StatusBar" />
|
||||||
<activity
|
|
||||||
android:name=".SettingsActivity"
|
|
||||||
android:theme="@style/AppTheme.StatusBar" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".FlashActivity"
|
android:name=".FlashActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||||
|
@ -185,8 +185,7 @@ public class MainActivity extends BaseActivity
|
|||||||
displayFragment(new LogFragment(), false);
|
displayFragment(new LogFragment(), false);
|
||||||
break;
|
break;
|
||||||
case R.id.settings:
|
case R.id.settings:
|
||||||
startActivity(new Intent(this, SettingsActivity.class));
|
displayFragment(new SettingsFragment(), true);
|
||||||
mDrawerItem = bak;
|
|
||||||
break;
|
break;
|
||||||
case R.id.app_about:
|
case R.id.app_about:
|
||||||
startActivity(new Intent(this, AboutActivity.class));
|
startActivity(new Intent(this, AboutActivity.class));
|
||||||
|
@ -1,401 +0,0 @@
|
|||||||
package com.topjohnwu.magisk;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.content.res.TypedArray;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.hardware.fingerprint.FingerprintManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.support.v14.preference.SwitchPreference;
|
|
||||||
import android.support.v7.app.ActionBar;
|
|
||||||
import android.support.v7.app.AlertDialog;
|
|
||||||
import android.support.v7.preference.ListPreference;
|
|
||||||
import android.support.v7.preference.Preference;
|
|
||||||
import android.support.v7.preference.PreferenceCategory;
|
|
||||||
import android.support.v7.preference.PreferenceFragmentCompat;
|
|
||||||
import android.support.v7.preference.PreferenceScreen;
|
|
||||||
import android.support.v7.widget.Toolbar;
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.asyncs.CheckUpdates;
|
|
||||||
import com.topjohnwu.magisk.asyncs.PatchAPK;
|
|
||||||
import com.topjohnwu.magisk.components.BaseActivity;
|
|
||||||
import com.topjohnwu.magisk.components.CustomAlertDialog;
|
|
||||||
import com.topjohnwu.magisk.receivers.DownloadReceiver;
|
|
||||||
import com.topjohnwu.magisk.utils.Download;
|
|
||||||
import com.topjohnwu.magisk.utils.FingerprintHelper;
|
|
||||||
import com.topjohnwu.magisk.utils.LocaleManager;
|
|
||||||
import com.topjohnwu.magisk.utils.RootUtils;
|
|
||||||
import com.topjohnwu.magisk.utils.Topic;
|
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
|
||||||
import com.topjohnwu.superuser.Shell;
|
|
||||||
import com.topjohnwu.superuser.ShellUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import butterknife.BindView;
|
|
||||||
import butterknife.ButterKnife;
|
|
||||||
|
|
||||||
public class SettingsActivity extends BaseActivity implements Topic.Subscriber {
|
|
||||||
|
|
||||||
@BindView(R.id.toolbar) Toolbar toolbar;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getDarkTheme() {
|
|
||||||
return R.style.AppTheme_StatusBar_Dark;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_settings);
|
|
||||||
ButterKnife.bind(this);
|
|
||||||
|
|
||||||
setSupportActionBar(toolbar);
|
|
||||||
|
|
||||||
toolbar.setNavigationOnClickListener(view -> finish());
|
|
||||||
|
|
||||||
ActionBar ab = getSupportActionBar();
|
|
||||||
if (ab != null) {
|
|
||||||
ab.setTitle(R.string.settings);
|
|
||||||
ab.setDisplayHomeAsUpEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
setFloating();
|
|
||||||
|
|
||||||
if (savedInstanceState == null) {
|
|
||||||
getSupportFragmentManager().beginTransaction().add(R.id.container, new SettingsFragment()).commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[] getSubscribedTopics() {
|
|
||||||
return new int[] {Topic.RELOAD_ACTIVITY};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPublish(int topic, Object[] result) {
|
|
||||||
recreate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SettingsFragment extends PreferenceFragmentCompat
|
|
||||||
implements SharedPreferences.OnSharedPreferenceChangeListener,
|
|
||||||
Topic.Subscriber, Topic.AutoSubscriber {
|
|
||||||
|
|
||||||
private PreferenceScreen prefScreen;
|
|
||||||
|
|
||||||
private ListPreference updateChannel, suAccess, autoRes, suNotification,
|
|
||||||
requestTimeout, multiuserMode, namespaceMode;
|
|
||||||
private MagiskManager mm;
|
|
||||||
private PreferenceCategory generalCatagory;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
|
||||||
setPreferencesFromResource(R.xml.app_settings, rootKey);
|
|
||||||
mm = Data.MM();
|
|
||||||
prefScreen = getPreferenceScreen();
|
|
||||||
|
|
||||||
generalCatagory = (PreferenceCategory) findPreference("general");
|
|
||||||
PreferenceCategory magiskCategory = (PreferenceCategory) findPreference("magisk");
|
|
||||||
PreferenceCategory suCategory = (PreferenceCategory) findPreference("superuser");
|
|
||||||
Preference hideManager = findPreference("hide");
|
|
||||||
Preference restoreManager = findPreference("restore");
|
|
||||||
findPreference("clear").setOnPreferenceClickListener((pref) -> {
|
|
||||||
mm.prefs.edit().remove(Const.Key.ETAG_KEY).apply();
|
|
||||||
mm.repoDB.clearRepo();
|
|
||||||
Utils.toast(R.string.repo_cache_cleared, Toast.LENGTH_SHORT);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
updateChannel = (ListPreference) findPreference(Const.Key.UPDATE_CHANNEL);
|
|
||||||
suAccess = (ListPreference) findPreference(Const.Key.ROOT_ACCESS);
|
|
||||||
autoRes = (ListPreference) findPreference(Const.Key.SU_AUTO_RESPONSE);
|
|
||||||
requestTimeout = (ListPreference) findPreference(Const.Key.SU_REQUEST_TIMEOUT);
|
|
||||||
suNotification = (ListPreference) findPreference(Const.Key.SU_NOTIFICATION);
|
|
||||||
multiuserMode = (ListPreference) findPreference(Const.Key.SU_MULTIUSER_MODE);
|
|
||||||
namespaceMode = (ListPreference) findPreference(Const.Key.SU_MNT_NS);
|
|
||||||
SwitchPreference reauth = (SwitchPreference) findPreference(Const.Key.SU_REAUTH);
|
|
||||||
SwitchPreference fingerprint = (SwitchPreference) findPreference(Const.Key.SU_FINGERPRINT);
|
|
||||||
|
|
||||||
updateChannel.setOnPreferenceChangeListener((p, o) -> {
|
|
||||||
String prev =String.valueOf(Data.updateChannel);
|
|
||||||
int channel = Integer.parseInt((String) o);
|
|
||||||
if (channel == Const.Value.CUSTOM_CHANNEL) {
|
|
||||||
View v = LayoutInflater.from(requireActivity()).inflate(R.layout.custom_channel_dialog, null);
|
|
||||||
EditText url = v.findViewById(R.id.custom_url);
|
|
||||||
url.setText(mm.prefs.getString(Const.Key.CUSTOM_CHANNEL, ""));
|
|
||||||
new AlertDialog.Builder(requireActivity())
|
|
||||||
.setTitle(R.string.settings_update_custom)
|
|
||||||
.setView(v)
|
|
||||||
.setPositiveButton(R.string.ok, (d, i) ->
|
|
||||||
mm.prefs.edit().putString(Const.Key.CUSTOM_CHANNEL,
|
|
||||||
url.getText().toString()).apply())
|
|
||||||
.setNegativeButton(R.string.close, (d, i) ->
|
|
||||||
mm.prefs.edit().putString(Const.Key.UPDATE_CHANNEL, prev).apply())
|
|
||||||
.setOnCancelListener(d ->
|
|
||||||
mm.prefs.edit().putString(Const.Key.UPDATE_CHANNEL, prev).apply())
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
setSummary();
|
|
||||||
|
|
||||||
// Disable dangerous settings in secondary user
|
|
||||||
if (Const.USER_ID > 0) {
|
|
||||||
suCategory.removePreference(multiuserMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable re-authentication option on Android O, it will not work
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
reauth.setEnabled(false);
|
|
||||||
reauth.setChecked(false);
|
|
||||||
reauth.setSummary(R.string.android_o_not_support);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable fingerprint option if not possible
|
|
||||||
if (!FingerprintHelper.canUseFingerprint()) {
|
|
||||||
fingerprint.setEnabled(false);
|
|
||||||
fingerprint.setChecked(false);
|
|
||||||
fingerprint.setSummary(R.string.disable_fingerprint);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Data.magiskVersionCode >= Const.MAGISK_VER.MANAGER_HIDE) {
|
|
||||||
if (mm.getPackageName().equals(Const.ORIG_PKG_NAME)) {
|
|
||||||
hideManager.setOnPreferenceClickListener((pref) -> {
|
|
||||||
PatchAPK.hideManager(requireActivity());
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
generalCatagory.removePreference(restoreManager);
|
|
||||||
} else {
|
|
||||||
if (Download.checkNetworkStatus(mm)) {
|
|
||||||
restoreManager.setOnPreferenceClickListener((pref) -> {
|
|
||||||
Download.receive(
|
|
||||||
requireActivity(), new DownloadReceiver() {
|
|
||||||
@Override
|
|
||||||
public void onDownloadDone(Context context, Uri uri) {
|
|
||||||
Data.exportPrefs();
|
|
||||||
Shell.su("cp " + uri.getPath() + " /data/local/tmp/manager.apk").exec();
|
|
||||||
if (ShellUtils.fastCmdResult("pm install /data/local/tmp/manager.apk")) {
|
|
||||||
Shell.su("rm -f /data/local/tmp/manager.apk").exec();
|
|
||||||
RootUtils.uninstallPkg(context.getPackageName());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Shell.su("rm -f /data/local/tmp/manager.apk").exec();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Data.managerLink,
|
|
||||||
Utils.fmt("MagiskManager-v%s.apk", Data.remoteManagerVersionString)
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
generalCatagory.removePreference(restoreManager);
|
|
||||||
}
|
|
||||||
generalCatagory.removePreference(hideManager);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
generalCatagory.removePreference(restoreManager);
|
|
||||||
generalCatagory.removePreference(hideManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Shell.rootAccess() || (Const.USER_ID > 0 &&
|
|
||||||
Data.multiuserMode == Const.Value.MULTIUSER_MODE_OWNER_MANAGED)) {
|
|
||||||
prefScreen.removePreference(suCategory);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Shell.rootAccess()) {
|
|
||||||
prefScreen.removePreference(magiskCategory);
|
|
||||||
generalCatagory.removePreference(hideManager);
|
|
||||||
} else if (Data.magiskVersionCode < Const.MAGISK_VER.UNIFIED) {
|
|
||||||
prefScreen.removePreference(magiskCategory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setLocalePreference(ListPreference lp) {
|
|
||||||
CharSequence[] entries = new CharSequence[LocaleManager.locales.size() + 1];
|
|
||||||
CharSequence[] entryValues = new CharSequence[LocaleManager.locales.size() + 1];
|
|
||||||
entries[0] = LocaleManager.getString(LocaleManager.defaultLocale, R.string.system_default);
|
|
||||||
entryValues[0] = "";
|
|
||||||
int i = 1;
|
|
||||||
for (Locale locale : LocaleManager.locales) {
|
|
||||||
entries[i] = locale.getDisplayName(locale);
|
|
||||||
entryValues[i++] = locale.toLanguageTag();
|
|
||||||
}
|
|
||||||
lp.setEntries(entries);
|
|
||||||
lp.setEntryValues(entryValues);
|
|
||||||
lp.setSummary(LocaleManager.locale.getDisplayName(LocaleManager.locale));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
|
||||||
mm.prefs.registerOnSharedPreferenceChangeListener(this);
|
|
||||||
Topic.subscribe(this);
|
|
||||||
return super.onCreateView(inflater, container, savedInstanceState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyView() {
|
|
||||||
mm.prefs.unregisterOnSharedPreferenceChangeListener(this);
|
|
||||||
Topic.unsubscribe(this);
|
|
||||||
super.onDestroyView();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
|
|
||||||
switch (key) {
|
|
||||||
case Const.Key.ROOT_ACCESS:
|
|
||||||
case Const.Key.SU_MULTIUSER_MODE:
|
|
||||||
case Const.Key.SU_MNT_NS:
|
|
||||||
mm.mDB.setSettings(key, Utils.getPrefsInt(prefs, key));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Data.loadConfig();
|
|
||||||
setSummary();
|
|
||||||
switch (key) {
|
|
||||||
case Const.Key.DARK_THEME:
|
|
||||||
Topic.publish(false, Topic.RELOAD_ACTIVITY);
|
|
||||||
break;
|
|
||||||
case Const.Key.COREONLY:
|
|
||||||
if (prefs.getBoolean(key, false)) {
|
|
||||||
try {
|
|
||||||
Const.MAGISK_DISABLE_FILE.createNewFile();
|
|
||||||
} catch (IOException ignored) {}
|
|
||||||
} else {
|
|
||||||
Const.MAGISK_DISABLE_FILE.delete();
|
|
||||||
}
|
|
||||||
Utils.toast(R.string.settings_reboot_toast, Toast.LENGTH_LONG);
|
|
||||||
break;
|
|
||||||
case Const.Key.MAGISKHIDE:
|
|
||||||
if (prefs.getBoolean(key, false)) {
|
|
||||||
Shell.su("magiskhide --enable").submit();
|
|
||||||
} else {
|
|
||||||
Shell.su("magiskhide --disable").submit();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Const.Key.HOSTS:
|
|
||||||
if (prefs.getBoolean(key, false)) {
|
|
||||||
Shell.su("cp -af /system/etc/hosts " + Const.MAGISK_HOST_FILE,
|
|
||||||
"mount -o bind " + Const.MAGISK_HOST_FILE + " /system/etc/hosts")
|
|
||||||
.submit();
|
|
||||||
} else {
|
|
||||||
Shell.su("umount -l /system/etc/hosts",
|
|
||||||
"rm -f " + Const.MAGISK_HOST_FILE)
|
|
||||||
.submit();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Const.Key.LOCALE:
|
|
||||||
LocaleManager.setLocale(mm);
|
|
||||||
Topic.publish(false, Topic.RELOAD_ACTIVITY);
|
|
||||||
break;
|
|
||||||
case Const.Key.UPDATE_CHANNEL:
|
|
||||||
case Const.Key.CUSTOM_CHANNEL:
|
|
||||||
CheckUpdates.check();
|
|
||||||
break;
|
|
||||||
case Const.Key.CHECK_UPDATES:
|
|
||||||
Utils.setupUpdateCheck();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceTreeClick(Preference preference) {
|
|
||||||
String key = preference.getKey();
|
|
||||||
switch (key) {
|
|
||||||
case Const.Key.SU_FINGERPRINT:
|
|
||||||
boolean checked = ((SwitchPreference) preference).isChecked();
|
|
||||||
((SwitchPreference) preference).setChecked(!checked);
|
|
||||||
CustomAlertDialog dialog = new CustomAlertDialog(requireActivity());
|
|
||||||
CustomAlertDialog.ViewHolder vh = dialog.getViewHolder();
|
|
||||||
Drawable fingerprint = getResources().getDrawable(R.drawable.ic_fingerprint);
|
|
||||||
fingerprint.setBounds(0, 0, Utils.dpInPx(50), Utils.dpInPx(50));
|
|
||||||
Resources.Theme theme = requireActivity().getTheme();
|
|
||||||
TypedArray ta = theme.obtainStyledAttributes(new int[] {R.attr.imageColorTint});
|
|
||||||
fingerprint.setTint(ta.getColor(0, Color.GRAY));
|
|
||||||
ta.recycle();
|
|
||||||
vh.messageView.setCompoundDrawables(null, null, null, fingerprint);
|
|
||||||
vh.messageView.setCompoundDrawablePadding(Utils.dpInPx(20));
|
|
||||||
vh.messageView.setGravity(Gravity.CENTER);
|
|
||||||
try {
|
|
||||||
FingerprintHelper helper = new FingerprintHelper() {
|
|
||||||
@Override
|
|
||||||
public void onAuthenticationError(int errorCode, CharSequence errString) {
|
|
||||||
vh.messageView.setTextColor(Color.RED);
|
|
||||||
vh.messageView.setText(errString);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
|
|
||||||
vh.messageView.setTextColor(Color.RED);
|
|
||||||
vh.messageView.setText(helpString);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAuthenticationFailed() {
|
|
||||||
vh.messageView.setTextColor(Color.RED);
|
|
||||||
vh.messageView.setText(R.string.auth_fail);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
|
|
||||||
dialog.dismiss();
|
|
||||||
((SwitchPreference) preference).setChecked(checked);
|
|
||||||
mm.mDB.setSettings(key, checked ? 1 : 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
dialog.setMessage(R.string.auth_fingerprint)
|
|
||||||
.setNegativeButton(R.string.close, (d, w) -> helper.cancel())
|
|
||||||
.setOnCancelListener(d -> helper.cancel())
|
|
||||||
.show();
|
|
||||||
helper.authenticate();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
Utils.toast(R.string.auth_fail, Toast.LENGTH_SHORT);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setSummary() {
|
|
||||||
updateChannel.setSummary(getResources()
|
|
||||||
.getStringArray(R.array.update_channel)[Data.updateChannel]);
|
|
||||||
suAccess.setSummary(getResources()
|
|
||||||
.getStringArray(R.array.su_access)[Data.suAccessState]);
|
|
||||||
autoRes.setSummary(getResources()
|
|
||||||
.getStringArray(R.array.auto_response)[Data.suResponseType]);
|
|
||||||
suNotification.setSummary(getResources()
|
|
||||||
.getStringArray(R.array.su_notification)[Data.suNotificationType]);
|
|
||||||
requestTimeout.setSummary(
|
|
||||||
getString(R.string.request_timeout_summary,
|
|
||||||
mm.prefs.getString(Const.Key.SU_REQUEST_TIMEOUT, "10")));
|
|
||||||
multiuserMode.setSummary(getResources()
|
|
||||||
.getStringArray(R.array.multiuser_summary)[Data.multiuserMode]);
|
|
||||||
namespaceMode.setSummary(getResources()
|
|
||||||
.getStringArray(R.array.namespace_summary)[Data.suNamespaceMode]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPublish(int topic, Object[] result) {
|
|
||||||
setLocalePreference((ListPreference) findPreference(Const.Key.LOCALE));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[] getSubscribedTopics() {
|
|
||||||
return new int[] {Topic.LOCALE_FETCH_DONE};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
351
app/src/full/java/com/topjohnwu/magisk/SettingsFragment.java
Normal file
351
app/src/full/java/com/topjohnwu/magisk/SettingsFragment.java
Normal file
@ -0,0 +1,351 @@
|
|||||||
|
package com.topjohnwu.magisk;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.hardware.fingerprint.FingerprintManager;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v14.preference.SwitchPreference;
|
||||||
|
import android.support.v7.app.AlertDialog;
|
||||||
|
import android.support.v7.preference.ListPreference;
|
||||||
|
import android.support.v7.preference.Preference;
|
||||||
|
import android.support.v7.preference.PreferenceCategory;
|
||||||
|
import android.support.v7.preference.PreferenceFragmentCompat;
|
||||||
|
import android.support.v7.preference.PreferenceScreen;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.asyncs.CheckUpdates;
|
||||||
|
import com.topjohnwu.magisk.asyncs.PatchAPK;
|
||||||
|
import com.topjohnwu.magisk.components.CustomAlertDialog;
|
||||||
|
import com.topjohnwu.magisk.receivers.DownloadReceiver;
|
||||||
|
import com.topjohnwu.magisk.utils.Download;
|
||||||
|
import com.topjohnwu.magisk.utils.FingerprintHelper;
|
||||||
|
import com.topjohnwu.magisk.utils.LocaleManager;
|
||||||
|
import com.topjohnwu.magisk.utils.RootUtils;
|
||||||
|
import com.topjohnwu.magisk.utils.Topic;
|
||||||
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
|
import com.topjohnwu.superuser.Shell;
|
||||||
|
import com.topjohnwu.superuser.ShellUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class SettingsFragment extends PreferenceFragmentCompat
|
||||||
|
implements SharedPreferences.OnSharedPreferenceChangeListener,
|
||||||
|
Topic.Subscriber, Topic.AutoSubscriber {
|
||||||
|
|
||||||
|
private PreferenceScreen prefScreen;
|
||||||
|
|
||||||
|
private ListPreference updateChannel, suAccess, autoRes, suNotification,
|
||||||
|
requestTimeout, multiuserMode, namespaceMode;
|
||||||
|
private MagiskManager mm;
|
||||||
|
private PreferenceCategory generalCatagory;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||||
|
setPreferencesFromResource(R.xml.app_settings, rootKey);
|
||||||
|
mm = Data.MM();
|
||||||
|
prefScreen = getPreferenceScreen();
|
||||||
|
|
||||||
|
generalCatagory = (PreferenceCategory) findPreference("general");
|
||||||
|
PreferenceCategory magiskCategory = (PreferenceCategory) findPreference("magisk");
|
||||||
|
PreferenceCategory suCategory = (PreferenceCategory) findPreference("superuser");
|
||||||
|
Preference hideManager = findPreference("hide");
|
||||||
|
Preference restoreManager = findPreference("restore");
|
||||||
|
findPreference("clear").setOnPreferenceClickListener((pref) -> {
|
||||||
|
mm.prefs.edit().remove(Const.Key.ETAG_KEY).apply();
|
||||||
|
mm.repoDB.clearRepo();
|
||||||
|
Utils.toast(R.string.repo_cache_cleared, Toast.LENGTH_SHORT);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
updateChannel = (ListPreference) findPreference(Const.Key.UPDATE_CHANNEL);
|
||||||
|
suAccess = (ListPreference) findPreference(Const.Key.ROOT_ACCESS);
|
||||||
|
autoRes = (ListPreference) findPreference(Const.Key.SU_AUTO_RESPONSE);
|
||||||
|
requestTimeout = (ListPreference) findPreference(Const.Key.SU_REQUEST_TIMEOUT);
|
||||||
|
suNotification = (ListPreference) findPreference(Const.Key.SU_NOTIFICATION);
|
||||||
|
multiuserMode = (ListPreference) findPreference(Const.Key.SU_MULTIUSER_MODE);
|
||||||
|
namespaceMode = (ListPreference) findPreference(Const.Key.SU_MNT_NS);
|
||||||
|
SwitchPreference reauth = (SwitchPreference) findPreference(Const.Key.SU_REAUTH);
|
||||||
|
SwitchPreference fingerprint = (SwitchPreference) findPreference(Const.Key.SU_FINGERPRINT);
|
||||||
|
|
||||||
|
updateChannel.setOnPreferenceChangeListener((p, o) -> {
|
||||||
|
String prev =String.valueOf(Data.updateChannel);
|
||||||
|
int channel = Integer.parseInt((String) o);
|
||||||
|
if (channel == Const.Value.CUSTOM_CHANNEL) {
|
||||||
|
View v = LayoutInflater.from(requireActivity()).inflate(R.layout.custom_channel_dialog, null);
|
||||||
|
EditText url = v.findViewById(R.id.custom_url);
|
||||||
|
url.setText(mm.prefs.getString(Const.Key.CUSTOM_CHANNEL, ""));
|
||||||
|
new AlertDialog.Builder(requireActivity())
|
||||||
|
.setTitle(R.string.settings_update_custom)
|
||||||
|
.setView(v)
|
||||||
|
.setPositiveButton(R.string.ok, (d, i) ->
|
||||||
|
mm.prefs.edit().putString(Const.Key.CUSTOM_CHANNEL,
|
||||||
|
url.getText().toString()).apply())
|
||||||
|
.setNegativeButton(R.string.close, (d, i) ->
|
||||||
|
mm.prefs.edit().putString(Const.Key.UPDATE_CHANNEL, prev).apply())
|
||||||
|
.setOnCancelListener(d ->
|
||||||
|
mm.prefs.edit().putString(Const.Key.UPDATE_CHANNEL, prev).apply())
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
setSummary();
|
||||||
|
|
||||||
|
// Disable dangerous settings in secondary user
|
||||||
|
if (Const.USER_ID > 0) {
|
||||||
|
suCategory.removePreference(multiuserMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable re-authentication option on Android O, it will not work
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
reauth.setEnabled(false);
|
||||||
|
reauth.setChecked(false);
|
||||||
|
reauth.setSummary(R.string.android_o_not_support);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable fingerprint option if not possible
|
||||||
|
if (!FingerprintHelper.canUseFingerprint()) {
|
||||||
|
fingerprint.setEnabled(false);
|
||||||
|
fingerprint.setChecked(false);
|
||||||
|
fingerprint.setSummary(R.string.disable_fingerprint);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Data.magiskVersionCode >= Const.MAGISK_VER.MANAGER_HIDE) {
|
||||||
|
if (mm.getPackageName().equals(Const.ORIG_PKG_NAME)) {
|
||||||
|
hideManager.setOnPreferenceClickListener((pref) -> {
|
||||||
|
PatchAPK.hideManager(requireActivity());
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
generalCatagory.removePreference(restoreManager);
|
||||||
|
} else {
|
||||||
|
if (Download.checkNetworkStatus(mm)) {
|
||||||
|
restoreManager.setOnPreferenceClickListener((pref) -> {
|
||||||
|
Download.receive(
|
||||||
|
requireActivity(), new DownloadReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onDownloadDone(Context context, Uri uri) {
|
||||||
|
Data.exportPrefs();
|
||||||
|
Shell.su("cp " + uri.getPath() + " /data/local/tmp/manager.apk").exec();
|
||||||
|
if (ShellUtils.fastCmdResult("pm install /data/local/tmp/manager.apk")) {
|
||||||
|
Shell.su("rm -f /data/local/tmp/manager.apk").exec();
|
||||||
|
RootUtils.uninstallPkg(context.getPackageName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Shell.su("rm -f /data/local/tmp/manager.apk").exec();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Data.managerLink,
|
||||||
|
Utils.fmt("MagiskManager-v%s.apk", Data.remoteManagerVersionString)
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
generalCatagory.removePreference(restoreManager);
|
||||||
|
}
|
||||||
|
generalCatagory.removePreference(hideManager);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
generalCatagory.removePreference(restoreManager);
|
||||||
|
generalCatagory.removePreference(hideManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Shell.rootAccess() || (Const.USER_ID > 0 &&
|
||||||
|
Data.multiuserMode == Const.Value.MULTIUSER_MODE_OWNER_MANAGED)) {
|
||||||
|
prefScreen.removePreference(suCategory);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Shell.rootAccess()) {
|
||||||
|
prefScreen.removePreference(magiskCategory);
|
||||||
|
generalCatagory.removePreference(hideManager);
|
||||||
|
} else if (Data.magiskVersionCode < Const.MAGISK_VER.UNIFIED) {
|
||||||
|
prefScreen.removePreference(magiskCategory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setLocalePreference(ListPreference lp) {
|
||||||
|
CharSequence[] entries = new CharSequence[LocaleManager.locales.size() + 1];
|
||||||
|
CharSequence[] entryValues = new CharSequence[LocaleManager.locales.size() + 1];
|
||||||
|
entries[0] = LocaleManager.getString(LocaleManager.defaultLocale, R.string.system_default);
|
||||||
|
entryValues[0] = "";
|
||||||
|
int i = 1;
|
||||||
|
for (Locale locale : LocaleManager.locales) {
|
||||||
|
entries[i] = locale.getDisplayName(locale);
|
||||||
|
entryValues[i++] = locale.toLanguageTag();
|
||||||
|
}
|
||||||
|
lp.setEntries(entries);
|
||||||
|
lp.setEntryValues(entryValues);
|
||||||
|
lp.setSummary(LocaleManager.locale.getDisplayName(LocaleManager.locale));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
mm.prefs.registerOnSharedPreferenceChangeListener(this);
|
||||||
|
Topic.subscribe(this);
|
||||||
|
requireActivity().setTitle(R.string.settings);
|
||||||
|
return super.onCreateView(inflater, container, savedInstanceState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
mm.prefs.unregisterOnSharedPreferenceChangeListener(this);
|
||||||
|
Topic.unsubscribe(this);
|
||||||
|
super.onDestroyView();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
|
||||||
|
switch (key) {
|
||||||
|
case Const.Key.ROOT_ACCESS:
|
||||||
|
case Const.Key.SU_MULTIUSER_MODE:
|
||||||
|
case Const.Key.SU_MNT_NS:
|
||||||
|
mm.mDB.setSettings(key, Utils.getPrefsInt(prefs, key));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Data.loadConfig();
|
||||||
|
setSummary();
|
||||||
|
switch (key) {
|
||||||
|
case Const.Key.DARK_THEME:
|
||||||
|
Topic.publish(false, Topic.RELOAD_ACTIVITY);
|
||||||
|
break;
|
||||||
|
case Const.Key.COREONLY:
|
||||||
|
if (prefs.getBoolean(key, false)) {
|
||||||
|
try {
|
||||||
|
Const.MAGISK_DISABLE_FILE.createNewFile();
|
||||||
|
} catch (IOException ignored) {}
|
||||||
|
} else {
|
||||||
|
Const.MAGISK_DISABLE_FILE.delete();
|
||||||
|
}
|
||||||
|
Utils.toast(R.string.settings_reboot_toast, Toast.LENGTH_LONG);
|
||||||
|
break;
|
||||||
|
case Const.Key.MAGISKHIDE:
|
||||||
|
if (prefs.getBoolean(key, false)) {
|
||||||
|
Shell.su("magiskhide --enable").submit();
|
||||||
|
} else {
|
||||||
|
Shell.su("magiskhide --disable").submit();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Const.Key.HOSTS:
|
||||||
|
if (prefs.getBoolean(key, false)) {
|
||||||
|
Shell.su("cp -af /system/etc/hosts " + Const.MAGISK_HOST_FILE,
|
||||||
|
"mount -o bind " + Const.MAGISK_HOST_FILE + " /system/etc/hosts")
|
||||||
|
.submit();
|
||||||
|
} else {
|
||||||
|
Shell.su("umount -l /system/etc/hosts",
|
||||||
|
"rm -f " + Const.MAGISK_HOST_FILE)
|
||||||
|
.submit();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Const.Key.LOCALE:
|
||||||
|
LocaleManager.setLocale(mm);
|
||||||
|
Topic.publish(false, Topic.RELOAD_ACTIVITY);
|
||||||
|
break;
|
||||||
|
case Const.Key.UPDATE_CHANNEL:
|
||||||
|
case Const.Key.CUSTOM_CHANNEL:
|
||||||
|
CheckUpdates.check();
|
||||||
|
break;
|
||||||
|
case Const.Key.CHECK_UPDATES:
|
||||||
|
Utils.setupUpdateCheck();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceTreeClick(Preference preference) {
|
||||||
|
String key = preference.getKey();
|
||||||
|
switch (key) {
|
||||||
|
case Const.Key.SU_FINGERPRINT:
|
||||||
|
boolean checked = ((SwitchPreference) preference).isChecked();
|
||||||
|
((SwitchPreference) preference).setChecked(!checked);
|
||||||
|
CustomAlertDialog dialog = new CustomAlertDialog(requireActivity());
|
||||||
|
CustomAlertDialog.ViewHolder vh = dialog.getViewHolder();
|
||||||
|
Drawable fingerprint = getResources().getDrawable(R.drawable.ic_fingerprint);
|
||||||
|
fingerprint.setBounds(0, 0, Utils.dpInPx(50), Utils.dpInPx(50));
|
||||||
|
Resources.Theme theme = requireActivity().getTheme();
|
||||||
|
TypedArray ta = theme.obtainStyledAttributes(new int[] {R.attr.imageColorTint});
|
||||||
|
fingerprint.setTint(ta.getColor(0, Color.GRAY));
|
||||||
|
ta.recycle();
|
||||||
|
vh.messageView.setCompoundDrawables(null, null, null, fingerprint);
|
||||||
|
vh.messageView.setCompoundDrawablePadding(Utils.dpInPx(20));
|
||||||
|
vh.messageView.setGravity(Gravity.CENTER);
|
||||||
|
try {
|
||||||
|
FingerprintHelper helper = new FingerprintHelper() {
|
||||||
|
@Override
|
||||||
|
public void onAuthenticationError(int errorCode, CharSequence errString) {
|
||||||
|
vh.messageView.setTextColor(Color.RED);
|
||||||
|
vh.messageView.setText(errString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
|
||||||
|
vh.messageView.setTextColor(Color.RED);
|
||||||
|
vh.messageView.setText(helpString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAuthenticationFailed() {
|
||||||
|
vh.messageView.setTextColor(Color.RED);
|
||||||
|
vh.messageView.setText(R.string.auth_fail);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
|
||||||
|
dialog.dismiss();
|
||||||
|
((SwitchPreference) preference).setChecked(checked);
|
||||||
|
mm.mDB.setSettings(key, checked ? 1 : 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
dialog.setMessage(R.string.auth_fingerprint)
|
||||||
|
.setNegativeButton(R.string.close, (d, w) -> helper.cancel())
|
||||||
|
.setOnCancelListener(d -> helper.cancel())
|
||||||
|
.show();
|
||||||
|
helper.authenticate();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
Utils.toast(R.string.auth_fail, Toast.LENGTH_SHORT);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setSummary() {
|
||||||
|
updateChannel.setSummary(getResources()
|
||||||
|
.getStringArray(R.array.update_channel)[Data.updateChannel]);
|
||||||
|
suAccess.setSummary(getResources()
|
||||||
|
.getStringArray(R.array.su_access)[Data.suAccessState]);
|
||||||
|
autoRes.setSummary(getResources()
|
||||||
|
.getStringArray(R.array.auto_response)[Data.suResponseType]);
|
||||||
|
suNotification.setSummary(getResources()
|
||||||
|
.getStringArray(R.array.su_notification)[Data.suNotificationType]);
|
||||||
|
requestTimeout.setSummary(
|
||||||
|
getString(R.string.request_timeout_summary,
|
||||||
|
mm.prefs.getString(Const.Key.SU_REQUEST_TIMEOUT, "10")));
|
||||||
|
multiuserMode.setSummary(getResources()
|
||||||
|
.getStringArray(R.array.multiuser_summary)[Data.multiuserMode]);
|
||||||
|
namespaceMode.setSummary(getResources()
|
||||||
|
.getStringArray(R.array.namespace_summary)[Data.suNamespaceMode]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPublish(int topic, Object[] result) {
|
||||||
|
setLocalePreference((ListPreference) findPreference(Const.Key.LOCALE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getSubscribedTopics() {
|
||||||
|
return new int[] {Topic.LOCALE_FETCH_DONE};
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@
|
|||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
|
android:layout_marginTop="?attr/actionBarSize"
|
||||||
android:id="@+id/content_frame"
|
android:id="@+id/content_frame"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_marginTop="?attr/actionBarSize"
|
|
||||||
tools:context="com.topjohnwu.magisk.LogFragment">
|
tools:context="com.topjohnwu.magisk.LogFragment">
|
||||||
|
|
||||||
<android.support.design.widget.TabLayout
|
<android.support.design.widget.TabLayout
|
||||||
|
@ -5,14 +5,12 @@
|
|||||||
android:id="@+id/swipeRefreshLayout"
|
android:id="@+id/swipeRefreshLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
android:layout_marginTop="?attr/actionBarSize"
|
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<ScrollView
|
<ScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:layout_marginTop="?attr/actionBarSize"
|
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
@ -5,7 +5,6 @@ xmlns:app="http://schemas.android.com/apk/res-auto"
|
|||||||
android:id="@+id/swipeRefreshLayout"
|
android:id="@+id/swipeRefreshLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
android:layout_marginTop="?attr/actionBarSize"
|
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
@ -3,8 +3,7 @@
|
|||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content">
|
||||||
android:layout_marginTop="?attr/actionBarSize">
|
|
||||||
|
|
||||||
<HorizontalScrollView
|
<HorizontalScrollView
|
||||||
android:id="@+id/hsvLog"
|
android:id="@+id/hsvLog"
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<android.support.v4.widget.SwipeRefreshLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/swipeRefreshLayout"
|
android:id="@+id/swipeRefreshLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
android:layout_marginTop="?attr/actionBarSize"
|
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
@ -13,7 +13,6 @@
|
|||||||
android:id="@+id/coordinator"
|
android:id="@+id/coordinator"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="?attr/actionBarSize"
|
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
<android.support.v7.widget.RecyclerView
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_marginTop="?attr/actionBarSize"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_marginTop="?attr/actionBarSize"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
@ -46,8 +46,8 @@
|
|||||||
android:id="@+id/log"
|
android:id="@+id/log"
|
||||||
android:icon="@drawable/ic_bug_report"
|
android:icon="@drawable/ic_bug_report"
|
||||||
android:title="@string/log" />
|
android:title="@string/log" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:checkable="false"
|
|
||||||
android:id="@+id/settings"
|
android:id="@+id/settings"
|
||||||
android:icon="@drawable/ic_settings"
|
android:icon="@drawable/ic_settings"
|
||||||
android:title="@string/settings"/>
|
android:title="@string/settings"/>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
<PreferenceScreen
|
<PreferenceScreen
|
||||||
android:layout_marginTop="?attr/actionBarSize"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="general"
|
android:key="general"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user