28

I am trying to use some arguments for an Instrumentation test. I noticed that I can read system properties with System.getProperty() function. So I use setprop command to set a system property. For example: adb shell setprop AP 123. Inside my Test code I try to read this AP property with :


tmp = System.getProperty("AP"); 
Log.d("MyTest","AP Value = " + tmp);

Then I use logcat to view this debug message but I get a null value for this property. Any ideas on what could be wrong? Note that I can still read the system property with adb shell getprop AP command.

DeRagan
  • 22,827
  • 6
  • 41
  • 50
Michalis
  • 3,109
  • 6
  • 26
  • 24
  • Assuming you want to change these properties between tests, and given that you can't apply new system properties at runtime (see Matthias' answer), it's probably best to abstract the setting/getting of system properties out to a helper class, of which you can provide a mock implementation when testing. – Christopher Orr Apr 09 '11 at 13:15
  • This thread is better: http://stackoverflow.com/questions/2641111/where-is-android-os-systemproperties – Snicolas Mar 13 '17 at 02:48

7 Answers7

26

To get the property set by 'setprop', there are two options:
One. use android.os.SystemProperties, this is a hide API. use it like this:

Class clazz = null;
clazz = Class.forName("android.os.SystemProperties");
Method method = clazz.getDeclaredMethod("get", String.class);
String prop = (String)method.invoke(null, "AP");
Log.e("so_test", "my prop is: <" + prop  + ">");

Two. use 'getprop' utility:

Process proc = Runtime.getRuntime().exec(new String[]{"/system/bin/getprop", "AP"});
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
Log.e("so_test", "my prop is: " + reader.readLine());

Maybe using functions availble in NDK is an option too, but why bother?

accuya
  • 1,412
  • 14
  • 14
  • 2
    Just to complete this for the ones like me who needed Set method `Method method = clazz.getDeclaredMethod("set", String.class, String.class);` – miroslavign Sep 18 '15 at 10:18
  • Do you need to add special permissions to do this? @miroslavign – htellez Dec 11 '15 at 05:13
  • @htellez No you don't – miroslavign Dec 11 '15 at 11:30
  • 1
    I get a RuntimeException: `java.lang.RuntimeException: failed to set system property at android.os.SystemProperties.native_set(Native Method) at android.os.SystemProperties.set(SystemProperties.java:130)` Have you tried this in Marshmallow? – htellez Dec 11 '15 at 17:13
  • in my case setProperty() throws exception => https://stackoverflow.com/questions/71161044/android-os-systemproperties-does-not-save-values-during-junit-testing – Tajuddin Khandaker Mar 02 '22 at 09:40
15

System properties are read once when the root VM (Zygote) is started, which in turn spawns other Dalvik VMs like that of your application. That means you cannot set system properties on the fly.

Try restarting Zygote using adb shell stop (wait until it has stopped) and adb shell start (wait until it has restarted), then try again. Or simply reboot the device or emulator.

mxk
  • 43,056
  • 28
  • 105
  • 132
  • 4
    It's worth mentioning that you should be able to set properties at emulator startup time, e.g. `emulator -avd 2.3 -prop AP=123`. – Christopher Orr Apr 09 '11 at 13:14
  • Always try your best to keep the environment intact when executing a test. And restart Zygote can't make the android system property available to System.getProperty() – accuya Jul 24 '12 at 02:40
  • I was not so much handing out advice on how to run instrumentation tests rather than answering his question, which was how you can change system properties on the emulator. What I described does exactly that. – mxk Jul 24 '12 at 08:41
11

Because there are two types of property in Android.

  1. System level - we can get/set with command adb shell getprop/setprop.
  2. In current process level - we can get/set with regular java System.getProperty()/setProperty().

As you are setting a system level property and trying to get its value as current process level, you are getting null value in log.

Amanda S
  • 3,266
  • 4
  • 33
  • 45
Nimesh
  • 111
  • 1
  • 3
6

here's a slightly saner version based on accuya's answer:

public static String readSystemProperty(String name) {
    InputStreamReader in = null;
    BufferedReader reader = null;
    try {
        Process proc = Runtime.getRuntime().exec(new String[]{"/system/bin/getprop", name});
        in = new InputStreamReader(proc.getInputStream());
        reader = new BufferedReader(in);
        return reader.readLine();
    } catch (IOException e) {
        return null;
    } finally {
        closeQuietly(in);
        closeQuietly(reader);
    }
}

public static void closeQuietly(Closeable closeable) {
    if (closeable == null) return;
    try {
        closeable.close();
    } catch (IOException ignored) {
    }
}
Felipe Lima
  • 10,530
  • 4
  • 41
  • 39
1

Based on provided answer, Slightly modified version of SetProperty

    public void setSystemProperty(String Key, String value){
    InputStreamReader in = null;
    BufferedReader reader = null;
    try {
        Process proc = Runtime.getRuntime().exec("/system/bin/setprop "+Key+" "+value);
        in = new InputStreamReader(proc.getInputStream());
        reader = new BufferedReader(in);

        String line = null;
        Log.d("Saurabh Shell" ,"<OUTPUT>");
        while ( (line = reader.readLine()) != null)
            Log.d("Shell" , line);
        Log.d("Saurabh Shell", "</OUTPUT>");
        int exitVal = proc.waitFor();
        Log.d("Saurabh Shell","Process exitValue: " + exitVal);

    } catch (IOException e) {
       e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        closeQuietly(in);
        closeQuietly(reader);
    }
}

close Input and reader

    public  void closeQuietly(Closeable closeable) {
    if (closeable == null) return;
    try {
        closeable.close();
    } catch (IOException ignored) {
    }
}
SAURABH_12
  • 2,262
  • 1
  • 19
  • 19
  • is this should be "adb shell" if I call it in unit test package? .. "Process proc = Runtime.getRuntime().exec("adb shell /system/bin/setprop "+Key+" "+value);" – Tajuddin Khandaker Mar 02 '22 at 10:36
-1

You need a root to set system property

adb shell
su
setprop AP 123
k4dima
  • 6,070
  • 5
  • 41
  • 39
-4

import android.os.SystemProperties

String s = SystemProterties.get("ro.xxx.xxx","default value if property not set");

Amol K
  • 165
  • 3
  • 12