Settings.Secure.INSTALL_NON_MARKET_APPS在 API 17 中已被弃用,因此如果您将 minimumSDK 设置为低于 17,则无法直接访问它并且必须使用反射。
我的解决方案:
public class BackwardCompatibility {
private static Class<?> settingsGlobal;
/**
* Returns Settings.Global class for reflective calls.
* Global is a nested class of the Settings, has to be done in a special way.
*
* @return
*/
public static Class<?> getSettingsGlobal(){
if (settingsGlobal!=null){
return settingsGlobal;
}
try {
Class<?> master = Class.forName("android.provider.Settings");
Class<?>[] classes = master.getClasses();
for(Class<?> cls : classes){
if (cls==null) {
continue;
}
if ("android.provider.Settings$Global".equals(cls.getName())){
settingsGlobal = cls;
return settingsGlobal;
}
}
return null;
} catch(Exception ex){
Log.e(TAG, "Reflective call not successfull", ex);
}
return null;
}
/**
* Determines whether installing Android apks from unknown sources is allowed.
*
* @param ctxt
* @return
*/
public static boolean isUnknownSourceInstallAllowed(Context ctxt){
try {
boolean unknownSource = false;
if (Build.VERSION.SDK_INT < 17) {
unknownSource = Settings.Secure.getInt(ctxt.getContentResolver(), Settings.Secure.INSTALL_NON_MARKET_APPS, 0) == 1;
} else {
// Has to use reflection since API 17 is not directly reachable.
// Original call would be:
// unknownSource = Settings.Global.getInt(ctxt.getContentResolver(), Settings.Global.INSTALL_NON_MARKET_APPS, 0) == 1;
//
Class<?> c = getSettingsGlobal();
Method m = c.getMethod("getInt", new Class[] { ContentResolver.class, String.class, int.class });
// Obtain constant value
Field f = c.getField("INSTALL_NON_MARKET_APPS");
final String constVal = (String) f.get(null);
unknownSource = Integer.valueOf(1).equals((Integer) m.invoke(null, ctxt.getContentResolver(), constVal, 0));
}
return unknownSource;
} catch(Exception e){
// Handle this as you like.
Log.w(TAG, "Cannot determine if installing from unknown sources is allowed", e);
}
return false;
}
}