Hi!
I have been developing android app which records sounds from the phones mic. Error happens when trying to excecute this method:
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
public void startRecording(View view) {
System.out.println("Start recording");
final Button aloita = (Button) findViewById(R.id.button3);
final Button lopeta = (Button) findViewById(R.id.button2);
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(tiedostonimi);
try {
recorder.prepare();
} catch (IOException e) {
Log.e(LOG_TAG, "prepare() kusi");
}
System.out.println(LOG_TAG);
recorder.start();
aloita.setEnabled(false);
lopeta.setEnabled(true);
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Error: Unfortunately myapp has stopped
LogCat: Could not excecute method of the activity and then some onClick errors
If I comment all the recorder.* from this method the app works fine. (I use also System.out.println as a debug tool)
I need help!
Update:
I changed the outputfiles variable and now I've got error: start called in an invalid state: 4.
Related
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 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.
I have to record the touch event of any android (.apk) application. For that I have created the .jar(Library) file which is responsible to record touch event when user press any control. This .jar will be injected with any .apk file.
For achieve the above things I have follow the below step.
1)I have created application with only one button name App.apk.
2)Also Create the another library project called Test.jar
3)Give the dependency of Test.jar to App.apk.
Now I want send same event to test.jar. I have write below code in App.apk activity
@override
public void onResume()
{
super.onResume();
Test.Event.MyHook(this);
}
@override
public void onPause()
{
super.onPause();
Test.Event.MyUnHook(this);
}
@override
public boolean dispatchKeyEvent(android.view.KeyEvent event)
{
Test.Event.MyEvent(event);
return super.dispatchKeyEvent(event);
}
Can u suggest the way to get button click event from App.apk to Test.jar ?
Thanks
maheng said:
I have to record the touch event of any android (.apk) application. For that I have created the .jar(Library) file which is responsible to record touch event when user press any control. This .jar will be injected with any .apk file.
For achieve the above things I have follow the below step.
1)I have created application with only one button name App.apk.
2)Also Create the another library project called Test.jar
3)Give the dependency of Test.jar to App.apk.
Now I want send same event to test.jar. I have write below code in App.apk activity
@override
public void onResume()
{
super.onResume();
Test.Event.MyHook(this);
}
@override
public void onPause()
{
super.onPause();
Test.Event.MyUnHook(this);
}
@override
public boolean dispatchKeyEvent(android.view.KeyEvent event)
{
Test.Event.MyEvent(event);
return super.dispatchKeyEvent(event);
}
Can u suggest the way to get button click event from App.apk to Test.jar ?
Thanks
Click to expand...
Click to collapse
Seems rather fishy why you'd have to do that, but let's roll with it...^^
TLDR: in pure java, using standard APIs or even reflection or root, you can't.
You could use the android-event-injector project (which is a C++/JNI library) : https://code.google.com/p/android-event-injector/
It provides methods to listen to all input events, something like that (this will send all the results to logcat):
PHP:
public void StartEventMonitor() {
m_bMonitorOn = true;
Thread b = new Thread(new Runnable() {
public void run() {
while (m_bMonitorOn) {
for (InputDevice idev:events.m_Devs) {
// Open more devices to see their messages
if (idev.getOpen() && (0 == idev.getPollingEvent())) {
final String line = idev.getName()+
":" + idev.getSuccessfulPollingType()+
" " + idev.getSuccessfulPollingCode() +
" " + idev.getSuccessfulPollingValue();
Log.d(LT, "Event:"+line);
}
}
}
}
});
b.start();
}
You can read more here: http://www.pocketmagic.net/2013/01/programmatically-injecting-events-on-android-part-2/
However, you might also be able to do that using the Xposed framework and finding a hook into the actual framework class for dispatchKeyEvent if it's the event you want to intercept.
I've never with Xposed so I can't really help you with the implementation, though, but it might be something to look into.
Hi all i'm having troubles with an app that I'm developing. I make use of NotificationListenerService, prompt the user to set the Notification permission from the menu and all works flawlessly. But when I update my app, or when my service gets killed it, for unknown reasons, doesn't restart.
In `onCreate()` I retain a reference to the service with `instance = this;` that I use to determine if my service is running from other classes.
This is some methods in `onNotificationPosted(StatusBarNotification notification)` that extends NotificationListenerService:
PHP:
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
if (MyOtherService.hasInstance()) {
Log.v(TAG, "onNotificationPosted called by system");
int count_debug = 1;
for (StatusBarNotificationListenerInterface listener : toBeNotified) {
if(listener != null) {
Log.v(TAG, "Loop call #" + count_debug++);
listener.onNotificationHotAdded(sbn);
}
}
} else {
// MyOtherService isn't running. Does nothing but clearing toBeNotified list.
toBeNotified.clear();
Log.v(TAG, "onNotificationPosted: MyOtherService is stopped ");
}
}
public static void registerForNotifications(StatusBarNotificationListenerInterface listener) {
if (!toBeNotified.contains(listener)) {
Log.v(TAG, listener.getClass().getCanonicalName() + " added to toBeNotified list");
toBeNotified.add(listener);
}
}
NOTE: MyOtherService extends DreamService and just register itself calling the `registerForNotifications()` method.
In the `MyNotificationListener` I override `onStartCommand` returning `START_STICKY`
I'm really going crazy with this stuff being killed almost at each update.
klarkent said:
Hi all i'm having troubles with an app that I'm developing. I make use of NotificationListenerService, prompt the user to set the Notification permission from the menu and all works flawlessly. But when I update my app, or when my service gets killed it, for unknown reasons, doesn't restart.
In `onCreate()` I retain a reference to the service with `instance = this;` that I use to determine if my service is running from other classes.
This is some methods in `onNotificationPosted(StatusBarNotification notification)` that extends NotificationListenerService:
PHP:
@Override
public void onNotificationPosted(StatusBarNotification sbn) {
if (MyOtherService.hasInstance()) {
Log.v(TAG, "onNotificationPosted called by system");
int count_debug = 1;
for (StatusBarNotificationListenerInterface listener : toBeNotified) {
if(listener != null) {
Log.v(TAG, "Loop call #" + count_debug++);
listener.onNotificationHotAdded(sbn);
}
}
} else {
// MyOtherService isn't running. Does nothing but clearing toBeNotified list.
toBeNotified.clear();
Log.v(TAG, "onNotificationPosted: MyOtherService is stopped ");
}
}
public static void registerForNotifications(StatusBarNotificationListenerInterface listener) {
if (!toBeNotified.contains(listener)) {
Log.v(TAG, listener.getClass().getCanonicalName() + " added to toBeNotified list");
toBeNotified.add(listener);
}
}
NOTE: MyOtherService extends DreamService and just register itself calling the `registerForNotifications()` method.
In the `MyNotificationListener` I override `onStartCommand` returning `START_STICKY`
I'm really going crazy with this stuff being killed almost at each update.
Click to expand...
Click to collapse
just to help others ( sorry for old post) bute start_sticky has a bug in android 4.4+
https://code.google.com/p/android/issues/detail?id=63793
I'm new to parse. Having trouble with updating. I don't have a problem at all with saving and retrieving user data. Just updating users data.
In my error toast I added some code to tell me my objectId. According to that its the objectId for my User. Not profile_info like I believe I need.
The error I get is "no result for query".
Code:
update.setOnClickListener(new OnClickListener() {
public void onClick(View arg1) {
final String obId = ParseUser.getCurrentUser().getObjectId();
ParseQuery<ParseObject> query = ParseQuery.getQuery("profile_info");
query.getInBackground(obId, new GetCallback<ParseObject>() {
public void done(ParseObject profile_info, ParseException e) {
if (e == null) {
profile_info.put("first_name", fname.getText().toString());
profile_info.put("last_name", lname.getText().toString());
profile_info.put("height_in_feet", hf.getText().toString());
profile_info.put("height_in_inches", hi.getText().toString());
profile_info.put("weight", weight.getText().toString());
profile_info.put("waist", waist.getText().toString());
profile_info.put("wrist", wrist.getText().toString());
profile_info.put("hip", hip.getText().toString());
profile_info.put("forearm", forearm.getText().toString());
profile_info.saveInBackground();
Toast.makeText(getApplicationContext(),
"Your profile has been updated",
Toast.LENGTH_SHORT)
.show();
} else {
Toast.makeText(getApplicationContext(),
"Error saving: " + e.getMessage() + "\nthe objectId is " + obId,
Toast.LENGTH_SHORT)
.show();
}
}
});
}
})
[\CODE]
Sent from my Nexus 6 using XDA Free mobile app
I figured it out. Not sure if this is the right way to do it but it works.
Code:
ParseQuery<ParseObject> pQuery = new ParseQuery<ParseObject>("profile_info");
pQuery.whereEqualTo("first_name", fname.getText().toString());
pQuery.getFirstInBackground(new GetCallback<ParseObject>()
{ [user=439709]@override[/user]
public void done(ParseObject profile_info, ParseException e) {
if (e == null){
[\CODE]
I I also figured out that I can't change the text that's in the text field used in this: "pQuery.whereEqualTo"
Sent from my Nexus 6 using XDA Free mobile app