michael@0: /* michael@0: * Copyright (C) 2013 The Android Open Source Project michael@0: * michael@0: * Licensed under the Apache License, Version 2.0 (the "License"); michael@0: * you may not use this file except in compliance with the License. michael@0: * You may obtain a copy of the License at michael@0: * michael@0: * http://www.apache.org/licenses/LICENSE-2.0 michael@0: * michael@0: * Unless required by applicable law or agreed to in writing, software michael@0: * distributed under the License is distributed on an "AS IS" BASIS, michael@0: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. michael@0: * See the License for the specific language governing permissions and michael@0: * limitations under the License. michael@0: */ michael@0: michael@0: package org.mozilla.gecko.background.preferences; michael@0: michael@0: import java.lang.reflect.Constructor; michael@0: import java.lang.reflect.Field; michael@0: import java.lang.reflect.InvocationHandler; michael@0: import java.lang.reflect.Method; michael@0: import java.lang.reflect.Proxy; michael@0: michael@0: import android.app.Activity; michael@0: import android.content.Context; michael@0: import android.content.Intent; michael@0: import android.preference.Preference; michael@0: import android.preference.PreferenceManager; michael@0: import android.preference.PreferenceScreen; michael@0: import android.util.Log; michael@0: michael@0: public class PreferenceManagerCompat { michael@0: michael@0: private static final String TAG = PreferenceManagerCompat.class.getSimpleName(); michael@0: michael@0: /** michael@0: * Interface definition for a callback to be invoked when a michael@0: * {@link Preference} in the hierarchy rooted at this {@link PreferenceScreen} is michael@0: * clicked. michael@0: */ michael@0: interface OnPreferenceTreeClickListener { michael@0: /** michael@0: * Called when a preference in the tree rooted at this michael@0: * {@link PreferenceScreen} has been clicked. michael@0: * michael@0: * @param preferenceScreen The {@link PreferenceScreen} that the michael@0: * preference is located in. michael@0: * @param preference The preference that was clicked. michael@0: * @return Whether the click was handled. michael@0: */ michael@0: boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference); michael@0: } michael@0: michael@0: static PreferenceManager newInstance(Activity activity, int firstRequestCode) { michael@0: try { michael@0: Constructor c = PreferenceManager.class.getDeclaredConstructor(Activity.class, int.class); michael@0: c.setAccessible(true); michael@0: return c.newInstance(activity, firstRequestCode); michael@0: } catch (Exception e) { michael@0: Log.w(TAG, "Couldn't call constructor PreferenceManager by reflection", e); michael@0: } michael@0: return null; michael@0: } michael@0: michael@0: /** michael@0: * Sets the owning preference fragment michael@0: */ michael@0: static void setFragment(PreferenceManager manager, PreferenceFragment fragment) { michael@0: // stub michael@0: } michael@0: michael@0: /** michael@0: * Sets the callback to be invoked when a {@link Preference} in the michael@0: * hierarchy rooted at this {@link PreferenceManager} is clicked. michael@0: * michael@0: * @param listener The callback to be invoked. michael@0: */ michael@0: static void setOnPreferenceTreeClickListener(PreferenceManager manager, final OnPreferenceTreeClickListener listener) { michael@0: try { michael@0: Field onPreferenceTreeClickListener = PreferenceManager.class.getDeclaredField("mOnPreferenceTreeClickListener"); michael@0: onPreferenceTreeClickListener.setAccessible(true); michael@0: if (listener != null) { michael@0: Object proxy = Proxy.newProxyInstance( michael@0: onPreferenceTreeClickListener.getType().getClassLoader(), michael@0: new Class[] { onPreferenceTreeClickListener.getType() }, michael@0: new InvocationHandler() { michael@0: @Override michael@0: public Object invoke(Object proxy, Method method, Object[] args) { michael@0: if (method.getName().equals("onPreferenceTreeClick")) { michael@0: return Boolean.valueOf(listener.onPreferenceTreeClick((PreferenceScreen) args[0], (Preference) args[1])); michael@0: } else { michael@0: return null; michael@0: } michael@0: } michael@0: }); michael@0: onPreferenceTreeClickListener.set(manager, proxy); michael@0: } else { michael@0: onPreferenceTreeClickListener.set(manager, null); michael@0: } michael@0: } catch (Exception e) { michael@0: Log.w(TAG, "Couldn't set PreferenceManager.mOnPreferenceTreeClickListener by reflection", e); michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Inflates a preference hierarchy from the preference hierarchies of michael@0: * {@link Activity Activities} that match the given {@link Intent}. An michael@0: * {@link Activity} defines its preference hierarchy with meta-data using michael@0: * the {@link #METADATA_KEY_PREFERENCES} key. michael@0: *

michael@0: * If a preference hierarchy is given, the new preference hierarchies will michael@0: * be merged in. michael@0: * michael@0: * @param queryIntent The intent to match activities. michael@0: * @param rootPreferences Optional existing hierarchy to merge the new michael@0: * hierarchies into. michael@0: * @return The root hierarchy (if one was not provided, the new hierarchy's michael@0: * root). michael@0: */ michael@0: static PreferenceScreen inflateFromIntent(PreferenceManager manager, Intent intent, PreferenceScreen screen) { michael@0: try { michael@0: Method m = PreferenceManager.class.getDeclaredMethod("inflateFromIntent", Intent.class, PreferenceScreen.class); michael@0: m.setAccessible(true); michael@0: PreferenceScreen prefScreen = (PreferenceScreen) m.invoke(manager, intent, screen); michael@0: return prefScreen; michael@0: } catch (Exception e) { michael@0: Log.w(TAG, "Couldn't call PreferenceManager.inflateFromIntent by reflection", e); michael@0: } michael@0: return null; michael@0: } michael@0: michael@0: /** michael@0: * Inflates a preference hierarchy from XML. If a preference hierarchy is michael@0: * given, the new preference hierarchies will be merged in. michael@0: * michael@0: * @param context The context of the resource. michael@0: * @param resId The resource ID of the XML to inflate. michael@0: * @param rootPreferences Optional existing hierarchy to merge the new michael@0: * hierarchies into. michael@0: * @return The root hierarchy (if one was not provided, the new hierarchy's michael@0: * root). michael@0: * @hide michael@0: */ michael@0: static PreferenceScreen inflateFromResource(PreferenceManager manager, Activity activity, int resId, PreferenceScreen screen) { michael@0: try { michael@0: Method m = PreferenceManager.class.getDeclaredMethod("inflateFromResource", Context.class, int.class, PreferenceScreen.class); michael@0: m.setAccessible(true); michael@0: PreferenceScreen prefScreen = (PreferenceScreen) m.invoke(manager, activity, resId, screen); michael@0: return prefScreen; michael@0: } catch (Exception e) { michael@0: Log.w(TAG, "Couldn't call PreferenceManager.inflateFromResource by reflection", e); michael@0: } michael@0: return null; michael@0: } michael@0: michael@0: /** michael@0: * Returns the root of the preference hierarchy managed by this class. michael@0: * michael@0: * @return The {@link PreferenceScreen} object that is at the root of the hierarchy. michael@0: */ michael@0: static PreferenceScreen getPreferenceScreen(PreferenceManager manager) { michael@0: try { michael@0: Method m = PreferenceManager.class.getDeclaredMethod("getPreferenceScreen"); michael@0: m.setAccessible(true); michael@0: return (PreferenceScreen) m.invoke(manager); michael@0: } catch (Exception e) { michael@0: Log.w(TAG, "Couldn't call PreferenceManager.getPreferenceScreen by reflection", e); michael@0: } michael@0: return null; michael@0: } michael@0: michael@0: /** michael@0: * Called by the {@link PreferenceManager} to dispatch a subactivity result. michael@0: */ michael@0: static void dispatchActivityResult(PreferenceManager manager, int requestCode, int resultCode, Intent data) { michael@0: try { michael@0: Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityResult", int.class, int.class, Intent.class); michael@0: m.setAccessible(true); michael@0: m.invoke(manager, requestCode, resultCode, data); michael@0: } catch (Exception e) { michael@0: Log.w(TAG, "Couldn't call PreferenceManager.dispatchActivityResult by reflection", e); michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Called by the {@link PreferenceManager} to dispatch the activity stop michael@0: * event. michael@0: */ michael@0: static void dispatchActivityStop(PreferenceManager manager) { michael@0: try { michael@0: Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityStop"); michael@0: m.setAccessible(true); michael@0: m.invoke(manager); michael@0: } catch (Exception e) { michael@0: Log.w(TAG, "Couldn't call PreferenceManager.dispatchActivityStop by reflection", e); michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Called by the {@link PreferenceManager} to dispatch the activity destroy michael@0: * event. michael@0: */ michael@0: static void dispatchActivityDestroy(PreferenceManager manager) { michael@0: try { michael@0: Method m = PreferenceManager.class.getDeclaredMethod("dispatchActivityDestroy"); michael@0: m.setAccessible(true); michael@0: m.invoke(manager); michael@0: } catch (Exception e) { michael@0: Log.w(TAG, "Couldn't call PreferenceManager.dispatchActivityDestroy by reflection", e); michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Sets the root of the preference hierarchy. michael@0: * michael@0: * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy. michael@0: * @return Whether the {@link PreferenceScreen} given is different than the previous. michael@0: */ michael@0: static boolean setPreferences(PreferenceManager manager, PreferenceScreen screen) { michael@0: try { michael@0: Method m = PreferenceManager.class.getDeclaredMethod("setPreferences", PreferenceScreen.class); michael@0: m.setAccessible(true); michael@0: return ((Boolean) m.invoke(manager, screen)); michael@0: } catch (Exception e) { michael@0: Log.w(TAG, "Couldn't call PreferenceManager.setPreferences by reflection", e); michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: }