Где находится android.os.SystemProperties?
Я смотрю на код камеры Android, и когда я пытаюсь импортировать android.os.SystemProperties
, это не может быть найдено.
Вот файл, который я смотрю:
https://android.googlesource.com/platform/packages/apps/Camera/+/eclair-release/src/com/android/camera/VideoCamera.java
Я создал новый проект 2.1 и попытался снова импортировать это пространство имен, но его по-прежнему не удается найти. Я проверил https://developer.android.com/ и SystemProperties
не было в списке.
Я что-то пропустил?
6 ответов
Это класс в исходном коде Android:
Увидеть {@hide}
в классе JavaDoc? Это означает, что этот класс не будет экспортирован как часть общедоступного SDK.
Приложение камеры использует его как внутреннее, и они не будут использовать общедоступный SDK для его создания.
Вы все еще можете получить в этом классе
отражением или
получая источник, удаляя
@hide
и сделать свой собственный индивидуальный SDK.
Однако по определению вы сейчасoff SDK
и, следовательно, ваше приложение может быть повреждено или иметь другое поведение в версиях ОС, так как пользователи Android приложат мало усилий, чтобы не менять этот класс между версиями.
Если вы используете опцию "отражение", вы можете использовать класс ниже
package com.etc.etc;
import java.io.File;
import java.lang.reflect.Method;
import android.content.Context;
import dalvik.system.DexFile;
public class SystemPropertiesProxy
{
/**
* This class cannot be instantiated
*/
private SystemPropertiesProxy(){
}
/**
* Get the value for the given key.
* @return an empty string if the key isn't found
* @throws IllegalArgumentException if the key exceeds 32 characters
*/
public static String get(Context context, String key) throws IllegalArgumentException {
String ret= "";
try{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[1];
paramTypes[0]= String.class;
Method get = SystemProperties.getMethod("get", paramTypes);
//Parameters
Object[] params= new Object[1];
params[0]= new String(key);
ret= (String) get.invoke(SystemProperties, params);
}catch( IllegalArgumentException iAE ){
throw iAE;
}catch( Exception e ){
ret= "";
//TODO
}
return ret;
}
/**
* Get the value for the given key.
* @return if the key isn't found, return def if it isn't null, or an empty string otherwise
* @throws IllegalArgumentException if the key exceeds 32 characters
*/
public static String get(Context context, String key, String def) throws IllegalArgumentException {
String ret= def;
try{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= String.class;
paramTypes[1]= String.class;
Method get = SystemProperties.getMethod("get", paramTypes);
//Parameters
Object[] params= new Object[2];
params[0]= new String(key);
params[1]= new String(def);
ret= (String) get.invoke(SystemProperties, params);
}catch( IllegalArgumentException iAE ){
throw iAE;
}catch( Exception e ){
ret= def;
//TODO
}
return ret;
}
/**
* Get the value for the given key, and return as an integer.
* @param key the key to lookup
* @param def a default value to return
* @return the key parsed as an integer, or def if the key isn't found or
* cannot be parsed
* @throws IllegalArgumentException if the key exceeds 32 characters
*/
public static Integer getInt(Context context, String key, int def) throws IllegalArgumentException {
Integer ret= def;
try{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= String.class;
paramTypes[1]= int.class;
Method getInt = SystemProperties.getMethod("getInt", paramTypes);
//Parameters
Object[] params= new Object[2];
params[0]= new String(key);
params[1]= new Integer(def);
ret= (Integer) getInt.invoke(SystemProperties, params);
}catch( IllegalArgumentException iAE ){
throw iAE;
}catch( Exception e ){
ret= def;
//TODO
}
return ret;
}
/**
* Get the value for the given key, and return as a long.
* @param key the key to lookup
* @param def a default value to return
* @return the key parsed as a long, or def if the key isn't found or
* cannot be parsed
* @throws IllegalArgumentException if the key exceeds 32 characters
*/
public static Long getLong(Context context, String key, long def) throws IllegalArgumentException {
Long ret= def;
try{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class SystemProperties= cl.loadClass("android.os.SystemProperties");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= String.class;
paramTypes[1]= long.class;
Method getLong = SystemProperties.getMethod("getLong", paramTypes);
//Parameters
Object[] params= new Object[2];
params[0]= new String(key);
params[1]= new Long(def);
ret= (Long) getLong.invoke(SystemProperties, params);
}catch( IllegalArgumentException iAE ){
throw iAE;
}catch( Exception e ){
ret= def;
//TODO
}
return ret;
}
/**
* Get the value for the given key, returned as a boolean.
* Values 'n', 'no', '0', 'false' or 'off' are considered false.
* Values 'y', 'yes', '1', 'true' or 'on' are considered true.
* (case insensitive).
* If the key does not exist, or has any other value, then the default
* result is returned.
* @param key the key to lookup
* @param def a default value to return
* @return the key parsed as a boolean, or def if the key isn't found or is
* not able to be parsed as a boolean.
* @throws IllegalArgumentException if the key exceeds 32 characters
*/
public static Boolean getBoolean(Context context, String key, boolean def) throws IllegalArgumentException {
Boolean ret= def;
try{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= String.class;
paramTypes[1]= boolean.class;
Method getBoolean = SystemProperties.getMethod("getBoolean", paramTypes);
//Parameters
Object[] params= new Object[2];
params[0]= new String(key);
params[1]= new Boolean(def);
ret= (Boolean) getBoolean.invoke(SystemProperties, params);
}catch( IllegalArgumentException iAE ){
throw iAE;
}catch( Exception e ){
ret= def;
//TODO
}
return ret;
}
/**
* Set the value for the given key.
* @throws IllegalArgumentException if the key exceeds 32 characters
* @throws IllegalArgumentException if the value exceeds 92 characters
*/
public static void set(Context context, String key, String val) throws IllegalArgumentException {
try{
@SuppressWarnings("unused")
DexFile df = new DexFile(new File("/system/app/Settings.apk"));
@SuppressWarnings("unused")
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class SystemProperties = Class.forName("android.os.SystemProperties");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= String.class;
paramTypes[1]= String.class;
Method set = SystemProperties.getMethod("set", paramTypes);
//Parameters
Object[] params= new Object[2];
params[0]= new String(key);
params[1]= new String(val);
set.invoke(SystemProperties, params);
}catch( IllegalArgumentException iAE ){
throw iAE;
}catch( Exception e ){
//TODO
}
}
}
Класс, опубликованный как ответ пользователя Void, содержит кучу ненужных вещей. Вот мой класс, который использует отражение на android.os.SystemProperties:
/*
* Copyright (C) 2015 Jared Rummler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Gives access to the system properties store. The system properties store contains a list of
* string key-value pairs.
*/
public class SystemProperties {
private static final Class<?> SP = getSystemPropertiesClass();
/**
* Get the value for the given key.
*/
public static String get(String key) {
try {
return (String) SP.getMethod("get", String.class).invoke(null, key);
} catch (Exception e) {
return null;
}
}
/**
* Get the value for the given key.
*
* @return if the key isn't found, return def if it isn't null, or an empty string otherwise
*/
public static String get(String key, String def) {
try {
return (String) SP.getMethod("get", String.class, String.class).invoke(null, key, def);
} catch (Exception e) {
return def;
}
}
/**
* Get the value for the given key, returned as a boolean. Values 'n', 'no', '0', 'false' or
* 'off' are considered false. Values 'y', 'yes', '1', 'true' or 'on' are considered true. (case
* sensitive). If the key does not exist, or has any other value, then the default result is
* returned.
*
* @param key
* the key to lookup
* @param def
* a default value to return
* @return the key parsed as a boolean, or def if the key isn't found or is not able to be
* parsed as a boolean.
*/
public static boolean getBoolean(String key, boolean def) {
try {
return (Boolean) SP.getMethod("getBoolean", String.class, boolean.class)
.invoke(null, key, def);
} catch (Exception e) {
return def;
}
}
/**
* Get the value for the given key, and return as an integer.
*
* @param key
* the key to lookup
* @param def
* a default value to return
* @return the key parsed as an integer, or def if the key isn't found or cannot be parsed
*/
public static int getInt(String key, int def) {
try {
return (Integer) SP.getMethod("getInt", String.class, int.class).invoke(null, key, def);
} catch (Exception e) {
return def;
}
}
/**
* Get the value for the given key, and return as a long.
*
* @param key
* the key to lookup
* @param def
* a default value to return
* @return the key parsed as a long, or def if the key isn't found or cannot be parsed
*/
public static long getLong(String key, long def) {
try {
return (Long) SP.getMethod("getLong", String.class, long.class).invoke(null, key, def);
} catch (Exception e) {
return def;
}
}
private static Class<?> getSystemPropertiesClass() {
try {
return Class.forName("android.os.SystemProperties");
} catch (ClassNotFoundException shouldNotHappen) {
return null;
}
}
private SystemProperties() {
throw new AssertionError("no instances");
}
}
Вы могли бы выполнить на getprop
команда:
String line = "";
try {
Process ifc = Runtime.getRuntime().exec("getprop ro.hardware");
BufferedReader bis = new BufferedReader(new InputStreamReader(ifc.getInputStream()));
line = bis.readLine();
} catch (java.io.IOException e) {
}
ifc.destroy();
После долгих раздумий я наконец-то получил приведенный выше код отражения, работающий над тем, чтобы установить и создать новые собственные свойства системы, вот несколько предостережений:
Вы должны быть системным пользователем, добавьте: android:sharedUserId="android.uid.system" в манифест.
Вам нужно подписать свой APK с помощью ключа платформы, я обманул и просто переопределил стандартный ключ подписи отладки в eclipse, как показано здесь: http://stoned-android.blogspot.co.uk/2012_01_01_archive.html
Служба системных свойств системы имеет ACL, который контролирует все права на запись в свойства, которые вы можете преобразовать в пространство ключей (например, sys. Или debug.). Смотрите /system/core/init/property_service.c:
{"net.", AID_SYSTEM, 0}, {"dev.", AID_SYSTEM, 0}, {"runtime.", AID_SYSTEM, 0}, {"hw.", AID_SYSTEM, 0}, {"sys.", AID_SYSTEM, 0}, {"service.", AID_SYSTEM, 0}, {"wlan.", AID_SYSTEM, 0}, {"dhcp.", AID_SYSTEM, 0},
Или, если вы катите свою собственную сборку, вы можете добавить свой собственный ключ, если вы действительно этого хотите, но, кажется, проще использовать один из перечисленных выше.
Вот как можно узнать из свойств системы. Я тоже включил запасной вариант:
import android.annotation.SuppressLint
import java.io.*
import java.lang.reflect.Method
object SystemProperties {
private var failedUsingReflection = false
private var getPropMethod: Method? = null
@SuppressLint("PrivateApi")
fun getProp(propName: String, defaultResult: String = ""): String {
if (!failedUsingReflection) try {
if (getPropMethod == null) {
val clazz = Class.forName("android.os.SystemProperties")
getPropMethod = clazz.getMethod("get", String::class.java, String::class.java)
}
return getPropMethod!!.invoke(null, propName, defaultResult) as String? ?: defaultResult
} catch (e: Exception) {
getPropMethod = null
failedUsingReflection = true
}
var process: Process? = null
try {
process = Runtime.getRuntime().exec("getprop \"$propName\" \"$defaultResult\"")
val reader = BufferedReader(InputStreamReader(process.inputStream))
return reader.readLine()
} catch (e: IOException) {
} finally {
process?.destroy()
}
return defaultResult
}
}
Используя отражение, он работает намного быстрее, чем чтение из вывода процесса. Примерно в 30 раз быстрее на каком-то устройстве, которое я тестировал (Xiaomi Redmi 8).
Так что вместо этого стоит попробовать.
После долгих поисков я нашел способ установить системное свойство для Android. Я не смог найти решение для версии Android Lollipop. Но мне это удалось. Для установки системного свойства нам нужно использовать:
import android.os.SystemProperties
SystemProperties.set(key, value).
например SystemProperties.set("sys.android", 5.0)
Теперь вам нужно дать права доступа к новому системному свойству. /home/inkkashy04/Android_Lollypop/external/sepolicy/property_contexts
и дать подходящее разрешение на вашу собственность
sys.android u:object_r:system_prop:s0
Теперь после перепрошивки вашего изображения вы можете увидеть системные свойства, перечисленные командой:
adb shell getprop
Gradle подход:
String SDK_DIR = System.getenv("ANDROID_SDK_HOME")
if(SDK_DIR == null) {
Properties props = new Properties()
props.load(new FileInputStream(project.rootProject.file("local.properties")))
SDK_DIR = props.get('sdk.dir');
}
dependencies {
compileOnly files("${SDK_DIR}/platforms/android-25/data/layoutlib.jar")
}