[Library] Cmd library: Execute Your Java Codes With Root Access Privileges - IDEs, Libraries, & Programming Tools

Synopsis:
Have you ever wanted as root apps developer to use your favourite Java codes instead of bash/shell commands?
Have you grown tired of Runtime.getRuntime.exec("su") and ProcessBuilder("su").start()?
I did and still do, that's why I've been searching for a solution for my problem until I found out in AOSP source code that some of *.java files run with root access, tracking the way they execute them with root access led me to make this simple library.
Description:
Cmd library -short for Command- is an open source (licensed under Apache licence V2) that allows you to execute java commands with root access privileges by passing package name, full class name and whether your app is a system app or not in just two lines of codes.
For instance, suppose you want to flash a *.img recovery image, the first thing comes to your mind is this code:
Code:
busybox dd if=/path/to/recovery.img of=/path/to/recoveryPartition
lets say /sdcard/recovery.img is the file path and /dev/block/mmcblk0p12 is the partition (Samsung GALAXY Ace Plus GT-S7500)
Here is how to implement it:
Code:
...
Proccess proc = Runtime.getRuntime().exec("su");
OutputStream stream = proc.getOutputStream();
stream.write("busybox dd if=/sdcard/recovery.img of=/dev/block/mmcblk0p12".getBytes());
stream.flush();
...
Pretty simple isn't it, now suppose you don't know anything about bash codes, what will you do?
Let me answer this question:
1) Learn some bash.
2) Use Cmd library with java codes.
Here is the same implementaion with Cmd library:
Code:
...
JavaRoot root = JavaRoot.newInstance(getPackageName(), RootCommands.class.getName(), false);
root.execute("/sdcard/recovery.img", "/dev/block/mmcblk0p12")
...
And in RootCommands.java file (should not be an inner class):
Code:
package com.bassel.example;
import com.bassel.cmd.Command;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class Main extends Command
{
private byte[] buffer;
private File recovery, partition;
private FileInputStream in;
private FileOutputStream out;
//static main method implementation is a must
@Override
public static void main(String[] args)
{
//required to start
new Main().run(args);
}
//the begging just like onCreate
@Override
public void onRun()
{
if(argsCount() < 2) showUsage();
System.out.println(String.format("Flashing %s to %s", getArg(0), getArg(1)));
recovery = new File(nextArg());
partition = new File(nextArg());
buffer = new byte[1024 * 1024];
try
{
in = new FileInputStream(recovery);
out = new FileOutputStream(partition);
while(in.read(buffer) > 0)
{
out.write(buffer);
out.flush();
}
in.close();
out.close();
System.out.println("Flashed successfully!");
}
catch (Exception e)
{e.printStackTrace(System.err);}
}
//called upon calling showUsage()
@Override
public void onShowUsage()
{
System.err.println("Two args are needed!");
}
//called once an exception is caught
@Override
public void onExceptionCaught(Exception exception)
{
exception.printStackTrace(System.err);
}
}
Quite lengthy but sometimes we prefer using Java codes to bash ones, don't we?
Here is another example for listing /data files:
Code:
package com.bassel. example;
import java.io.File;
//Without extending Command.class
public class Main
{
@Override
public static void main(String[] args)
{
String[] files = new File("/data").list();
for(String file : files)
{
System.out.println(file);
}
}
}
Usage in depth:
Check root access:
Cmd.root();
No root:
Cmd.SH.ex(String command, String... args);
Cmd.SH.ex(String[] commands);
Cmd.SH.ex(List commands);
With root access:
Cmd.SU.ex(String command, String... args);
Cmd.SU.ex(String[] commands);
Cmd.SU.ex(List commands);
JavaRoot java = JavaRoot.newInstance(String packageName, String className, boolean isSystemApp);
java.execute(String... args);
java.executeInBackground(String... args);
All previous methods aside of the last one:
java.executeInBackground(String... args);
return an instance of type Output that has the following methods:
Code:
boolean success() //returns true if process exit value = 0 else false
String getString() //returns output in String format
String[] getArray() //returns output in String Array format
List getList() //returns output in String List format
int getExitValue() //returns process exit value
String toString() //returns process status and output in String format
Converting:
String string = ...;
String[] array = ...;
List list = ...;
String s1 = Convert.array2string(array);
String s2 = Convert.list2string(list);
String[] a1 = Convert.list2array(list);
String[] a2 = Convert.string2array(string);
List l1 = Convert.array2list(array);
List l2 = Convert.string2list(string);
Library GitHub link:
Cmd (licensed under Apache License, Version 2.0)
Examples:
Window Manipulator

Related

Need help with Root access app.

I have a simple app that I'm trying to develop. I have written Android apps for work but this would be the first app with root access, and it is not for work. Here is my onCreate code.
Code:
setContentView(R.layout.main);
/**
* Set up the spinner for the buffer size
*/
spinner = (Spinner) findViewById(R.id.spKBSelect);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
this, R.array.KBs, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
txtCurVal = (TextView) findViewById(R.id.txtCurrentV);
try {
txtCurVal.setText(getString(R.string.cursetvalue) + " " + getCurrentValue() + " KB");
p = Runtime.getRuntime().exec("su");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
This code works fine. I get root access from Superuser. Now when I click the button in the following code it works. The only thing is that when I try to refresh my txtCurVal.setText() after the update I get the same value. I have checked and the update to the file did go through. So what I think is that the su process and/or commands dealing with the su have not finished when I read the value again. After searching online most people were saying that I needed to add a p.waitfor(); so that the terminal could finish. This is where the problems occurs it gets to the point and the app just stops. After a few second Android says that the app is non responsive and wants to force close. Here is the button click code.
Code:
public void onClick(View v) throws Exception {
switch (v.getId()) {
case R.id.btnAbout:
Toast.makeText(this, "Created by: Ben Murphy (Smurph82)\nCreated on: 2011_0618", Toast.LENGTH_LONG).show();
break;
case R.id.btnSave:
DataOutputStream os = new DataOutputStream(p.getOutputStream());
DataInputStream osRes = new DataInputStream(p.getInputStream());
//backupFile(getString(R.string.rakpath));
os.writeBytes("busybox cp " + getString(R.string.rakpath) + " " + sdcard + "/.sdspeedshifter\n");
os.flush();
os.writeBytes("busybox mv -f " + sdcard + "/.sdspeedshifter/read_ahead_kb " + " " + sdcard + "/.sdspeedshifter/read_ahead_kb_bak\n");
os.flush();
//writeNewValue(spinner.getSelectedItem().toString(), getString(R.string.rakpath));
os.writeBytes("echo \"" + spinner.getSelectedItem().toString() + "\" > " + getString(R.string.rakpath) + "\n");
os.flush();
os.writeBytes("exit\n");
os.flush();
[B]p.waitFor();[/B]
txtCurVal.setText(getString(R.string.cursetvalue) + " " + getCurrentValue() + " KB");
break;
default:
break;
}
}
If I take the p.waitfor(); out everything runs but the value is not displayed correctly. This is just an app for me to learn how to use su access. As you can tell all this does is increase the value in the read_ahead_kb file that helps with sd card speed. Any help of advice would be great. Thanks.
I don't see "p" every declared, so there's no way to know, given what you've posted, whether it is in-scope for both "setContentView" and "onClick" so that may be why you're app is hanging, but I don't think this is the way to go about it. Running a bare "su" command in exec is going to spawn off a new command shell with root privileges, but without passing any arguments, the shell is just going to sit there assuming it is a login shell, waiting for the user to type commands.
Generally, if you need root level control over some resource, you just do it once for the time it is needed and then drop the privilege once the work is done. I typically write a small C code executable that does the privileged stuff, then call is as a command line argument for the su command with the "-c" argument:
Code:
Runtime.getRuntime().exec("su -c mycmd");
Now, mycmd runs, does what it needs to do, then exits returning full control to the app (no hang).
You need to use JNI or another toolchain to write command-line exe's for the device.
Here is the whole class.
Code:
public class SDSpeedShifterActivity extends Activity {
private final static File sdcard = Environment.getExternalStorageDirectory();
private static Process p = null;
private static TextView txtCurVal = null;
private static Spinner spinner = null;
private static StringBuilder sb = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
/**
* Set up the spinner for the buffer size
*/
spinner = (Spinner) findViewById(R.id.spKBSelect);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
this, R.array.KBs, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
txtCurVal = (TextView) findViewById(R.id.txtCurrentV);
try {
txtCurVal.setText(getString(R.string.cursetvalue) + " " + getCurrentValue() + " KB");
p = Runtime.getRuntime().exec("su");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* This handles all of the button clicks.
* @param v The view (Button) that was clicked.
* @throws Exception If something goes wrong.
*/
public void onClick(View v) throws Exception {
switch (v.getId()) {
case R.id.btnAbout:
Toast.makeText(this, "Created by: Ben Murphy (Smurph82)\nCreated on: 2011_0618", Toast.LENGTH_LONG).show();
break;
case R.id.btnSave:
DataOutputStream os = new DataOutputStream(p.getOutputStream());
DataInputStream osRes = new DataInputStream(p.getInputStream());
os.writeBytes("busybox cp " + getString(R.string.rakpath) + " " + sdcard + "/.sdspeedshifter\n");
os.flush();
os.writeBytes("busybox mv -f " + sdcard + "/.sdspeedshifter/read_ahead_kb " + " " + sdcard + "/.sdspeedshifter/read_ahead_kb_bak\n");
os.flush();
//writeNewValue(spinner.getSelectedItem().toString(), getString(R.string.rakpath));
os.writeBytes("echo \"" + spinner.getSelectedItem().toString() + "\" > " + getString(R.string.rakpath) + "\n");
os.flush();
os.writeBytes("exit\n");
os.flush();
//p.waitFor();
txtCurVal.setText(getString(R.string.cursetvalue) + " " + getCurrentValue() + " KB");
break;
default:
break;
}
}
/**
* Show the current read_ahead_kb value from the file.
* @param v The view (Textview) that needs to be changed.
* @throws IOException
*/
private final String getCurrentValue() throws IOException{
File rak = new File(getString(R.string.rakpath));
BufferedReader br = new BufferedReader(new FileReader(rak));
String line, vm = "";
while ((line = br.readLine()) != null) {
vm = line;
break;
}
return vm;
}
Thanks for the help.
So I assume it is the "busybox mv..." and/or "busybox cp ..." commands that need root permissions? Just change them to:
Code:
"su -c 'busybox mv ...'"
Search z4root source code in Google and have a good look at VirtualTerminal(in source code) and how to use it.
maybe you want to check out this one:
http://code.google.com/p/roottools/

How SEUS Flashing Works

OK, so been trying to figure out what happens when you use SEUS.
It checks for internet connection by loading this URL:
Code:
http://emma.extranet.sonyericsson.com/ns/no-cache
I've figured out quite a bit.
Sony Ericsson has implemented something called Tampered Device Service.
This checks if the devices has been tampered with.
This service works from this server:
Code:
tds.sonyericsson.com
Then for the actual firmware download.
This is done by downloading 2 *.ser.gz which tells SEUS what Software customization to get and is sessions specific.
The customization ser.gz file looks something like this:
Code:
CDA=1233-7027_NjKhzOzTUsfXvPg40lyh6aTl.ser.gz
And it's downloaded from:
Code:
emma.extranet.sonyericsson.com
It's done via some sort of search mechanism on the server.
That looks like this:
Code:
ns/usdoe1/2/script/search/TAC8=35941903/CDA=1233-7027_By5JACZqd1R7JOpLu6qvwK8N.ser.gz
After that it's downloading the actual firmware files.
They are downloaded in bin format which I haven't been able to unpack yet.
They are also downloaded from the emma server and is named something like:
Code:
277795427_k9ABo3YVh+8klYUKwllGLDcJ.bin - ~14.3 MB
277835617_ZpJseUr9e09U5h2Cz81+5vcT.bin ~149 MB
Then it does a netbios call which has some sort of HEX code.
And then check the Internet connection again:
Code:
http://emma.extranet.sonyericsson.com/ns/no-cache
Now it starts up a service called:
Code:
/fq/ServiceClientDbServlet
This service runs from this server:
Code:
ma3.extranet.sonyericsson.com
This last part is done twice in a row.
Inside one of the *ser.gz files is a *.ser file which contains some code and instructions. Some parts is encrypted but most of the code is not.
See the complete code in post #2
I don't quite know what to do with all this info yet.
But hopefully something useful will come of this.
Just wanted to share a bit of my knowledge, hope it's useful for some of you here.
Code:
import com.sonyericsson.cs.ma.tess.api.ServiceException;
import com.sonyericsson.cs.ma.tess.api.ServiceRuntimeException;
import com.sonyericsson.cs.ma.tess.api.TessFile;
import com.sonyericsson.cs.ma.tess.api.UI;
import com.sonyericsson.cs.ma.tess.api.device.IdentificationResult;
import com.sonyericsson.cs.ma.tess.api.inject.InjectConfigValue;
import com.sonyericsson.cs.ma.tess.api.inject.InjectRef;
import com.sonyericsson.cs.ma.tess.api.inject.IncludeFor;
import com.sonyericsson.cs.ma.tess.api.inject.ServiceMethod;
import com.sonyericsson.cs.ma.tess.api.logging.Logging;
import com.sonyericsson.cs.ma.tess.api.protocols.DataArea;
import com.sonyericsson.cs.ma.tess.api.protocols.ProtocolFactory;
import com.sonyericsson.cs.ma.tess.api.protocols.VersionResponse;
import com.sonyericsson.cs.ma.tess.api.protocols.s1.S1Protocol;
import com.sonyericsson.cs.ma.tess.api.protocols.s1.S1Protocol.ShutdownMode;
import com.sonyericsson.cs.ma.tess.api.secs.SECSUnitData;
import com.sonyericsson.cs.ma.tess.api.secs.SECSUtil;
import com.sonyericsson.cs.ma.tess.api.service.ServiceResult;
import com.sonyericsson.cs.ma.tess.api.service.ServiceResultType;
import com.sonyericsson.cs.ma.tess.api.service.ServiceType;
import com.sonyericsson.cs.ma.tess.api.statistics.DiagnosticsUtil;
import com.sonyericsson.cs.ma.tess.api.statistics.StatisticsUtil;
import com.sonyericsson.cs.ma.tess.api.statistics.StatisticsUtil.SoftwareComponent;
import com.sonyericsson.cs.ma.tess.api.ta.TAUnit;
import com.sonyericsson.cs.ma.tess.api.util.StringUtil;
import com.sonyericsson.cs.ma.tess.api.x10.MarlinCertificateUpdate;
import com.sonyericsson.cs.ma.tess.api.zip.ZipFileUtil;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.w3c.dom.Document;
/**
* S1 QSD8250 eSheep platform Main Services implementation.
*
* Services in this logic implemented for use in COMMERCIAL services!
*
*/
public class S1QSD8250eSheepMainServicesLIVE
{
@InjectRef
private ProtocolFactory aProtocolFactory;
@InjectRef
private UI aUI;
@InjectRef
private Logging aLogger;
@InjectRef
private IdentificationResult aIdentifiers;
@InjectRef
private ZipFileUtil aZipFileUtil;
@InjectRef
private static DiagnosticsUtil aDiagnostics;
@InjectRef
private StatisticsUtil aStatistics;
@InjectRef
private SECSUtil aSECS;
@InjectRef
private StringUtil aStringUtil;
@InjectRef
private ClientEnvironment aClientEnvironment;
@InjectRef
private MarlinCertificateUpdate marlinCertUpdate;
// File references
// Loader reference
@InjectConfigValue("cLOADER")
private TessFile aLoader;
// App-SW reference - Exclude from Activation
@IncludeFor([ServiceType.CUSTOMIZE, ServiceType.SOFTWARE_UPDATE,
ServiceType.SOFTWARE_UPDATE_CONTENT_REFRESH])
@InjectConfigValue("cAPP_SW")
private TessFile aAppSW;
// FSP Reference - Exclude from Activation
@IncludeFor([ServiceType.CUSTOMIZE, ServiceType.SOFTWARE_UPDATE,
ServiceType.SOFTWARE_UPDATE_CONTENT_REFRESH])
@InjectConfigValue("cFSP")
private TessFile aFSP;
// miscTA units
// Startup/Shutdown flag used for indicating successful flash.
@InjectConfigValue("cTA_FLASH_STARTUP_SHUTDOWN_RESULT")
private String aStrTaFlashStartShutdownResult;
// Startup/Shutdown flag used for indicating successful flash.
@InjectConfigValue("cTA_EDREAM_FLASH_IN_PROGRESS")
private String aStrTaEDreamFlashStartShutdownResult;
// SIMlock data unit
@InjectConfigValue("cTA_SIMLOCK_DATA")
private String aStrTaSimlockData;
// Loose temp data unit
@InjectConfigValue("cTA_LOOSE_TEMP")
private String aStrTaLooseTemp;
// TA_APPLICATION_BUFFER_DATA_ARRAY[2]
@InjectConfigValue("cTA_APPLICATION_BUFFER_DATA_ARRAY2")
private String aStrTaApplicationBufferDataArray2;
// TA_APPLICATION_BUFFER_DATA_ARRAY[3]
@InjectConfigValue("cTA_APPLICATION_BUFFER_DATA_ARRAY3")
private String aStrTaApplicationBufferDataArray3;
// TA_MARLIN_DRM_KEY_UPDATE_FLAG
@InjectConfigValue("cTA_MARLIN_DRM_KEY_UPDATE_FLAG")
private String aStrTaMarlinDRMKeyUpdateFlag;
// Parameter names
@InjectConfigValue("cTA_APPLICATION_BUFFER_DATA_ARRAY0_NAME")
private String aTaApplicationBufferDataArray0Name;
@InjectConfigValue("cTA_APPLICATION_BUFFER_DATA_ARRAY1_NAME")
private String aTaApplicationBufferDataArray1Name;
@InjectConfigValue("cTA_APPLICATION_BUFFER_DATA_ARRAY2_NAME")
private String aTaApplicationBufferDataArray2Name;
@InjectConfigValue("cTA_APPLICATION_BUFFER_DATA_ARRAY3_NAME")
private String aTaApplicationBufferDataArray3Name;
@InjectConfigValue("cTA_SIMLOCK_DATA_NAME")
private String aTaSimlockDataName;
@InjectConfigValue("cTA_LOOSE_TEMP_NAME")
private String aTaLooseTempName;
@InjectConfigValue("cVERSION_RESPONSE")
private String aVersionResponseName;
// miscTA unit values
// Startup/Shutdown flag, cTA_FLASH_STARTUP_SHUTDOWN_RESULT, values
@InjectConfigValue("cTA_FLASH_STARTUP_SHUTDOWN_RESULT_ONGOING_VALUE")
private String aTaFlashStartupShutdownResultOngoingValue;
@InjectConfigValue("cTA_FLASH_STARTUP_SHUTDOWN_RESULT_FINISHED_VALUE")
private String aTaFlashStartupShutdownResultFinishedValue;
// Startup/Shutdown flag, cTA_EDREAM_FLASH_STARTUP_SHUTDOWN_RESULT, values
@InjectConfigValue("cTA_EDREAM_FLASH_FLASH_IN_PROGRESS_ONGOING")
private String aTaEDreamFlashStartupShutdownResultOngoingValue;
@InjectConfigValue("cTA_EDREAM_FLASH_FLASH_IN_PROGRESS_COMPLETED")
private String aTaEDreamFlashStartupShutdownResultFinishedValue;
// Update.xml values
// File name
private static String UPDATE_XML_FILE_NAME = "update.xml";
// NOERASE tag value
private static String UPDATE_XML_NOERASE_TAG = "NOERASE";
// SIMLOCK tag value
private static String UPDATE_XML_SIMLOCK_TAG = "SIMLOCK";
// PRESERVECACHE tag value
private static String UPDATE_XML_PRESERVECACHE_TAG = "PRESERVECACHE";
// UI Progress texts
@InjectConfigValue("cSEND_DATA")
private String aSendDataText;
@InjectConfigValue("cSEND_DATA_DONE")
private String aSendDataDoneText;
@InjectConfigValue("cSERVICE_FINALIZING")
private String aServiceFinalizingText;
@InjectConfigValue("cSERVICE_FINALIZING_DONE")
private String aServiceFinalizingDoneText;
@InjectConfigValue("cSERVICE_INITIALIZATION")
private String aServiceInitializationText;
@InjectConfigValue("cSERVICE_INITIALIZATION_DONE")
private String aServiceInitializationDoneText;
/**
* ACTIVATION
*
*/
@ServiceMethod(ServiceType.ACTIVATION)
public ServiceResult activation() throws ServiceException
{
boolean vDoActivation = true;
showInitServiceText();
try
{
S1Protocol vS1 = aProtocolFactory.getProtocol(S1Protocol.class);
int vTaSimlockData = Integer.parseInt(aStrTaSimlockData);
int vTaLooseTemp = Integer.parseInt(aStrTaLooseTemp);
int vTaApplicationBufferDataArray2 =
Integer.parseInt(aStrTaApplicationBufferDataArray2);
int vTaApplicationBufferDataArray3 =
Integer.parseInt(aStrTaApplicationBufferDataArray3);
// Check if activation is needed?
// Send loader
vS1.sendFile(aLoader);
vS1.openDataArea(DataArea.MISC_TA);
// Read the SIMlock data from TA_SIMLOCK_DATA
byte[] vSIMlockData = vS1.readDataArea(vTaSimlockData);
if (vSIMlockData != null && vSIMlockData.length >= 20)
{
// Check 20 first bytes (if set to 0)
for (int vI = 0; vI < 20; vI++)
{
if (vSIMlockData[vI] != 0)
{
vDoActivation = false;
break;
}
}
}
else
{
aLogger
.error("Could not determine if activation is needed. Not possible to read enough data.");
throw new ServiceRuntimeException("Error when activating phone.");
}
// Do activation?
if (vDoActivation)
{
// Verify that the dongle is present
aSECS.ensureDongleReady();
String vIMEI = aIdentifiers.getIMEI();
SECSUnitData[] vInputData = getS1SIMLockSignatureInputData(vS1);
SECSUnitData[] vOutputData =
vS1.getS1SIMLockSignature(vInputData, vIMEI);
if (vOutputData != null && vOutputData.length > 6)
{
byte[] vEmpty = new byte[1];
vEmpty[0] = 0x00;
vS1.writeToDataArea(vTaApplicationBufferDataArray2, vEmpty);
vS1.writeToDataArea(
vTaApplicationBufferDataArray3,
vOutputData[3].getUnitData());
vS1
.writeToDataArea(vTaSimlockData, vOutputData[4]
.getUnitData());
vS1.writeToDataArea(vTaLooseTemp, vOutputData[5].getUnitData());
}
else
{
aLogger.error("Not enough data in response from SECS server.");
throw new ServiceRuntimeException(
"Error occured when communicating with server.");
}
}
else
{
aUI
.showText("ACTIVATION NOT NEEDED! This unit has been "
+ "activated already. The service is exiting without execution.");
}
showFinalizingText();
vS1.closeDataArea();
vS1.shutdownDevice(ShutdownMode.DISCONNECT);
}
catch (ServiceException pEx)
{
aLogger.error("Exception when executing ACTIVATION service.", pEx);
throw pEx;
}
return ServiceResult.SUCCESSFUL;
}
/**
* CUSTOMIZE
*
*/
@ServiceMethod(ServiceType.CUSTOMIZE)
public ServiceResult customize() throws ServiceException
{
showInitServiceText();
ServiceResult vServiceResult =
new ServiceResult(
ServiceResultType.SUCCESSFUL,
"Customize EXECUTED! ACTIVATION NEEDED!",
null);
try
{
S1Protocol vS1 = aProtocolFactory.getProtocol(S1Protocol.class);
int vTaSimlockData = Integer.parseInt(aStrTaSimlockData);
int vTaLooseTemp = Integer.parseInt(aStrTaLooseTemp);
showSendingDataText();
// Send loader
vS1.sendFile(aLoader);
vS1.openDataArea(DataArea.MISC_TA);
readDID(vS1);
updateMartinKey(vS1);
setFlashStartupShutdownFlagOngoing(vS1);
// Send App-SW
sendFile(vS1, aAppSW);
// Send FSP
if ("false".equalsIgnoreCase(aFSP.getProperty("SIMLockCustomized"))
&& "true".equalsIgnoreCase(aIdentifiers
.getIdentifier("SIMLockReusable")))
{
// quick-customize
String[] vExcludeTags = new String[1];
vExcludeTags[0] = UPDATE_XML_SIMLOCK_TAG;
String[] vFilesToExcludeFromFSP = parseFile(aFSP, vExcludeTags);
// Send FSP
sendZipFile(vS1, aFSP, vFilesToExcludeFromFSP);
vServiceResult =
new ServiceResult(
ServiceResultType.SUCCESSFUL,
"Quick Customize EXECUTED! NO ACTIVATION NEEDED!",
null);
}
else
{
// customize
// Tamper the simlock data
tamperSimlockData(vS1);
// Set the simlock data unit id to loose temp
aFSP.modifyData(vTaSimlockData, vTaLooseTemp);
sendFile(vS1, aFSP);
}
setFlashStartupShutdownFlagFinished(vS1);
showSendingDataTextDone();
showFinalizingText();
vS1.closeDataArea();
vS1.shutdownDevice(ShutdownMode.DISCONNECT);
storeSoftwareAfterStatistics();
}
catch (ServiceException pEx)
{
aLogger.error("Exception when executing CUSTOMIZE service.", pEx);
throw pEx;
}
return vServiceResult;
}
/**
* SOFTWARE UPDATE
*
*/
@ServiceMethod(ServiceType.SOFTWARE_UPDATE)
public ServiceResult softwareUpdate() throws ServiceException
{
showInitServiceText();
try
{
S1Protocol vS1 = aProtocolFactory.getProtocol(S1Protocol.class);
showSendingDataText();
// Send loader
vS1.sendFile(aLoader);
vS1.openDataArea(DataArea.MISC_TA);
readDID(vS1);
updateMartinKey(vS1);
// Search the APP-SW zip file for xml file and metadata. Exclude user
// data
String[] vExcludeTags = new String[1];
vExcludeTags[0] = UPDATE_XML_NOERASE_TAG;
String[] vFilesToExcludeFromAPPSW = parseFile(aAppSW, vExcludeTags);
// Search the FSP zip file for xml file and metadata. Exclude user data
// and simlock if existing
vExcludeTags = new String[2];
vExcludeTags[0] = UPDATE_XML_NOERASE_TAG;
vExcludeTags[1] = UPDATE_XML_SIMLOCK_TAG;
String[] vFilesToExcludeFromFSP = parseFile(aFSP, vExcludeTags);
setFlashStartupShutdownFlagOngoing(vS1);
// Send App-SW
// Anything to exclude?
if (vFilesToExcludeFromAPPSW != null
&& vFilesToExcludeFromAPPSW.length > 0)
{
sendZipFile(vS1, aAppSW, vFilesToExcludeFromAPPSW);
}
else
{
sendFile(vS1, aAppSW);
}
// Send FSP
sendZipFile(vS1, aFSP, vFilesToExcludeFromFSP);
setFlashStartupShutdownFlagFinished(vS1);
showSendingDataTextDone();
showFinalizingText();
vS1.closeDataArea();
vS1.shutdownDevice(ShutdownMode.DISCONNECT);
storeSoftwareAfterStatistics();
}
catch (ServiceException pEx)
{
aLogger
.error("Exception when executing SOFTWARE UPDATE service.", pEx);
throw pEx;
}
return ServiceResult.SUCCESSFUL;
}
/**
* SOFTWARE UPDATE CONTENT REFRESH
*
*/
@ServiceMethod(ServiceType.SOFTWARE_UPDATE_CONTENT_REFRESH)
public ServiceResult softwareUpdateContentRefresh() throws ServiceException
{
showInitServiceText();
try
{
S1Protocol vS1 = aProtocolFactory.getProtocol(S1Protocol.class);
showSendingDataText();
// Send loader
vS1.sendFile(aLoader);
vS1.openDataArea(DataArea.MISC_TA);
readDID(vS1);
updateMartinKey(vS1);
// Search the FSP zip file for xml file and metadata. Exclude
// simlock if existing
String[] vExcludeTags = new String[0];
aLogger.debug("isSwapEnabled is: "
+ aClientEnvironment.isSwapEnabled());
// Check the client environment.
if (!aClientEnvironment.isSwapEnabled())
{
aLogger.debug("Cache partition will be preserved.");
vExcludeTags = new String[1];
vExcludeTags[0] = UPDATE_XML_PRESERVECACHE_TAG;
}
// Temporarily catch the exception
String[] vFilesToExcludeFromAPPSW = parseFile(aAppSW, vExcludeTags);
vExcludeTags = new String[1];
vExcludeTags[0] = UPDATE_XML_SIMLOCK_TAG;
String[] vFilesToExcludeFromFSP = parseFile(aFSP, vExcludeTags);
setFlashStartupShutdownFlagOngoing(vS1);
// Anything to exclude?
if (vFilesToExcludeFromAPPSW != null
&& vFilesToExcludeFromAPPSW.length > 0)
{
sendZipFile(vS1, aAppSW, vFilesToExcludeFromAPPSW);
}
else
{
sendFile(vS1, aAppSW);
}
// Send FSP
sendZipFile(vS1, aFSP, vFilesToExcludeFromFSP);
setFlashStartupShutdownFlagFinished(vS1);
showSendingDataTextDone();
showFinalizingText();
vS1.closeDataArea();
vS1.shutdownDevice(ShutdownMode.DISCONNECT);
storeSoftwareAfterStatistics();
}
catch (ServiceException pEx)
{
aLogger
.error(
"Exception when executing SOFTWARE UPDATE CONTENT REFRESH service.",
pEx);
throw pEx;
}
return ServiceResult.SUCCESSFUL;
}
/**
* Private help method to get DID data from device, if available.
*
*/
private void readDID(S1Protocol pS1)
{
byte[] vEmptyUnit = new byte[0];
List<TAUnit> vUnits = new ArrayList<TAUnit>();
aLogger.debug("Reading diagnostic data.");
final int vLastUnit = 10009;
final int vFirstUnit = 10000;
for (int vUnit = vFirstUnit; vUnit <= vLastUnit; vUnit++)
{
try
{
byte[] vData = pS1.readDataArea(vUnit);
if (vData != null && vData.length > 0)
{
pS1.writeToDataArea(vUnit, vEmptyUnit);
vUnits.add(new TAUnit(vUnit, vData));
}
}
catch (ServiceException vServiceException)
{
}
}
if (vUnits.size() > 0)
{
byte[] vDiagnosticData;
try
{
aLogger.debug("Diagnostic data found, sending diagnostic data.");
vDiagnosticData = aDiagnostics.createDiagnosticData(vUnits);
aDiagnostics.storeDiagnostic(aIdentifiers.getIMEI(), aIdentifiers
.getApplicationSoftwareID(), aIdentifiers
.getApplicationSoftwareRev(), vDiagnosticData, "06");
}
catch (ServiceException pEx)
{
}
}
}
/**
* Private help method to tamper the simlock data.
*
*/
private void tamperSimlockData(S1Protocol pS1) throws ServiceException
{
int vTaSimlockData = Integer.parseInt(aStrTaSimlockData);
// Read the SIMlock data from TA_SIMLOCK_DATA
byte[] vSIMlockData = pS1.readDataArea(vTaSimlockData);
if (vSIMlockData != null && vSIMlockData.length > 0)
{
// Tamper 20 first bytes (set to 0)
// Make sure enough data is read
if (vSIMlockData.length >= 20)
{
for (int vI = 0; vI < 20; vI++)
{
vSIMlockData[vI] = 0;
}
}
else
{
throw new ServiceRuntimeException(
"Data read, but not enough to tamper.");
}
// Write back the tampered SIMlock data to TA_SIMLOCK_DATA
pS1.writeToDataArea(vTaSimlockData, vSIMlockData);
}
else
{
throw new ServiceRuntimeException("Could not read data.");
}
}
/**
* Private help method to get S1 SIMlock signature input data from device.
*
*/
private SECSUnitData[] getS1SIMLockSignatureInputData(S1Protocol pS1)
throws ServiceException
{
SECSUnitData[] vSECSUnitData = new SECSUnitData[7];
int vTaSimlockData = Integer.parseInt(aStrTaSimlockData);
int vTaLooseTemp = Integer.parseInt(aStrTaLooseTemp);
int vTaApplicationBufferDataArray3 =
Integer.parseInt(aStrTaApplicationBufferDataArray3);
byte[] vEmpty = new byte[1];
vEmpty[0] = 0x00;
vSECSUnitData[0] =
new SECSUnitData(aTaApplicationBufferDataArray0Name, vEmpty);
vSECSUnitData[1] =
new SECSUnitData(aTaApplicationBufferDataArray1Name, vEmpty);
vSECSUnitData[2] =
new SECSUnitData(aTaApplicationBufferDataArray2Name, vEmpty);
byte[] vInputUnitData = pS1.readDataArea(vTaApplicationBufferDataArray3);
vSECSUnitData[3] =
new SECSUnitData(aTaApplicationBufferDataArray3Name, vInputUnitData);
vInputUnitData = pS1.readDataArea(vTaSimlockData);
vSECSUnitData[4] = new SECSUnitData(aTaSimlockDataName, vInputUnitData);
vInputUnitData = pS1.readDataArea(vTaLooseTemp);
vSECSUnitData[5] = new SECSUnitData(aTaLooseTempName, vInputUnitData);
VersionResponse vVersionResponse = pS1.getVersionResponse();
byte[] vVersionResponseArray =
vVersionResponse.getVersionResponseAsBytes();
vInputUnitData = vVersionResponseArray;
vSECSUnitData[6] = new SECSUnitData(aVersionResponseName, vInputUnitData);
return vSECSUnitData;
}
/**
* Parses the specified file for a xml metadata file and the parses the xml
* file for the tags defined. Tag values are then returned as a string array.
*
*/
private String[] parseFile(TessFile pFile, String[] pTags)
throws ServiceException
{
ArrayList<String> vResult = new ArrayList<String>();
Document vUpdateXML =
aZipFileUtil.getXMLFile(pFile, UPDATE_XML_FILE_NAME);
if (vUpdateXML != null)
{
if (pTags != null)
{
for (String vTag : pTags)
{
String[] vFilesFound =
aZipFileUtil.getXMLTextContentByTagName(vUpdateXML, vTag);
if (vFilesFound != null && vFilesFound.length > 0)
{
aLogger.debug("Found files to exclude from "
+ pFile.getFileName()
+ " from tag "
+ vTag
+ " in "
+ UPDATE_XML_FILE_NAME
+ ":");
for (String vFileName : vFilesFound)
{
aLogger.debug(vFileName);
}
vResult.addAll(Arrays.asList(vFilesFound));
}
}
}
}
else
{
aLogger.debug("No " + UPDATE_XML_FILE_NAME + " found");
// throw new
throw new ServiceRuntimeException("Could not find a "
+ UPDATE_XML_FILE_NAME
+ " in the zip file, abort.");
}
return vResult.toArray(new String[vResult.size()]);
}
private void updateMartinKey(S1Protocol pS1) throws ServiceException
{
int vTaMarlinDRMKeyUpdateFlag =
Integer.parseInt(aStrTaMarlinDRMKeyUpdateFlag);
byte[] vFlagValue = null;
pS1.openDataArea(DataArea.MISC_TA);
// check the flag
try
{
vFlagValue = pS1.readDataArea(vTaMarlinDRMKeyUpdateFlag);
if (vFlagValue != null
&& aStringUtil
.convertByteArrayToString(vFlagValue)
.equalsIgnoreCase("01"))
{
// updated already
return;
}
}
catch (ServiceException vServiceException)
{
// exception indicates no update has been done
}
// check if update is available for this unit
if (marlinCertUpdate.isNewCertificateAvailable())
{
// update the cert
InputStream vTAFileInputStream =
marlinCertUpdate.getCertificateTAInputStream();
pS1.sendTAFileFromStream(vTAFileInputStream);
aLogger.debug("Marlin key updated.");
}
// set the flag as updated
pS1.writeToDataArea(vTaMarlinDRMKeyUpdateFlag, aStringUtil
.convertStringToByteArray("0x01"));
return;
}
/**
* Private help method to set the flash ongoing flag to ongoing.
*
* @throws ServiceException
*
*/
private void setFlashStartupShutdownFlagOngoing(S1Protocol pS1)
throws ServiceException
{
int vTaFlashStartupShutdownResult =
Integer.parseInt(aStrTaFlashStartShutdownResult);
int vTaEDreamFlashStartupShutdownResult =
Integer.parseInt(aStrTaEDreamFlashStartShutdownResult);
// Set the TA_FLASH_STARTUP_SHUTDOWN_RESULT (2227) flag to 0xA0000000 to
// indicate
// flash ongoing
pS1
.writeToDataArea(
vTaFlashStartupShutdownResult,
aStringUtil
.convertStringToByteArray(aTaFlashStartupShutdownResultOngoingValue));
// Set the 10100 flag specific for eDream
// Set the TA_EDREAM_FLASH_STARTUP_SHUTDOWN_RESULT (10100) flag to 0x01 to
// indicate
// flash ongoing
pS1
.writeToDataArea(
vTaEDreamFlashStartupShutdownResult,
aStringUtil
.convertStringToByteArray(aTaEDreamFlashStartupShutdownResultOngoingValue));
}
/**
* Private help method to set the flash ongoing flag to finished.
*
* @throws ServiceException
*
*/
private void setFlashStartupShutdownFlagFinished(S1Protocol pS1)
throws ServiceException
{
int vTaFlashStartupShutdownResult =
Integer.parseInt(aStrTaFlashStartShutdownResult);
int vTaEDreamFlashStartupShutdownResult =
Integer.parseInt(aStrTaEDreamFlashStartShutdownResult);
// Set the TA_FLASH_STARTUP_SHUTDOWN_RESULT (2227) flag to 0xAA000000 to
// indicate
// flash finished
pS1
.writeToDataArea(
vTaFlashStartupShutdownResult,
aStringUtil
.convertStringToByteArray(aTaFlashStartupShutdownResultFinishedValue));
// Set the 10100 flag specific for eDream
// Set the TA_EDREAM_FLASH_STARTUP_SHUTDOWN_RESULT (10100) flag to 0x00 to
// indicate flash finished
pS1
.writeToDataArea(
vTaEDreamFlashStartupShutdownResult,
aStringUtil
.convertStringToByteArray(aTaEDreamFlashStartupShutdownResultFinishedValue));
}
/**
* Private help method to store software and CDF ids and versions.
*
*/
private void storeSoftwareAfterStatistics()
{
String vAPPSWId = aAppSW.getProperty("Id");
String vAPPSWVer = aAppSW.getVersion();
String vCDFId = aFSP.getProperty("CDFId");
String vCDFVer = aFSP.getProperty("CDFVer");
if (vAPPSWId != null)
{
aStatistics.storeSoftwareAfter(
SoftwareComponent.SW1,
vAPPSWId,
vAPPSWVer);
}
if (vCDFId != null)
{
aStatistics.storeCustomizationAfter(vCDFId, vCDFVer);
}
}
private void sendZipFile(
S1Protocol pS1,
TessFile pFile,
String[] pFilesToExclude) throws ServiceException
{
aLogger.debug("Sending "
+ pFile.getFileName()
+ ", "
+ pFile.getVersion());
pS1.sendZipFile(pFile, pFilesToExclude);
}
private void sendFile(S1Protocol pS1, TessFile pFile)
throws ServiceException
{
aLogger.debug("Sending "
+ pFile.getFileName()
+ ", "
+ pFile.getVersion());
pS1.sendFile(pFile);
}
/**
* Private help method to display start sending data text.
*
*/
private void showSendingDataText()
{
aUI.showText(aSendDataText);
}
/**
* Private help method to display start sending data done text.
*
*/
private void showSendingDataTextDone()
{
aUI.showText(aSendDataDoneText);
}
/**
* Private help method to display start up and initialization text.
*
*/
private void showInitServiceText()
{
aUI.showText(aServiceInitializationText);
aUI.showText(aServiceInitializationDoneText);
aUI.showText("");
}
/**
* Private help method to display please wait text.
*
*/
private void showFinalizingText()
{
aUI.showText("");
aUI.showText(aServiceFinalizingText);
aUI.showText(aServiceFinalizingDoneText);
}
}
Reserved for future use.
wow seems u done some packet sniffing...
may be u should contact Bin4ry regarding this... he is involved in FreeXperia Project for Arc/Play...
i am sure he can shed some more light on this matter...
Figured out the *.bin files is the actual files that also goes in the blob_fs folder:
Code:
%programfiles%\Sony Ericsson\Update Service\db\
So they are decryptable using the known method.
Tampered Device Service does in fact check for Root and custom software.
Don't know if this will have an effect in the updating process from SEUS.
So, it's a bad news huh. Keep looking. Thanks for the info.
Sent from my X10i using XDA App
Confirmed that devices that has been rooted and modified in software will not be eligible for 2.3.3 update. You will have to flash back a stock unrooted firmware before updating to 2.3.3
Of course. SE said that in their blog. Better backup all data in SD Card and format it too. I don't think the SEUS' intelligent enough to check out that the SD Card contains CyanogenMod folder as busybox and xRecovery
EDIT: I tried to find the update 2.1 package in my computer after repaired my phone for several times and I can't find it. It's of course that it's deleted as soon as the update completed.
I believe SEUS works like the Flash Tool and Pay-Per-Update service through fastgsm.com and davince.
Flash Tool requires you to provide the firmware and place the sin files in the correct location.
Pay service requires a fee to install the correct sin files/firmware.
SEUS requires a CDA to determine which sin files/firmware to install.
I beg that the FlashTool works like SEUS cause without SEUS and other update services, where is FlashTool come from?
But what if SEUS change its method? Well, i still want to update and we will see how it goes.
Sent from my X10i using XDA App
Whatever method they choose, they can't close the door behind them. They need the access too. Flash Tool can be updated.
Nor would google allow that. JMHO
Yes, FT can be updated but it's development is kinda dead as of now, and we don't even have its source codes, so the other developers can't update it. Unless if Androxyde and Bin4ry want to work on FT again.
Hzu said:
Yes, FT can be updated but it's development is kinda dead as of now, and we don't even have its source codes, so the other developers can't update it. Unless if Androxyde and Bin4ry want to work on FT again.
Click to expand...
Click to collapse
Why are the devs acting like this is an issue? The Flash Tool already works on the ARC, so what are you worried about?
Work on Arc no mean it can work on X10, just like Arc has bootloader unlocked but no mean X10 can when update to 2.3.3
silveraero said:
Work on Arc no mean it can work on X10, just like Arc has bootloader unlocked but no mean X10 can when update to 2.3.3
Click to expand...
Click to collapse
You totally missed the point. The bootloader or root has NEVER mattered. When the NEVER has happened, then start your *****ing.
agentJBM said:
Why are the devs acting like this is an issue? The Flash Tool already works on the ARC, so what are you worried about?
Click to expand...
Click to collapse
What I mean is that IF SE changed their flashing method for the GB firmware and FT won't work for those who upgraded their X10 to GB. But another user has said that they won't since it requires them to start all over again.
Who knows, we're not the one who are developing the firmwares and we all should stop making assumptions(but some people aren't making assumptions, they are so sure they are right).
Hzu said:
What I mean is that IF SE changed their flashing method for the GB firmware and FT won't work for those who upgraded their X10 to GB. But another user has said that they won't since it requires them to start all over again.
Who knows, we're not the one who are developing the firmwares and we all should stop making assumptions(but some people aren't making assumptions, they are so sure they are right).
Click to expand...
Click to collapse
I am not pretending to know. However, you are failing to acknowledge that the Flash Tool is a modification of Update Service. The same method is used. Quit acting like this is nuclear science.
I told you, what IF they CHANGE the flashing method, then SEUS will also be updated with the new method.
Why am I repeating this anyway? Silly me.

Interested in toggling a value in the build.prop

So in my toolkit, id like to design an activity where I could point it towards certain lines in the build.prop to allow a user to easily toggle, for instance this line
qemu.hw.mainkeys=0
So, in the layout xml, lets say it had "Enable Nav Bar" and a "Toggle Button" for on/off
Where would i start in developing such a feature?
You create a ToggleButton and whenever it is clicked, you change the line.
What is your problem?
nikwen said:
You create a ToggleButton and whenever it is clicked, you change the line.
What is your problem?
Click to expand...
Click to collapse
My concerns are wouldnt I need to add ro permissions on the prop before toggling and a reboot action to apply
I think your device needs to be rooted to be able to write to the build.prop file. You do not need root access to read it though
I'm from mobile and i can't post some code but i will give you some hints
To edit build.prop programmatically first you ne ed to be rooted then you can use the shell command "sed" to exchange values. Take a look at AOKP settings source on github and look for density changer class
If you want to import various build properties you can use fileinputstream and read the file line by line then let the app create listview custom items for every line in the file (you need a custom adapter) .
Sorry if this post it's not really useful but i will edit this when at PC
Sent from my HTC One X using Tapatalk 4 Beta
Thankyou for the tip! The answer might of been infront of my face possibly...
Sent from my 9300 using xda app-developers app
xcesco89 said:
I'm from mobile and i can't post some code but i will give you some hints
To edit build.prop programmatically first you ne ed to be rooted then you can use the shell command "sed" to exchange values. Take a look at AOKP settings source on github and look for density changer class
If you want to import various build properties you can use fileinputstream and read the file line by line then let the app create listview custom items for every line in the file (you need a custom adapter) .
Sorry if this post it's not really useful but i will edit this when at PC
Sent from my HTC One X using Tapatalk 4 Beta
Click to expand...
Click to collapse
I Wrote something up but I keep getting force closes "Not a java code monkey yet, still learning" and Ill post here what I have when I get to my pc later. Maybe you can see what Im missing or did wrong. What I did is I have a preference screen similiar to AOKP density changer class. What Im going for is a PreferenceList that you click and your values are Enable or Disabled and another preference to reboot to apply settings. Im wanting to allow the user to enable and disable the Navigation Bar by toggling it through the build.prop. If this works, I want to add more toggles custom values like change your phone model, Screen Density, build number, ect; but figured Id start with something simpler first and see if it works.
Sent from my Alps9300 using Tapatalk
Nx Biotic said:
I Wrote something up but I keep getting force closes "Not a java code monkey yet, still learning" and Ill post here what I have when I get to my pc later. Maybe you can see what Im missing or did wrong. What I did is I have a preference screen similiar to AOKP density changer class. What Im going for is a PreferenceList that you click and your values are Enable or Disabled and another preference to reboot to apply settings. Im wanting to allow the user to enable and disable the Navigation Bar by toggling it through the build.prop. If this works, I want to add more toggles custom values like change your phone model, Screen Density, build number, ect; but figured Id start with something simpler first and see if it works.
Sent from my Alps9300 using Tapatalk
Click to expand...
Click to collapse
this is the method you need:
Code:
private void setLcdDensity(int newDensity) {
Helpers.getMount("rw");
new CMDProcessor().su.runWaitFor("busybox sed -i 's|ro.sf.lcd_density=.*|"
+ "ro.sf.lcd_density" + "=" + newDensity + "|' " + "/system/build.prop");
Helpers.getMount("ro");
}
( method took from here : https://github.com/TeamBAKED/packag...aked/romcontrol/fragments/DensityChanger.java )
newDensity is the int/string you let the user set ( you can use a seekbar or a dialog or what you prefer)
you have also CMDProcessor().su.runWaitFor : just use the classes you can find here : https://github.com/TeamBAKED/packag...11bca71808c9143/src/com/baked/romcontrol/util
just add these classes in your project ( these are to simplify your life when you need to use android terminal [ remember to give credits on your app! ] )
Now, you can use various types of views and methods to show to the user all the available props:
- manually add every view for every line in your build.prop ( this will probably limit the compatibility with other devices and make your app "laggy" due to "gazilions" views )
- use a blank linearLayout and inflate a "row view" for every line in build.prop:
read file line by line and import every line in an ArrayList:
Code:
ArrayList<String> Tokens = new ArrayList<String>();
try {
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream("/system/build.prop");
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
// Read File Line By Line
while ((strLine = br.readLine()) != null) {
strLine = strLine.trim();
if ((strLine.length()!=0)) {
String[] names = strLine.split("\\s+");
Tokens.add(names[0]);
}
}
for (String s : Tokens) {
//System.out.println(s);
//Log.d("NNNNNNNNNNNNNNNNNN", s);
}
// Close the input stream
in.close();
} catch (Exception e) {// Catch exception if any
System.err.println("Error: " + e.getMessage());
}
names = new String[Tokens.size()-1];
names = Tokens.toArray(names);
ArrayList<String> value = new ArrayList<String>();
try {
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream("/sys/devices/system/cpu/cpu0/cpufreq/UV_mV_table");
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
// Read File Line By Line
while ((strLine = br.readLine()) != null) {
strLine = strLine.trim();
if ((strLine.length()!=0)) {
String[] val = strLine.split("\\s+");
value.add(val[1]);
}
}
for (String s : value) {
//System.out.println(s);
//Log.d("NNNNNNNNNNNNNNNNNN", s);
}
// Close the input stream
in.close();
} catch (Exception e) {// Catch exception if any
System.err.println("Error: " + e.getMessage());
}
values = new String[value.size()-1];
values = value.toArray(values);
LineNumberReader lnr = null;
try {
lnr = new LineNumberReader(new FileReader(new File("/sys/devices/system/cpu/cpu0/cpufreq/UV_mV_table")));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
lnr.skip(Long.MAX_VALUE);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int num = lnr.getLineNumber();
Log.d("LINES", ""+num);
int i = 0;
//now inflate a specific view for every line
// you can also filter every item for example by reading the string and inflating a different layout using an if statement
for (String s : names) {
LayoutInflater inflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View v = inflater.inflate(R.layout.uvrow, null, true);
TextView text0 = (TextView) v.findViewById(R.id.text0);
ImageButton back0 = (ImageButton) v.findViewById(R.id.back0);
final EditText edit0 = (EditText) v.findViewById(R.id.edit0);
ImageButton fwd0 = (ImageButton) v.findViewById(R.id.fwd0);
text0.setText(s);
parentGroup.addView(v);
edit0.setText(values[i]);
/*
* if you need to set listeners and actions insert them inside this loop!
*/
}
if you need more informations, take a look at my code on github ( was my first "really useful" app ): https://github.com/cesco89/CustomSettings/blob/master/src/com/cesco/customsettings/UVTable.java
it's not perfect, could be tricky, but i can't post all the code here
This Is what I put together...Excuse any errors in java...Im new at this. When I start this fragment, I get a force close. What did I do?
Code:
package com.bionx.res.catalyst;
import android.content.Context;
import android.os.Bundle;
import android.os.PowerManager;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceFragment;
import com.bionx.res.R;
import com.bionx.res.helpers.CMDProcessor;
import com.bionx.res.helpers.Helpers;
public abstract class Navbar extends PreferenceFragment implements OnPreferenceChangeListener {
Preference mReboot;
ListPreference mStockValue;
int newStockValue;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.navbarchanger);
mStockValue = (ListPreference) findPreference("stock_value");
mStockValue.setOnPreferenceChangeListener(this);
mReboot = findPreference("reboot");
}
public boolean onPreference(Preference preference) {
if (preference == mReboot) {
PowerManager pm = (PowerManager) getActivity()
.getSystemService(Context.POWER_SERVICE);
pm.reboot("Setting Navbar");
}
return false;
}
[user=439709]@override[/user]
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference == mStockValue) {
newStockValue = Integer.parseInt((String) newValue);
setNavbarValue(newStockValue);
mStockValue.setSummary(getResources().getString(R.string.navbar_changer) + newStockValue);
return true;
}
return false;
}
private void setNavbarValue(int newNavbar) {
Helpers.getMount("rw");
new CMDProcessor().su.runWaitFor("busybox sed -i 's|qemu.hw.mainkeys=.*|"
+ "qemu.hw.mainkeys" + "=" + newNavbar + "|' " + "/system/build.prop");
Helpers.getMount("ro");
}
}
Code:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<Preference
android:title="System Properties"
android:summary="User System Tweaks" />
<ListPreference
android:entries="@array/navbar_stock_entries"
android:entryValues="@array/navbar_stock_values"
android:key="stock_value"
android:title="NavBar Enabler"
android:summary="Toggle the system navbar" />
<Preference
android:key="reboot"
android:title="Reboot"
android:summary="Applies tweaks and reboots" />
</PreferenceScreen>
Where I launch the fragment.
Code:
...
<header
android:fragment="com.bionx.res.catalyst.Navbar"
android:icon="@drawable/ic_changelog"
android:title="System Ui Tweaks"
android:summary="Developers soup of the week" />
...
Nx Biotic said:
This Is what I put together...Excuse any errors in java...Im new at this. When I start this fragment, I get a force close. What did I do?
Code:
package com.bionx.res.catalyst;
import android.content.Context;
import android.os.Bundle;
import android.os.PowerManager;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceFragment;
import com.bionx.res.R;
import com.bionx.res.helpers.CMDProcessor;
import com.bionx.res.helpers.Helpers;
public abstract class Navbar extends PreferenceFragment implements OnPreferenceChangeListener {
Preference mReboot;
ListPreference mStockValue;
int newStockValue;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.navbarchanger);
mStockValue = (ListPreference) findPreference("stock_value");
mStockValue.setOnPreferenceChangeListener(this);
mReboot = findPreference("reboot");
}
public boolean onPreference(Preference preference) {
if (preference == mReboot) {
PowerManager pm = (PowerManager) getActivity()
.getSystemService(Context.POWER_SERVICE);
pm.reboot("Setting Navbar");
}
return false;
}
[user=439709]@override[/user]
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference == mStockValue) {
newStockValue = Integer.parseInt((String) newValue);
setNavbarValue(newStockValue);
mStockValue.setSummary(getResources().getString(R.string.navbar_changer) + newStockValue);
return true;
}
return false;
}
private void setNavbarValue(int newNavbar) {
Helpers.getMount("rw");
new CMDProcessor().su.runWaitFor("busybox sed -i 's|qemu.hw.mainkeys=.*|"
+ "qemu.hw.mainkeys" + "=" + newNavbar + "|' " + "/system/build.prop");
Helpers.getMount("ro");
}
}
Code:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<Preference
android:title="System Properties"
android:summary="User System Tweaks" />
<ListPreference
android:entries="@array/navbar_stock_entries"
android:entryValues="@array/navbar_stock_values"
android:key="stock_value"
android:title="NavBar Enabler"
android:summary="Toggle the system navbar" />
<Preference
android:key="reboot"
android:title="Reboot"
android:summary="Applies tweaks and reboots" />
</PreferenceScreen>
Where I launch the fragment.
Code:
...
<header
android:fragment="com.bionx.res.catalyst.Navbar"
android:icon="@drawable/ic_changelog"
android:title="System Ui Tweaks"
android:summary="Developers soup of the week" />
...
Click to expand...
Click to collapse
please post the Log you get on Eclipse !
the log will tell you exactly where the error is

[Guide] Accessing all Build.prop values without Root

Hi.
I was developing an app in which I needed to access some of the build.prop values without accessing root.
After some days finally I found a good & working solution.
So, for whom they need it later, I decided to share it here.
All you have to do is this :
1. Make a process which executes "getprop" from the "/system/bin/getprop" directory and initialize the String which we want to get (ro.board.platform in example).
2. Make a BufferedReader which gets the value (String) by retrieving the data from a inputStreamReader().
3.Convert the BufferedReader to String.
Help your selves.
Code:
Process p = null;
String board_platform = "";
try {
p = new ProcessBuilder("/system/bin/getprop", "ro.board.platform").redirectErrorStream(true).start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line=br.readLine()) != null){
board_platform = line;
}
p.destroy();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Thanks man!.,,..
But are we really in such a need of getprop? If I remember correctly, on all Android devices /system partition is world-readable. So we can just read it build.prop like a normal text file and then parse it.
Dr.Alexander_Breen said:
But are we really in such a need of getprop? If I remember correctly, on all Android devices /system partition is world-readable. So we can just read it build.prop like a normal text file and then parse it.
Click to expand...
Click to collapse
Maybe you're right.
But before the Tut، I collected some info on build.prop.
I read different files from different devices with different ROMs.
And I gained a result : The file differs from ROM to ROM and from device to device.
I had thought of this knowing that in device Nexus 4 "ro.x.y" is in line "z" forexample :
1. Create BufferedReader to read the build.prop file.
2.
// Let's consider ro.x.y : outcome in build.prop
int x = 0;
String y ="";
If ((y = br.readLine()) != null) {
x++;
String line = y;
if (x = z){
// So we have found ro.x.y
String result = line;
result = result.replaceAll("ro.x.y", "");
result = result.replaceAll(" :", "");
}
}
Using this procedure we have retreived the ro.x.y value in Nexus 4.
But does anybody promise that ro.x.y is in line "z" in all devices?
The answer is NO as I mentioned above.
Maybe someone has changed his build.prop file and ... .
I hope it helps.
Shouldn't the title be [Guide], not [Guilde]?
nikwen said:
Shouldn't the title be [Guide], not [Guilde]?
Click to expand...
Click to collapse
Thanks sir.
Didn't notice at all.
And here is C# Translation for the code:
------------------------------------------------------------------------------------------------
Global Variables
------------------------------------------------------------------------------------------------
Code:
private Process p = null;
private string AdbPath = Path.Combine(Path.GetTempPath(), "RegawMOD", "AndroidLib", "adb");
------------------------------------------------------------------------------------------------
Process Definition
------------------------------------------------------------------------------------------------
Code:
try
{
p = new Process();
ProcessStartInfo sInfo = new ProcessStartInfo("cmd");
sInfo.RedirectStandardOutput = true;
sInfo.RedirectStandardInput = true;
sInfo.CreateNoWindow = true;
sInfo.UseShellExecute = false;
sInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo = sInfo;
p.OutputDataReceived += p_OutputDataReceived;
p.EnableRaisingEvents = true;
p.Start();
p.BeginOutputReadLine();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error starting adb process", MessageBoxButton.OK, MessageBoxImage.Error);
}
------------------------------------------------------------------------------------------------
p_OutputDataReceived Definition
------------------------------------------------------------------------------------------------
Code:
void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
string line = "";
try
{
if (!(line = e.Data).Trim().Length.Equals(0) && !line.Contains("/system/bin/getprop ro.board.platform"))
{
this.Dispatcher.BeginInvoke(new Action(() => txt.AppendText(line + "\n")));
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error Reading Output", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
------------------------------------------------------------------------------------------------
Passing command to our little adb process
------------------------------------------------------------------------------------------------
Code:
if (p != null)
{
p.StandardInput.WriteLine(AdbPath + " shell /system/bin/getprop ro.board.platform");
}
------------------------------------------------------------------------------------------------
Side Notes:
------------------------------------------------------------------------------------------------
Code above will result in active shell, it's a simulation for executing commands via CMD
What you need to do is the following:
Change "AdbPath" content to match the path of your adb executable.
"txt" is the Textbox that will show the output, put your own object.
Remove this line " !line.Contains("/system/bin/getprop ro.board.platform);" from "p_OutputDataReceived" to have an idea why I included it in the first place, it's not a must to have it but it will make output look nicer.
In the "Passing command to our little adb process" section, you can replace " shell /system ...etc" with your own object to make the app flexible and be able to execute any command the user type [example: .p.StandardInput.WriteLine(String.Join(" ", AdbPath , CommandTextBox.Text));]
This is almost the same code I execute in Droid Manager for the active shell, I just added few more lines to serve my active shell demands
My device is rooted, nevertheless it doesn't matter which language we are using, as long as we are executing the same command, then it should work with non rooted devices too just like OP says
I use AndroidLib that's why my Adb path points to AndroidLib's adb executable.
------------------------------------------------------------------------------------------------
Good luck
------------------------------------------------------------------------------------------------
Edit:
Dr.Alexander_Breen said:
But are we really in such a need of getprop? If I remember correctly, on all Android devices /system partition is world-readable. So we can just read it build.prop like a normal text file and then parse it.
Click to expand...
Click to collapse
@Dr.Alexander_Breen Yes /system is read only and we can read the file, but if you read it like a text file you will have to break text apart to get the value and not key + value. and you will have to go line by line to reach the key you want, so by using "getprop" you will get the value without having to write extra lines of code to make the app show you value only. As for me I prefer it that way, no need to make the app execute more lines of code just to get a part of the string.
torpedo mohammadi said:
Using this procedure we have retreived the ro.x.y value in Nexus 4.
But does anybody promise that ro.x.y is in line "z" in all devices?
The answer is NO as I mentioned above.
Maybe someone has changed his build.prop file and ... .
I hope it helps.
Click to expand...
Click to collapse
Well, we are supposed to write smart parser which is indifferent to line number, it searches by key name...and gets the value. However, that is the reinvention of the wheel - getprop does exactly the same.
Just saying that the same result is available without the getprop. But it will be (or will not if you're really good in regular expressions) harder, yes.
Alternatively, you can use reflection to access Android's internal android.os.SystemProperties class.
Here is the class I use to reflect it in Pimp My Rom :
Code:
package com.androguide.pimpmyrom.helpers;
import android.content.Context;
import java.io.File;
import java.lang.reflect.Method;
import dalvik.system.DexFile;
/*
Class using reflection to grant access to the private hidden android.os.SystemProperties class
*/
public class SystemPropertiesReflection {
/**
* This class cannot be instantiated
*/
private SystemPropertiesReflection() {
}
/**
* 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();
[user=1299008]@supp[/user]ressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
[user=1299008]@supp[/user]ressWarnings("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.
*
* [user=2056652]@return[/user] if the key isn't found, return def if it isn't null, or an empty string otherwise
* [user=948141]@Throw[/user]s 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();
[user=1299008]@supp[/user]ressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
[user=1299008]@supp[/user]ressWarnings("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.
*
* [user=955119]@param[/user] key the key to lookup
* [user=955119]@param[/user] def a default value to return
* [user=2056652]@return[/user] the key parsed as an integer, or def if the key isn't found or
* cannot be parsed
* [user=948141]@Throw[/user]s 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();
[user=1299008]@supp[/user]ressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
[user=1299008]@supp[/user]ressWarnings("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.
*
* [user=955119]@param[/user] key the key to lookup
* [user=955119]@param[/user] def a default value to return
* [user=2056652]@return[/user] the key parsed as a long, or def if the key isn't found or
* cannot be parsed
* [user=948141]@Throw[/user]s 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();
[user=1299008]@supp[/user]ressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
[user=1299008]@supp[/user]ressWarnings("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.
*
* [user=955119]@param[/user] key the key to lookup
* [user=955119]@param[/user] def a default value to return
* [user=2056652]@return[/user] the key parsed as a boolean, or def if the key isn't found or is
* not able to be parsed as a boolean.
* [user=948141]@Throw[/user]s 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();
[user=1299008]@supp[/user]ressWarnings("rawtypes")
Class SystemProperties = cl.loadClass("android.os.SystemProperties");
//Parameters Types
[user=1299008]@supp[/user]ressWarnings("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.
*
* [user=948141]@Throw[/user]s IllegalArgumentException if the key exceeds 32 characters
* [user=948141]@Throw[/user]s IllegalArgumentException if the value exceeds 92 characters
*/
public static void set(Context context, String key, String val) throws IllegalArgumentException {
try {
[user=1299008]@supp[/user]ressWarnings("unused")
DexFile df = new DexFile(new File("/system/app/Settings.apk"));
[user=1299008]@supp[/user]ressWarnings("unused")
ClassLoader cl = context.getClassLoader();
[user=1299008]@supp[/user]ressWarnings("rawtypes")
Class SystemProperties = Class.forName("android.os.SystemProperties");
//Parameters Types
[user=1299008]@supp[/user]ressWarnings("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
}
}
}
Then, you can create a static method like the following in order to avoid NPEs if the property we're asking for isn't present and such:
Code:
public static String getSystemProp(Context context, String prop, String default) {
String result = null;
try {
result = SystemPropertiesReflection.get(context, prop);
} catch (IllegalArgumentException iae) {
Log.e(TAG, "Failed to get prop: " + prop);
}
return result == null ? default : result;
}
And simply invoke it to get the returned property, for example:
Code:
String prop = getSystemProp(this, "ro.sf.lcd_density", "213");
EDIT : sorry to the guys that were @ mentionned by the code's annotations
@ whoever's code I decide to use: Thanks, I'll make use of this in my library I'll put you in the credits :good:
I'm using the code in the OP and it's returning the default value, but not the actual value... This is really weird...
EDIT: Ok, so it won't update values until I reboot the device. Is there any workaround?
Tezlastorme said:
EDIT: Ok, so it won't update values until I reboot the device. Is there any workaround?
Click to expand...
Click to collapse
The system properties are not reloaded after you edit the build.prop, you need a reboot, or you've to read from build.prop file.
vektor88 said:
The system properties are not reloaded after you edit the build.prop, you need a reboot, or you've to read from build.prop file.
Click to expand...
Click to collapse
But whenever I read directly from build.prop something screws up, like build.prop becomes empty or deletes itself. In my last test my sdcard became corrupted and build.prop became blank.
Sent from my Galaxy Nexus
Tezlastorme said:
But whenever I read directly from build.prop something screws up, like build.prop becomes empty or deletes itself. In my last test my sdcard became corrupted and build.prop became blank.
Sent from my Galaxy Nexus
Click to expand...
Click to collapse
Use setprop and getprop in addition to the changes you make to the build.prop, this way you can get the current value without the hassle or performance loss of having to parse the whole build.prop for each value you want to read.
For example, if you change ro.whatever=true to ro.whatever=false, also do a setprop ro.whatever false so that you can retrieve the value from getprop ro.whatever
Dr.Alexander_Breen said:
But are we really in such a need of getprop? If I remember correctly, on all Android devices /system partition is world-readable. So we can just read it build.prop like a normal text file and then parse it.
Click to expand...
Click to collapse
If this is true (and i think it is), why <ou don't simply use the Java Properties class to read the prop file?
developer.android.com/reference/java/util/Properties.html
Sorry for answering in this old Thread, but i dont see why you read the properties file by yourself.
amfa84 said:
If this is true (and i think it is), why <ou don't simply use the Java Properties class to read the prop file?
developer.android.com/reference/java/util/Properties.html
Sorry for answering in this old Thread, but i dont see why you read the properties file by yourself.
Click to expand...
Click to collapse
Yeah, it should work, in theory.. But in practice it screw things up a lot. It ends up deleting the whole contents of build.prop or not reading correctly and it's very unpredictable :-/
And yes I was using the Properties class (and still do)
Sent from my sushi grade tuna
---------- Post added at 08:48 AM ---------- Previous post was at 08:47 AM ----------
Androguide.fr said:
Use setprop and getprop in addition to the changes you make to the build.prop, this way you can get the current value without the hassle or performance loss of having to parse the whole build.prop for each value you want to read.
For example, if you change ro.whatever=true to ro.whatever=false, also do a setprop ro.whatever false so that you can retrieve the value from getprop ro.whatever
Click to expand...
Click to collapse
Btw I tried this ^^ and it didn't work
Sent from my sushi grade tuna
Tezlastorme said:
Yeah, it should work, in theory.. But in practice it screw things up a lot. It ends up deleting the whole contents of build.prop or not reading correctly and it's very unpredictable :-/
And yes I was using the Properties class (and still do)
Sent from my sushi grade tuna
---------- Post added at 08:48 AM ---------- Previous post was at 08:47 AM ----------
Btw I tried this ^^ and it didn't work
Sent from my sushi grade tuna
Click to expand...
Click to collapse
Then you're not doing it right, it does work, and it's very easy to test, just open Terminal emulator, and try the following:
Code:
setprop ro.test.prop true
getprop ro.test.prop
# returns
true
As I said, this will not modify the build.prop, but if everytime you modify the build.prop you also use setprop, then you can avoir the big performance overhead of having to parse the whole build.prop just to get the value of a single prop.
The best way to me remains accessing the private android.os.SystemProperties class through reflection. I believe I had already posted the class in this thread earlier, but here it is:
PHP:
package com.androguide.pimpmyromv2.helpers;
import android.content.Context;
import java.io.File;
import java.lang.reflect.Method;
import dalvik.system.DexFile;
/**
* Class using reflection to grant access to the private hidden android.os.SystemProperties class
*/
public class SystemPropertiesReflection {
/**
* This class cannot be instantiated
*/
private SystemPropertiesReflection() {
}
/**
* 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
}
}
}
one x new in android
torpedo mohammadi said:
Hi.
I was developing an app in which I needed to access some of the build.prop values without accessing root.
After some days finally I found a good & working solution.
So, for whom they need it later, I decided to share it here.
All you have to do is this :
1. Make a process which executes "getprop" from the "/system/bin/getprop" directory and initialize the String which we want to get (ro.board.platform in example).
2. Make a BufferedReader which gets the value (String) by retrieving the data from a inputStreamReader().
3.Convert the BufferedReader to String.
Help your selves.
Code:
Process p = null;
String board_platform = "";
try {
p = new ProcessBuilder("/system/bin/getprop", "ro.board.platform").redirectErrorStream(true).start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line=br.readLine()) != null){
board_platform = line;
}
p.destroy();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Click to expand...
Click to collapse
Hi, Is anyone nood friendly to explain me or some tutorial where and how to put this comand, to change my build.prop without unlocking bootloader on my HOX tegra 3..grateful for any response
---------- Post added at 01:25 PM ---------- Previous post was at 01:13 PM ----------
torpedo mohammadi said:
Hi.
I was developing an app in which I needed to access some of the build.prop values without accessing root.
After some days finally I found a good & working solution.
So, for whom they need it later, I decided to share it here.
All you have to do is this :
1. Make a process which executes "getprop" from the "/system/bin/getprop" directory and initialize the String which we want to get (ro.board.platform in example).
2. Make a BufferedReader which gets the value (String) by retrieving the data from a inputStreamReader().
3.Convert the BufferedReader to String.
Help your selves.
Code:
Process p = null;
String board_platform = "";
try {
p = new ProcessBuilder("/system/bin/getprop", "ro.board.platform").redirectErrorStream(true).start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line=br.readLine()) != null){
board_platform = line;
}
p.destroy();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Click to expand...
Click to collapse
Hi, Is anyone nood friendly to explain me or some tutorial where and how to put this comand, to change my build.prop without unlocking bootloader on my HOX tegra 3..grateful for any response
Hey,
Sorry for bumping this old thread.
How a non-developer user could use this to change/add build.prop lines?
I got a complete stock Nexus 5X that I'd like to add some new lines into build.prop without root.
Is it possible?
Thanks in advance!
How to integrate that to show in textView?

Dynamically loading an external library at runtime

I am using and android 2.2 phone for testing and getting an error which is driving me crazy
07-27 01:24:55.692: W/System.err(14319): java.lang.ClassNotFoundException: com.shoaib.AndroidCCL.MyClass in loader [email protected]
Can someone help me what to do now..i have tried various suggested solutions on different posts
First I wrote the following class:
Code:
package org.shoaib.androidccl;
import android.util.Log;
public class MyClass {
public MyClass() {
Log.d(MyClass.class.getName(), "MyClass: constructor called.");
}
public void doSomething() {
Log.d(MyClass.class.getName(), "MyClass: doSomething() called.");
}
}
And I packaged it in a DEX file that I saved on my device's SD card as `/sdcard/testdex.jar`.
Then I wrote the program below, after having removed `MyClass` from my Eclipse project and cleaned it:
Code:
public class Main extends Activity {
[user=1299008]@supp[/user]ressWarnings("unchecked")
[user=439709]@override[/user]
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
final String libPath = Environment.getExternalStorageDirectory() + "/testdex.jar";
final File tmpDir = getDir("dex", 0);
final DexClassLoader classloader = new DexClassLoader(libPath, tmpDir.getAbsolutePath(), null, this.getClass().getClassLoader());
final Class<Object> classToLoad = (Class<Object>) classloader.loadClass("org.shoaib.androidccl.MyClass");
final Object myInstance = classToLoad.newInstance();
final Method doSomething = classToLoad.getMethod("doSomething");
doSomething.invoke(myInstance);
} catch (Exception e) {
e.printStackTrace();
}
}
}
As far as I know you can't load external dex classes (and certainly not a jar file), the only ones that can be loaded are the ones packaged in the classes.dex file inside the APK and protected by its signature and certificate.
This would be quite a security flaw if your app could be "clean" at install but then download malicious classes and execute them.

Categories

Resources