Hello,
I've been trying to do some android stuff on java for some time now, and i've come across a problem here: i can't get the app to execute linux stuff, as there is no system() method like on other platforms... so i searched some code and found this:
Code:
protected void system(String[] Commands){
e Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
DataInputStream osRes = new DataInputStream(process.getInputStream());
Vector<String> res = new Vector<String>();
for (String single : Commands) {
e os.writeBytes(single + "\n");
e os.flush();
e res.add(osRes.readLine());
// Log.e("CMDs", osRes.readLine());
}
e os.writeBytes("exit\n");
e os.flush();
process.waitFor();
}
However that won't work because of some errors i have in the marked lines:
"Unhandled exception type IOException"
and the process.waitFor(); line also gives me an error:
"Unhandled exception type InterruptedException"
Any ideas?
You need to add a try/catch block around that code which catches the IO exception and the interrupted exception.
deleted
So, first of all thanks to both of you it appears to be working now... i tried in on the emulator, and of course "su" didn't work there (broken pipe), so i replaced it by "sh", however this didn't seem to work well too. the application just locked up with a warning in android.... strange...
edit: tried using /system/bin/sh, didn't work, locked up again
What version of Android in the emulator? I've done it with 1.5 through 2.2 in the emulator, just by using "sh".
could you post the code you used please? would be AWESOME!
i'm trying to get this working on 2.1
Sure, I can post some more details later, but for now just the code.
Include the file in your project and use with:
Code:
ShellCommand cmd = new ShellCommand();
CommandResult r = cmd.sh.runWaitFor("ls -l");
if (!r.success()) {
Log.v(TAG, "Error " + r.stderr);
} else {
Log.v(TAG, "Success! " + r.stdout);
}
If you want su you can either use cmd.shOrSu().runWaitFor("..."); which will try su (by running "id", it just tests the status code but it's a nice entry in logcat for debugging) and fallback to sh. Or you can use cmd.su.runWaitFor("...");
Also at
teslacoilsw.com/files/ShellCommand.java
Code:
package com.teslacoilsw.quicksshd;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import android.util.Log;
public class ShellCommand {
private static final String TAG = "ShellCommand.java";
private Boolean can_su;
public SH sh;
public SH su;
public ShellCommand() {
sh = new SH("sh");
su = new SH("su");
}
public boolean canSU() {
return canSU(false);
}
public boolean canSU(boolean force_check) {
if (can_su == null || force_check) {
CommandResult r = su.runWaitFor("id");
StringBuilder out = new StringBuilder();
if (r.stdout != null)
out.append(r.stdout).append(" ; ");
if (r.stderr != null)
out.append(r.stderr);
Log.v(TAG, "canSU() su[" + r.exit_value + "]: " + out);
can_su = r.success();
}
return can_su;
}
public SH suOrSH() {
return canSU() ? su : sh;
}
public class CommandResult {
public final String stdout;
public final String stderr;
public final Integer exit_value;
CommandResult(Integer exit_value_in, String stdout_in, String stderr_in)
{
exit_value = exit_value_in;
stdout = stdout_in;
stderr = stderr_in;
}
CommandResult(Integer exit_value_in) {
this(exit_value_in, null, null);
}
public boolean success() {
return exit_value != null && exit_value == 0;
}
}
public class SH {
private String SHELL = "sh";
public SH(String SHELL_in) {
SHELL = SHELL_in;
}
public Process run(String s) {
Process process = null;
try {
process = Runtime.getRuntime().exec(SHELL);
DataOutputStream toProcess = new DataOutputStream(process.getOutputStream());
toProcess.writeBytes("exec " + s + "\n");
toProcess.flush();
} catch(Exception e) {
Log.e(QuickSSHD.TAG, "Exception while trying to run: '" + s + "' " + e.getMessage());
process = null;
}
return process;
}
private String getStreamLines(InputStream is) {
String out = null;
StringBuffer buffer = null;
DataInputStream dis = new DataInputStream(is);
try {
if (dis.available() > 0) {
buffer = new StringBuffer(dis.readLine());
while(dis.available() > 0)
buffer.append("\n").append(dis.readLine());
}
dis.close();
} catch (Exception ex) {
Log.e(TAG, ex.getMessage());
}
if (buffer != null)
out = buffer.toString();
return out;
}
public CommandResult runWaitFor(String s) {
Process process = run(s);
Integer exit_value = null;
String stdout = null;
String stderr = null;
if (process != null) {
try {
exit_value = process.waitFor();
stdout = getStreamLines(process.getInputStream());
stderr = getStreamLines(process.getErrorStream());
} catch(InterruptedException e) {
Log.e(TAG, "runWaitFor " + e.toString());
} catch(NullPointerException e) {
Log.e(TAG, "runWaitFor " + e.toString());
}
}
return new CommandResult(exit_value, stdout, stderr);
}
}
}
Thanks kevin The code you are using there is awesome Looking good so far, however it keeps returning permission denied... is it some setting in the android manifest?
Actually "Permission denied" often also means "no such file or directory" on android :-/ . It's very frustrating.
Try running something simple to start with like:
cmd.sh.runWaitFor("echo foo");
[email protected] said:
Actually "Permission denied" often also means "no such file or directory" on android :-/ . It's very frustrating.
Try running something simple to start with like:
cmd.sh.runWaitFor("echo foo");
Click to expand...
Click to collapse
yep, i tried running echo as i was confused by the "permission denied" although i had already set write permissions for the sdcard... didn't work, for some odd reason
I'm developing an Android app that purchase errors copying files from /assets to /system. I have this code but I don't know why isn't works. Can anybody help me, This is my code:
Code:
public class MainActivity extends Activity
{
ProgressDialog progressDialog = null;
/** Called when the activity is first created. */
[user=439709]@override[/user]
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
{
}}
public void reparar(View view) throws IOException {
progressDialog = ProgressDialog.show(MainActivity.this, "Instalando parche", "Por favor, espere...", true);
//Aqi poner el conjunto de acciones hasta mover los archivos al
//directorio system
try {
ProcessBuilder pb = new ProcessBuilder(new String[] { "su", "mount -o rw, remount -t yaffs2 /dev/block/mtdblock4 /system", "cp /assets/keypad/file.format /system", "mount -o ro, remount -t yaffs2 /dev/block/mtdblock4 /system" });
java.lang.Process process = pb.start();
process.waitFor();
} catch (IOException e) {
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
progressDialog.dismiss();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Debe reiniciar el terminal. Desea hacerlo ahora?")
.setTitle("Instalacion satisfactoria!")
.setCancelable(false)
.setNegativeButton("Reiniciar mas tarde",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
})
.setPositiveButton("Reiniciar ahora",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// metodo que se debe implementar
try {
ProcessBuilder pb = new ProcessBuilder(new String[] { "su", "-c", "/system/bin/reboot" });
java.lang.Process process = pb.start();
process.waitFor();
} catch (IOException e) {
}
// TODO Auto-generated method stub
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
AlertDialog alert = builder.create();
alert.show();
}
[user=439709]@override[/user]
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.options, menu);
return true;
}
}
Enviado desde mi GT-S5570I usando Tapatalk 2
Please! Help me :crying:
DannyGM16 said:
Please! Help me :crying:
Click to expand...
Click to collapse
first you'll have to copy the file from the apk-assets folder to /data/data/your.pqackage.name/file/file.format, after that you can copy it as root to the system partition.
Code:
String data_storage_root = mContext.getFilesDir().toString();
InputStream is= null;
OutputStream os = null;
File h = new File(data_storage_root+"/file.format");
if (h.exists()) h.setWritable(true, true);
try {
is = mContext.getResources().getAssets().open("keypad/file.format");
os = new FileOutputStream(data_storage_root+"/file.format");
IOUtils.copy(is, os);
is.close();
os.flush();
os.close();
os = null;
Log.d(TAG, "success copying");
} catch (IOException e) {
Log.w(TAG, "failed copying");
}
h.setExecutable(false, true);
h.setReadable(true, true);
h.setWritable(false, true);
Zatta said:
first you'll have to copy the file from the apk-assets folder to /data/data/your.pqackage.name/file/file.format, after that you can copy it as root to the system partition.
Code:
String data_storage_root = mContext.getFilesDir().toString();
InputStream is= null;
OutputStream os = null;
File h = new File(data_storage_root+"/file.format");
if (h.exists()) h.setWritable(true, true);
try {
is = mContext.getResources().getAssets().open("keypad/file.format");
os = new FileOutputStream(data_storage_root+"/file.format");
IOUtils.copy(is, os);
is.close();
os.flush();
os.close();
os = null;
Log.d(TAG, "success copying");
} catch (IOException e) {
Log.w(TAG, "failed copying");
}
h.setExecutable(false, true);
h.setReadable(true, true);
h.setWritable(false, true);
Click to expand...
Click to collapse
Thanks for the info, I didn't know it!
When I use this code I have two issues, in mContext and IOUtils, what am I doing wrong?
And Copying from data to system I preffer doing it with RootTools. Can u help me pls??
Oh, sorry. This is a snipplet from one of my apps, it uses a library called commons-io-2.1.jar for the IOUtils. The context is just the context from the loader where this snipplet comes from.
I've never used RootUtils so I can't help you with that, sorry.
When I'm not on my phone but at a computer I'll search for an alternative to extract the file from the apk for you (if you haven't found it by then, SO will have an answer for sure).
Taptalked u see .. əəs n pəʞlɐʇdɐʇ
Zatta said:
Oh, sorry. This is a snipplet from one of my apps, it uses a library called commons-io-2.1.jar for the IOUtils. The context is just the context from the loader where this snipplet comes from.
I've never used RootUtils so I can't help you with that, sorry.
When I'm not on my phone but at a computer I'll search for an alternative to extract the file from the apk for you (if you haven't found it by then, SO will have an answer for sure).
Taptalked u see .. əəs n pəʞlɐʇdɐʇ
Click to expand...
Click to collapse
Lots of thanks! I'm waiting for you
Enviado desde mi GT-S5570I usando Tapatalk 2
Zatta said:
Oh, sorry. This is a snipplet from one of my apps, it uses a library called commons-io-2.1.jar for the IOUtils. The context is just the context from the loader where this snipplet comes from.
I've never used RootUtils so I can't help you with that, sorry.
When I'm not on my phone but at a computer I'll search for an alternative to extract the file from the apk for you (if you haven't found it by then, SO will have an answer for sure).
Taptalked u see .. əəs n tapatalked
Click to expand...
Click to collapse
Code:
import android.app.*;
import android.content.*;
import android.os.*;
import android.os.Process;
import android.util.*;
import android.view.*;
import android.view.View.*;
import android.widget.Button;
import android.widget.Toast;
import java.io.*;
import com.stericson.RootTools.RootTools;
import com.stericson.RootTools.execution.CommandCapture;
import java.util.concurrent.*;
import com.stericson.RootTools.exceptions.*;
import org.apache.commons.io.*;
public class MainActivity extends Activity {
{
}
ProgressDialog progressDialog = null;
/** Called when the activity is first created. */
[user=439709]@override[/user]
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (RootTools.isAccessGiven()) {
} else {
makeToast("Se necesitan permisos de Superusuario!");
finish();
}
}
public void reparar(View view) throws IOException, TimeoutException, RootDeniedException, InterruptedException {
CopyFromAssets();
CopyFromAssetstosystem();
End();
}
public void CopyFromAssets() {
progressDialog = ProgressDialog.show(MainActivity.this, "Instalando parche", "Por favor, espere...", true);
String data_storage_root = getFilesDir().toString();
InputStream is= null;
OutputStream os = null;
File h = new File(data_storage_root+"/caca.txt");
File p = new File(data_storage_root+"/caca2.txt");
if (h.exists()) h.setWritable(true, true);
if (p.exists()) h.setWritable(true, true);
try {
is = getResources().getAssets().open("keypad/caca.txt");
is = getResources().getAssets().open("keypad/caca2.txt");
os = new FileOutputStream(data_storage_root+"/sec_key.kl");
os = new FileOutputStream(data_storage_root+"/sec_keypad.kl");
IOUtils.copy(is, os);
is.close();
os.flush();
os.close();
os = null;
} catch (IOException e) {
makeToast("Fallo al copiar");
finish();
}
h.setExecutable(false, true);
h.setReadable(true, true);
h.setWritable(false, true);
}
public void CopyFromAssetstosystem() throws TimeoutException, IOException, RootDeniedException {
CommandCapture command = new CommandCapture(0, "su", "mount -o rw, remount -t yaffs2 /dev/block/mtdblock4 /system", "cp /data/data/com.fixer.gminipop/files/caca.txt /system", "mount -o ro, remount -t yaffs2 /dev/block/mtdblock4 /system");
RootTools.getShell(true).add(command).waitForFinish();
}
public void End() {
ClosePD();
AlertDialog();
}
public void AlertDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Es necesario reiniciar para que se apliquen los cambios. Desea hacerlo ahora?")
.setTitle("Instalacion satisfactoria!")
.setCancelable(false)
.setNegativeButton("Reiniciar mas tarde",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
})
.setPositiveButton("Reiniciar ahora",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// metodo que se debe implementar
try {
ProcessBuilder pb = new ProcessBuilder(new String[] { "su", "-c", "/system/bin/reboot" });
java.lang.Process process = pb.start();
process.waitFor();
} catch (IOException e) {
}
// TODO Auto-generated method stub
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
AlertDialog alert = builder.create();
alert.show();
}
public void ClosePD() {
progressDialog.dismiss();
}
private static void copy(InputStream is, OutputStream os) {
// TODO Auto-generated method stub
}
public void makeToast(String msg) {
Context context = getApplicationContext();
CharSequence text = msg;
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
public void RootActions() {
}
}
This is all my code, I use your library and RootTool library.
I have two issues:
1- Error in waitForFinish();
2- processDialog don't appear.
Enviado desde mi GT-S5570I usando Tapatalk 2
Hi,
I've rewrote my snipplet not to use the apache library (eventually it is just one method that was used so this is more clean) and added that to a asynctask.
Better late than never now you have rewritten yours as well :S Attached is the eclipse project.
Also, in your code you are trying to copy two files, that is not going to work like that. You define the inputstream and the outputstream twice. I will make this thing work for you if you haven't figured it out tomorrow, will take 24 hrs for me to come back on this. I don't use roottools as I said but maybe I'll look into that as well. Else I will give you an alternative.
Code:
package by.zatta.copyassets;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.widget.Toast;
public class MainActivity extends Activity {
private static final String TAG = "Copy Example";
[user=439709]@override[/user]
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new PlantFiles().execute();
}
private void doneBackground(boolean succes){
// this method should be used to progress further after,
// update the ui, do other things like copying the file to /system
if (succes)
Toast.makeText(this, "Copied!", Toast.LENGTH_LONG).show();
else
Toast.makeText(this, "Failed", Toast.LENGTH_LONG).show();
}
private class PlantFiles extends AsyncTask<Void, Void, Boolean> {
protected Boolean doInBackground(Void... arg0) {
String data_storage_root = getApplicationContext().getFilesDir().toString();
boolean copied=false;
InputStream is= null;
OutputStream os = null;
File h = new File(data_storage_root+"/file.format");
if (h.exists()) h.delete();
try {
is = getApplicationContext().getResources().getAssets().open("keypad/file.format");
os = new FileOutputStream(data_storage_root+"/file.format");
if (copy(is, os)) copied = true;
is.close();
os.flush();
os.close();
os = null;
Log.d(TAG, "success copying certificate generic");
} catch (IOException e) {
Log.w(TAG, "failed copying certificate generic");
}
return copied;
}
protected void onPostExecute(Boolean result){
doneBackground(result);
}
private boolean copy(InputStream in, OutputStream out){
try {
byte[] buffer = new byte[1024];
int read;
while (( read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
return true;
} catch (IOException e) {
Log.w(TAG, "problems copying");
return false;
}
}
}
}
Zatta said:
Hi,
I've rewrote my snipplet not to use the apache library (eventually it is just one method that was used so this is more clean) and added that to a asynctask.
Better late than never now you have rewritten yours as well :S Attached is the eclipse project.
Also, in your code you are trying to copy two files, that is not going to work like that. You define the inputstream and the outputstream twice. I will make this thing work for you if you haven't figured it out tomorrow, will take 24 hrs for me to come back on this. I don't use roottools as I said but maybe I'll look into that as well. Else I will give you an alternative.
Code:
package by.zatta.copyassets;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.widget.Toast;
public class MainActivity extends Activity {
private static final String TAG = "Copy Example";
[user=439709]@override[/user]
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new PlantFiles().execute();
}
private void doneBackground(boolean succes){
// this method should be used to progress further after,
// update the ui, do other things like copying the file to /system
if (succes)
Toast.makeText(this, "Copied!", Toast.LENGTH_LONG).show();
else
Toast.makeText(this, "Failed", Toast.LENGTH_LONG).show();
}
private class PlantFiles extends AsyncTask<Void, Void, Boolean> {
protected Boolean doInBackground(Void... arg0) {
String data_storage_root = getApplicationContext().getFilesDir().toString();
boolean copied=false;
InputStream is= null;
OutputStream os = null;
File h = new File(data_storage_root+"/file.format");
if (h.exists()) h.delete();
try {
is = getApplicationContext().getResources().getAssets().open("keypad/file.format");
os = new FileOutputStream(data_storage_root+"/file.format");
if (copy(is, os)) copied = true;
is.close();
os.flush();
os.close();
os = null;
Log.d(TAG, "success copying certificate generic");
} catch (IOException e) {
Log.w(TAG, "failed copying certificate generic");
}
return copied;
}
protected void onPostExecute(Boolean result){
doneBackground(result);
}
private boolean copy(InputStream in, OutputStream out){
try {
byte[] buffer = new byte[1024];
int read;
while (( read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
return true;
} catch (IOException e) {
Log.w(TAG, "problems copying");
return false;
}
}
}
}
Click to expand...
Click to collapse
I'm frustrated... You change the name of my functions an now I don't understand anything.
public void reparar is the name of the button function, in your code the functions starts "onCreate".
I prefer my dirty but understable (for me) code
Now I have only one problem, the app works, but it take a long time to reemplace the file in system directory. In other words, I pulse the button, close the application, an in one minute the file is reemplaced. How can I fix that an take this time in a progress dialog?
Sorry for my bad english! I'm spanish
This is my code, is dirty but I think you understand it. Add functions and edit, but no the name of the functions, Please!
Code:
public class MainActivity extends Activity {
ProgressDialog progress;
private static final String TAG = "Copy Example";
[user=439709]@override[/user]
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (RootTools.isRootAvailable()) {
} else {
finish();
}
}
public void reparar(View view) throws IOException, TimeoutException, RootDeniedException {
progress = ProgressDialog.show(this, "dialog title",
"dialog message", true);
copyfile1();
copyfile2();
copyfile1tosystem();
copyfile2tosystem();
End();
}
public void copyfile1() {
String data_storage_root = getApplicationContext().getFilesDir().toString();
InputStream is= null;
OutputStream os = null;
File h = new File(data_storage_root+"/sec_key.kl");
if (h.exists()) h.delete();
try {
is = getApplicationContext().getResources().getAssets().open("keypad/sec_key.kl");
os = new FileOutputStream(data_storage_root+"/sec_key.kl");
if (copy(is, os))
is.close();
os.flush();
os.close();
os = null;
Log.d(TAG, "success");
} catch (IOException e) {
Log.w(TAG, "failed copying certificate generic");
}
return;
}
public void copyfile2() {
String data_storage_root = getApplicationContext().getFilesDir().toString();
InputStream is= null;
OutputStream os = null;
File h = new File(data_storage_root+"/sec_keypad.kl");
if (h.exists()) h.delete();
try {
is = getApplicationContext().getResources().getAssets().open("keypad/sec_keypad.kl");
os = new FileOutputStream(data_storage_root+"/sec_keypad.kl");
if (copy(is, os))
is.close();
os.flush();
os.close();
os = null;
} catch (IOException e) {
finish();
}
return;
}
public void copyfile1tosystem() throws IOException, TimeoutException, RootDeniedException {
CommandCapture command = new CommandCapture(0, "su", "mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system", "cp /data/data/com.fixer.gminipop/files/sec_key.kl /system/usr/keylayout/sec_key.kl", "mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system");
RootTools.getShell(true).add(command);
}
public void copyfile2tosystem() throws IOException, TimeoutException, RootDeniedException {
CommandCapture command = new CommandCapture(0, "su", "mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system", "cp /data/data/com.fixer.gminipop/files/sec_keypad.kl /system/usr/keylayout/sec_keypad.kl", "mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system");
RootTools.getShell(true).add(command);
}
public void End() {
progress.dismiss();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Es necesario reiniciar")
.setTitle("Instalacion satisfactoria!")
.setCancelable(false)
.setNegativeButton("Hacerlo mas tarde",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
})
.setPositiveButton("Reiniciar",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// metodo que se debe implementar
try {
ProcessBuilder pb = new ProcessBuilder(new String[] { "su", "-c", "/system/bin/reboot" });
java.lang.Process process = pb.start();
process.waitFor();
} catch (IOException e) {
}
// TODO Auto-generated method stub
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
AlertDialog alert = builder.create();
alert.show();
}
private boolean copy(InputStream in, OutputStream out){
try {
byte[] buffer = new byte[1024];
int read;
while (( read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
return true;
} catch (IOException e) {
Log.w(TAG, "fallo al copiar");
finish();
return false;
}
}
}
Hi, I haven't had time to produce more code for you.
Just some remarks looking at your code:
1 you duplicate a lot of code
2 your application does everything on the main thread
3 you do a lot of unnescasairy code on the terminal
1)
copyfle 1 and 2 are almost the same, why not use it only once? copyFile(String filename){ ... } for example?
2)
extracting the files form the apk to /data schould be done at the loading of the app, in the background and preferably only once (now it tis done everytime the app starts), then copy it to system at a press of the button. In my example there is a function doneBackground(boolean succes), from there you could set the visiblity of your button to View.VISIBLE, allowing the user to copy the file to /system, now everything is done after the button press.
3)
Code:
"su"
"mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system"
"cp /data/data/com.fixer.gminipop/files/sec_key.kl /system/usr/keylayout/sec_key.kl"
"mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system")
"su"
"mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system"
"cp /data/data/com.fixer.gminipop/files/sec_keypad.kl /system/usr/keylayout/sec_keypad.kl"
"mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system");
this calls 2 times su and it mounts 2 times the system as rw and back to ro, can hugely be optimized
Edit, just read Nikwens reply in your other thread, you don't have to call su at all according to him. However,as I said, I am not a user of Roottools so can't confirm that.
Zatta said:
Hi, I haven't had time to produce more code for you.
Just some remarks looking at your code:
1 you duplicate a lot of code
2 your application does everything on the main thread
3 you do a lot of unnescasairy code on the terminal
1)
copyfle 1 and 2 are almost the same, why not use it only once? copyFile(String filename){ ... } for example?
2)
extracting the files form the apk to /data schould be done at the loading of the app, in the background and preferably only once (now it tis done everytime the app starts), then copy it to system at a press of the button. In my example there is a function doneBackground(boolean succes), from there you could set the visiblity of your button to View.VISIBLE, allowing the user to copy the file to /system, now everything is done after the button press.
3)
Code:
"su"
"mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system"
"cp /data/data/com.fixer.gminipop/files/sec_key.kl /system/usr/keylayout/sec_key.kl"
"mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system")
"su"
"mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system"
"cp /data/data/com.fixer.gminipop/files/sec_keypad.kl /system/usr/keylayout/sec_keypad.kl"
"mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system");
this calls 2 times su and it mounts 2 times the system as rw and back to ro, can hugely be optimized
Edit, just read Nikwens reply in your other thread, you don't have to call su at all according to him. However,as I said, I am not a user of Roottools so can't confirm that.
Click to expand...
Click to collapse
Thank's! I'm going to fix that, Optimice code and clear it. But the problem persist, the copy of the file to system take a long time, and the process to do it is after I close the app, This is my only important error..
Enviado desde mi GT-S5570I usando Tapatalk 2
Ok! I fix all and I'm going to upload it to Google Play, thanks for all your help in this project!
Now I only need your help to put Ads (If my app have lots of downloads) Can u give me a link of a Tutorial?
Enviado desde mi GT-S5570I usando Tapatalk 2
DannyGM16 said:
Ok! I fix all and I'm going to upload it to Google Play, thanks for all your help in this project!
Now I only need your help to put Ads (If my app have lots of downloads) Can u give me a link of a Tutorial?
Enviado desde mi GT-S5570I usando Tapatalk 2
Click to expand...
Click to collapse
No, I hate ads
Post your play store link here, I'm curious what you made.
Taptalked u see .. əəs n pəʞlɐʇdɐʇ
Zatta said:
No, I hate ads
Post your play store link here, I'm curious what you made.
Taptalked u see .. əəs n pəʞlɐʇdɐʇ
Click to expand...
Click to collapse
You hate ads and you are a developer? ;D Is the most easy form to win money for your work. I develop apps for fun but I want obtain some money for it You can download my app, but If you don't have a galaxy mini S5570I is useless, only you can watch it...
Enviado desde mi GT-S5570I usando Tapatalk 2
This is my application: https://play.google.com/store/apps/details?id=com.fixer.gminipop
Whatch it in Google Play
Enviado desde mi GT-S5570I usando Tapatalk 2
DannyGM16 said:
This is my application: https://play.google.com/store/apps/details?id=com.fixer.gminipop
Whatch it in Google Play
Enviado desde mi GT-S5570I usando Tapatalk 2
Click to expand...
Click to collapse
You should get someone to translate all that Spanish to English. I took the effort to translate it for myself (with Google translator) but I'm sure the advantage potential user won't.
Edit, non the less, congratulations with your play store registration!!
Taptalked u see .. əəs n pəʞlɐʇdɐʇ
Zatta said:
You should get someone to translate all that Spanish to English. I took the effort to translate it for myself (with Google translator) but I'm sure the advantage potential user won't.
Edit, non the less, congratulations with your play store registration!!
Taptalked u see .. əəs n pəʞlɐʇdɐʇ
Click to expand...
Click to collapse
Thank's for show me that error, but I'm going to update it!! Only I have one problem, in one of my update I want to copy a DIRECTORY of assets to /data/data. I watch for the code in a lot o pages, but I don't find it, help me only one more time Pls!
Enviado desde mi GT-S5570I usando Tapatalk 2
Check this for finding translators: http://forum.xda-developers.com/showthread.php?t=2069390
nikwen said:
Check this for finding translators: http://forum.xda-developers.com/showthread.php?t=2069390
Click to expand...
Click to collapse
Nikewn, I know spanish and english, I can translate my app But Thank's. Only I want to resolve my last problem.
DannyGM16 said:
Nikewn, I know spanish and english, I can translate my app But Thank's. Only I want to resolve my last problem.
Click to expand...
Click to collapse
I see that you can write English.
However, you might want to have it translated to other languages, too.
---------- Post added at 03:42 PM ---------- Previous post was at 03:39 PM ----------
DannyGM16 said:
Thank's for show me that error, but I'm going to update it!! Only I have one problem, in one of my update I want to copy a DIRECTORY of assets to /data/data. I watch for the code in a lot o pages, but I don't find it, help me only one more time Pls!
Enviado desde mi GT-S5570I usando Tapatalk 2
Click to expand...
Click to collapse
Create the directory using the mkdir() method in the java.io.File class. And copy every file to the directory in /data/data. You need to copy the files one by one.
I'm an experienced developer but new to Android development. I have an app that runs some native binaries, and I provide a status indicator to show when the native process is running and when it's not. Currently I poll the device to figure this out, using the ActivityManager API to determine if specific processes are running or not.
I'm hoping there is some way to register a listener on process state changes, so I can get notified when my process starts or stops. I looked through the API, and there doesn't seem to be such a thing. Does anyone know how I can keep track of process start and stop other than polling via ActivityManager?
MidnightJava said:
I'm an experienced developer but new to Android development. I have an app that runs some native binaries, and I provide a status indicator to show when the native process is running and when it's not. Currently I poll the device to figure this out, using the ActivityManager API to determine if specific processes are running or not.
I'm hoping there is some way to register a listener on process state changes, so I can get notified when my process starts or stops. I looked through the API, and there doesn't seem to be such a thing. Does anyone know how I can keep track of process start and stop other than polling via ActivityManager?
Click to expand...
Click to collapse
Afaik there's no way to accomplish that other than your way or being system/root app. See this similar question here for reference.
Can you show how you start the process?
EmptinessFiller said:
Can you show how you start the process?
Click to expand...
Click to collapse
Sure. Here's the class that manages starting, stopping, and statusing (running or not) the binary executable. In this case, it's the omniNames service of the omni ORB (CORBA broker).
Code:
public class RHManager {
private TimerTask task = new TimerTask() {
@Override
public void run() {
if (RHManager.this.listener != null) {
listener.running(isOmniNamesRunning());
}
}
};
private IStatusListener listener;
public RHManager() {
}
public void startOmniNames() {
final Exec exec = new Exec();
final String[] args = new String[]
{RhMgrConstants.INSTALL_LOCATION_OMNI_NAMES_SCRIPTS + "/" + RhMgrConstants.OMNI_NAMES_SCRIPT_FILE,
"start"};
final String[] env = new String[] {"LD_LIBRARY_PATH=/sdcard/data/com.axiosengineering.rhmanager/omniORB/lib"};
Thread t = new Thread() {
public void run() {
try {
int res = exec.doExec(args, env);
logMsg("omniNames start return code " + res);
} catch (IOException e) {
logMsg("Failed to start omniNames");
e.printStackTrace();
}
String std = exec.getOutResult();
logMsg("omniNames start: std out==> " + std );
String err = exec.getErrResult();
logMsg("omniNames start: err out==> " + err );
};
};
t.start();
logMsg("omniNames started");
}
private boolean isOmniNamesRunning() {
String pid_s = getOmniNamesPid();
Integer pid = null;
if (pid_s != null) {
try {
pid = Integer.parseInt(pid_s);
} catch (NumberFormatException e) {
return false;
}
}
if (pid != null) {
RunningAppProcessInfo activityMgr = new ActivityManager.RunningAppProcessInfo("omniNames", pid, null);
return activityMgr.processName != null ;
}
return false;
}
public void stopOmniNames() {
String pid = getOmniNamesPid();
android.os.Process.killProcess(Integer.parseInt(pid));
android.os.Process.sendSignal(Integer.parseInt(pid), android.os.Process.SIGNAL_KILL);
}
private String getOmniNamesPid() {
Exec exec = new Exec();
final String[] args = new String[]
{RhMgrConstants.INSTALL_LOCATION_OMNI_NAMES_SCRIPTS + "/" + RhMgrConstants.OMNI_NAMES_SCRIPT_FILE,
"pid"};
String pid = "";
try {
int res = exec.doExec(args, null);
logMsg("oniNames pid return code: " + res);
} catch (IOException e) {
logMsg("Failed to start omniNames");
e.printStackTrace();
return pid;
}
String std = exec.getOutResult();
logMsg("omniNames pid: std out ==> " + std);
String err = exec.getErrResult();
logMsg("omniNames pid: err out ==> " + err);
String[] parts = std.split("\\s+");
if (parts.length >= 2) {
pid = parts[1];
}
return pid;
}
//monitor omniNames status and report status periodically to an IStatusListener
public void startMonitorProcess(IStatusListener listener, String string) {
this.listener = listener;
Timer t = new Timer();
t.schedule(task, 0, 1000);
}
private void logMsg(String msg) {
if (RhMgrConstants.DEBUG) {
System.err.println(msg);
}
}
}
Here's the Exec class that handles invocation of Runtime#exec(), consumes std and err out, and reports those and process return status to the caller.
Code:
public class Exec {
private String outResult;
private String errResult;
private Process process;
private boolean failed = false;
StreamReader outReader;
StreamReader errReader;
public int doExec(String[] cmd, String[] envp) throws IOException{
Timer t = null;
try {
process = Runtime.getRuntime().exec(cmd, envp);
outReader = new StreamReader(process.getInputStream());
outReader.setPriority(10);
errReader = new StreamReader(process.getErrorStream());
outReader.start();
errReader.start();
t = new Timer();
t.schedule(task, 10000);
int status = process.waitFor();
outReader.join();
errReader.join();
StringWriter outWriter = outReader.getResult();
outResult = outWriter.toString();
outWriter.close();
StringWriter errWriter = errReader.getResult();
errResult = errWriter.toString();
errWriter.close();
return (failed ? -1: status);
} catch (InterruptedException e) {
return -1;
} finally {
if (t != null) {
t.cancel();
}
}
}
public int doExec(String[] cmd) throws IOException{
return doExec(cmd, null);
}
public String getOutResult(){
return outResult;
}
public String getErrResult(){
return errResult;
}
private static class StreamReader extends Thread {
private InputStream is;
private StringWriter sw;
StreamReader(InputStream is) {
this.is = is;
sw = new StringWriter(30000);
}
public void run() {
try {
int c;
while ((c = is.read()) != -1){
sw.write(c);
}
}
catch (IOException e) { ; }
}
StringWriter getResult() {
try {
is.close();
} catch (IOException e) {
System.err.println("Unable to close input stream in StreamReader");
}
return sw;
}
}
private TimerTask task = new TimerTask() {
@Override
public void run() {
failed = true;
process.destroy();
}
};
}
Here's the script that startOminNames() invokes. It's the shell script installed with omniORB with functions other than start and get_pid removed, since those are handled by Android classes. You can invoke any executable in place of the script, or wrap your executable in a script.
Code:
#
# omniNames init file for starting up the OMNI Naming service
#
# chkconfig: - 20 80
# description: Starts and stops the OMNI Naming service
#
exec="/sdcard/data/com.axiosengineering.rhmanager/omniORB/bin/omniNames"
prog="omniNames"
logdir="/sdcard/data/com.axiosengineering.rhmanager/omniORB/logs"
logfile="/sdcard/data/com.axiosengineering.rhmanager/omniORB/logs/omninames-localhost.err.log"
options=" -start -always -logdir $logdir -errlog $logfile"
start() {
#[ -x $exec ] || exit 5
echo -n $"Starting $prog: "
$exec $options
}
get_pid() {
ps | grep omniNames
}
case "$1" in
start)
start && exit 0
$1
;;
pid)
get_pid
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
exit 2
esac
exit $?
And here's the IStatusListener interface
Code:
public interface IStatusListener {
public void running(boolean running);
}
Runtime.exec() has some pitfalls. See this helpful Runtime.exec tutorial for a nice explanation.
And you may also want to check out this post on loading native binaries in Android.