299 lines
9.8 KiB
Java
299 lines
9.8 KiB
Java
/*
|
|
This file is part of Subsonic.
|
|
|
|
Subsonic is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Subsonic is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
Copyright 2014 (C) Scott Jackson
|
|
*/
|
|
|
|
package net.nullsum.audinaut.fragments;
|
|
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.os.Bundle;
|
|
import android.os.Handler;
|
|
import android.os.Message;
|
|
import android.preference.Preference;
|
|
import android.preference.PreferenceManager;
|
|
import android.preference.PreferenceScreen;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.ListView;
|
|
|
|
import androidx.appcompat.app.AppCompatActivity;
|
|
|
|
import net.nullsum.audinaut.R;
|
|
import net.nullsum.audinaut.util.Constants;
|
|
|
|
import java.lang.reflect.Constructor;
|
|
import java.lang.reflect.Method;
|
|
|
|
public abstract class PreferenceCompatFragment extends SubsonicFragment {
|
|
private static final int FIRST_REQUEST_CODE = 100;
|
|
private static final int MSG_BIND_PREFERENCES = 1;
|
|
private static final String PREFERENCES_TAG = "android:preferences";
|
|
private boolean mHavePrefs;
|
|
private boolean mInitDone;
|
|
private ListView mList;
|
|
final private Runnable mRequestFocus = new Runnable() {
|
|
public void run() {
|
|
mList.focusableViewAvailable(mList);
|
|
}
|
|
};
|
|
private PreferenceManager mPreferenceManager;
|
|
private final Handler mHandler = new Handler() {
|
|
@Override
|
|
public void handleMessage(Message msg) {
|
|
switch (msg.what) {
|
|
|
|
case MSG_BIND_PREFERENCES:
|
|
bindPreferences();
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
private void bindPreferences() {
|
|
PreferenceScreen localPreferenceScreen = getPreferenceScreen();
|
|
if (localPreferenceScreen != null) {
|
|
ListView localListView = getListView();
|
|
localPreferenceScreen.bind(localListView);
|
|
}
|
|
}
|
|
|
|
private void ensureList() {
|
|
if (mList == null) {
|
|
View view = getView();
|
|
if (view == null) {
|
|
throw new IllegalStateException("Content view not yet created");
|
|
}
|
|
|
|
View listView = view.findViewById(android.R.id.list);
|
|
if (!(listView instanceof ListView)) {
|
|
throw new RuntimeException("Content has view with id attribute 'android.R.id.list' that is not a ListView class");
|
|
}
|
|
|
|
mList = (ListView) listView;
|
|
|
|
mHandler.post(mRequestFocus);
|
|
}
|
|
}
|
|
|
|
private void postBindPreferences() {
|
|
if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) {
|
|
mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
|
|
}
|
|
}
|
|
|
|
private void requirePreferenceManager() {
|
|
if (this.mPreferenceManager == null) {
|
|
throw new RuntimeException("This should be called after super.onCreate.");
|
|
}
|
|
}
|
|
|
|
private PreferenceScreen addPreferencesFromResource(int resId) {
|
|
requirePreferenceManager();
|
|
PreferenceScreen screen = inflateFromResource(getActivity(), resId, getPreferenceScreen());
|
|
setPreferenceScreen(screen);
|
|
|
|
for (int i = 0; i < screen.getPreferenceCount(); i++) {
|
|
Preference preference = screen.getPreference(i);
|
|
if (preference instanceof PreferenceScreen && preference.getKey() != null) {
|
|
preference.setOnPreferenceClickListener(preference1 -> {
|
|
onStartNewFragment(preference1.getKey());
|
|
return false;
|
|
});
|
|
}
|
|
}
|
|
|
|
return screen;
|
|
}
|
|
|
|
Preference findPreference(CharSequence key) {
|
|
if (mPreferenceManager == null) {
|
|
return null;
|
|
}
|
|
return mPreferenceManager.findPreference(key);
|
|
}
|
|
|
|
private ListView getListView() {
|
|
ensureList();
|
|
return mList;
|
|
}
|
|
|
|
PreferenceManager getPreferenceManager() {
|
|
return mPreferenceManager;
|
|
}
|
|
|
|
@Override
|
|
public void onActivityCreated(Bundle savedInstanceState) {
|
|
super.onActivityCreated(savedInstanceState);
|
|
getListView().setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
|
|
if (mHavePrefs) {
|
|
bindPreferences();
|
|
}
|
|
mInitDone = true;
|
|
if (savedInstanceState != null) {
|
|
Bundle localBundle = savedInstanceState.getBundle(PREFERENCES_TAG);
|
|
if (localBundle != null) {
|
|
PreferenceScreen screen = getPreferenceScreen();
|
|
if (screen != null) {
|
|
screen.restoreHierarchyState(localBundle);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
super.onActivityResult(requestCode, resultCode, data);
|
|
dispatchActivityResult(requestCode, resultCode, data);
|
|
}
|
|
|
|
@Override
|
|
public void onCreate(Bundle paramBundle) {
|
|
super.onCreate(paramBundle);
|
|
mPreferenceManager = createPreferenceManager();
|
|
|
|
int res = this.getArguments().getInt(Constants.INTENT_EXTRA_FRAGMENT_TYPE, 0);
|
|
if (res != 0) {
|
|
PreferenceScreen preferenceScreen = addPreferencesFromResource(res);
|
|
onInitPreferences(preferenceScreen);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public View onCreateView(LayoutInflater paramLayoutInflater, ViewGroup paramViewGroup, Bundle paramBundle) {
|
|
return paramLayoutInflater.inflate(R.layout.preferences, paramViewGroup, false);
|
|
}
|
|
|
|
@Override
|
|
public void onDestroy() {
|
|
super.onDestroy();
|
|
dispatchActivityDestroy();
|
|
}
|
|
|
|
@Override
|
|
public void onDestroyView() {
|
|
mList = null;
|
|
mHandler.removeCallbacks(mRequestFocus);
|
|
mHandler.removeMessages(MSG_BIND_PREFERENCES);
|
|
super.onDestroyView();
|
|
}
|
|
|
|
@Override
|
|
public void onSaveInstanceState(Bundle bundle) {
|
|
super.onSaveInstanceState(bundle);
|
|
PreferenceScreen screen = getPreferenceScreen();
|
|
if (screen != null) {
|
|
Bundle localBundle = new Bundle();
|
|
screen.saveHierarchyState(localBundle);
|
|
bundle.putBundle(PREFERENCES_TAG, localBundle);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onStop() {
|
|
super.onStop();
|
|
dispatchActivityStop();
|
|
}
|
|
|
|
/**
|
|
* Access methods with visibility private
|
|
**/
|
|
|
|
private PreferenceManager createPreferenceManager() {
|
|
try {
|
|
Constructor<PreferenceManager> c = PreferenceManager.class.getDeclaredConstructor(AppCompatActivity.class, int.class);
|
|
c.setAccessible(true);
|
|
return c.newInstance(this.getActivity(), FIRST_REQUEST_CODE);
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
private PreferenceScreen getPreferenceScreen() {
|
|
try {
|
|
Method m = PreferenceManager.class.getDeclaredMethod("getPreferenceScreen");
|
|
m.setAccessible(true);
|
|
return (PreferenceScreen) m.invoke(mPreferenceManager);
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
void setPreferenceScreen(PreferenceScreen preferenceScreen) {
|
|
try {
|
|
Method m = PreferenceManager.class.getDeclaredMethod("setPreferences", PreferenceScreen.class);
|
|
m.setAccessible(true);
|
|
boolean result = (Boolean) m.invoke(mPreferenceManager, preferenceScreen);
|
|
if (result && preferenceScreen != null) {
|
|
mHavePrefs = true;
|
|
if (mInitDone) {
|
|
postBindPreferences();
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
private void dispatchActivityResult(int requestCode, int resultCode, Intent data) {
|
|
try {
|
|
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityResult", int.class, int.class, Intent.class);
|
|
m.setAccessible(true);
|
|
m.invoke(mPreferenceManager, requestCode, resultCode, data);
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
private void dispatchActivityDestroy() {
|
|
try {
|
|
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityDestroy");
|
|
m.setAccessible(true);
|
|
m.invoke(mPreferenceManager);
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
private void dispatchActivityStop() {
|
|
try {
|
|
Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityStop");
|
|
m.setAccessible(true);
|
|
m.invoke(mPreferenceManager);
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
private PreferenceScreen inflateFromResource(Context context, int resId, PreferenceScreen rootPreferences) {
|
|
PreferenceScreen preferenceScreen;
|
|
try {
|
|
Method m = PreferenceManager.class.getDeclaredMethod("inflateFromResource", Context.class, int.class, PreferenceScreen.class);
|
|
m.setAccessible(true);
|
|
preferenceScreen = (PreferenceScreen) m.invoke(mPreferenceManager, context, resId, rootPreferences);
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
return preferenceScreen;
|
|
}
|
|
|
|
protected abstract void onInitPreferences(PreferenceScreen preferenceScreen);
|
|
|
|
protected abstract void onStartNewFragment(String name);
|
|
}
|