Where is android.os.SystemProperties?
Asked Answered
C

8

55

I'm looking at the Android Camera code, and when I try importing android.os.SystemProperties, it cannot be found.

Here is the file I'm looking at:
https://android.googlesource.com/platform/packages/apps/Camera/+/eclair-release/src/com/android/camera/VideoCamera.java

I created a new 2.1 project and tried importing this namespace again, but It still cannot be found. I checked https://developer.android.com and SystemProperties was not listed.

Did I miss something?

Cachexia answered 14/4, 2010 at 21:17 Comment(0)
L
39

This is the class in the Android source code:

https://android.googlesource.com/platform/frameworks/base/+/eclair-release/core/java/android/os/SystemProperties.java

See {@hide} in the class JavaDoc? That means this class won't be exported as part of the public SDK.

The camera app uses it as it's internal and they won't use the public SDK to build it.

You may still be able to get at this class

  1. by reflection or

  2. by getting the source, removing @hide and making your own customized SDK.

However pretty much by definition you are now going 'off SDK' and therefore your app may well be broken or get different behavior on OS versions as the Android folks will make little effort not to change this class between versions.

Lash answered 14/4, 2010 at 21:34 Comment(3)
If the above source code link is not working, you can try this one androidxref.com/4.3_r2.1/xref/frameworks/base/core/java/android/…Mccaleb
@Jim Blackler: could you please explain more about the 2nd solution. how I can make my own SDK?Incrustation
in my case setProperty() throws exception => #71161544Bogey
R
67

If you use the "reflection" option, you may use the class below

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
        }

    }
}
Ribaldry answered 5/4, 2011 at 13:51 Comment(6)
Does this work? I tried SystemPropertiesProxy.get(this, "android.telephony.TelephonyProperties.PROPERTY_IMSI"); but comes empty.Shipmate
@bruno.braga, it's not that kind of property that is obtained from SystemProperties. To see what properties you can get from your device this way, run adb shell getprop.Rommel
@Psycho, yeah I know... that's the point... for none of the devices I tested, this is available in getprop. That's why I think this simply doesn't work.Shipmate
@bruno.braga, I see, you must be trying this solution: https://mcmap.net/q/41921/-getting-imsi-from-android-phone. But you shouldn't pass android.telephony.TelephonyProperties.PROPERTY_IMSI as a string, it's a Java class's field. I found its string value here: androidjavadoc.com/m5-rc15/…. So try writing "gsm.sim.imsi", although it's not there on my phone either... There are props like gsm.operator.numeric, gsm.sim.operator.alpha, gsm.sim.operator.numeric, etc., but not IMSI.Rommel
Works like a Charm! TanxBonded
@Cristian Following your code, I can't set system property via set method. I can get property value but can't set. Call set method, no exception throw out. What do I miss? Need permission or need another setting?Tea
L
39

This is the class in the Android source code:

https://android.googlesource.com/platform/frameworks/base/+/eclair-release/core/java/android/os/SystemProperties.java

See {@hide} in the class JavaDoc? That means this class won't be exported as part of the public SDK.

The camera app uses it as it's internal and they won't use the public SDK to build it.

You may still be able to get at this class

  1. by reflection or

  2. by getting the source, removing @hide and making your own customized SDK.

However pretty much by definition you are now going 'off SDK' and therefore your app may well be broken or get different behavior on OS versions as the Android folks will make little effort not to change this class between versions.

Lash answered 14/4, 2010 at 21:34 Comment(3)
If the above source code link is not working, you can try this one androidxref.com/4.3_r2.1/xref/frameworks/base/core/java/android/…Mccaleb
@Jim Blackler: could you please explain more about the 2nd solution. how I can make my own SDK?Incrustation
in my case setProperty() throws exception => #71161544Bogey
S
28

The class posted as an answer from user Void has a bunch of unnecessary things. Here is my class that uses reflection on 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");
  }

}
Sustainer answered 9/2, 2015 at 3:31 Comment(2)
I see the set method doesn't work. My device has been rooted. When I run your code, SuperSU app doesn't appear dialog for gaining permission. So I think your code doesn't really trigger su permission.Daryn
@Daryn you will need to run setprop in a shell. I should remove the setprop method.Sustainer
I
17

You could exec out to the getprop command:

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();
Implacable answered 22/9, 2010 at 18:12 Comment(2)
There is no IMEI/IMSI in getprop: guardianproject.info/wiki/…Shipmate
Here's an example by accuya: https://mcmap.net/q/41922/-how-to-define-and-use-a-system-property-in-android-instrumentation-testHanleigh
M
15

After a lot of messing around I've finally got reflection code above working to both set and create new native system properties, there are some caveats:

  1. You need to be the system user, add: android:sharedUserId="android.uid.system" to the manifest.

  2. You need to sign your APK with the platform key, I cheated and just overrode the default debug signing key in eclipse as show here: http://stoned-android.blogspot.co.uk/2012_01_01_archive.html

  3. The native system properties service has an ACL that controls all write access to properties you can subvert a key space (such as sys. or debug.). See /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 },

Or if you are rolling your own build you could add your own key if you really wanted but it seems easier to reuse one of the above.

Morpheme answered 20/6, 2012 at 16:6 Comment(1)
I've done both 1 and 2 items. but It didn't work. Should I need to do something for 3rd item? @MorphemeOberammergau
W
9

Here's how you can read from the system properties. I've included a fallback too :

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
    }
}

Using reflection it works much faster than reading from the process output. About x30 faster on some device I tested (Xiaomi Redmi 8).

So it's worth to try it instead.

Wame answered 2/8, 2020 at 14:41 Comment(0)
M
2

After lots of searching I found a way to set the system property for Android. I was not able to find solution for Android Lollipop version. But I was successful in doing so. For setting system property we need to use :

import android.os.SystemProperties
SystemProperties.set(key, value).

e.g. SystemProperties.set("sys.android", 5.0)

Now you need to give permissions to the new system property Go to /home/inkkashy04/Android_Lollypop/external/sepolicy/property_contexts and give suitable permission to your property

sys.android u:object_r:system_prop:s0

Now after flashing your image you can see your system properties listed by command:

adb shell getprop
Michaeline answered 17/6, 2015 at 7:36 Comment(0)
P
0

Gradle approach :

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")
}
Porte answered 28/3, 2019 at 9:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.