I have implemented a solution
try {
var process = Runtime.getRuntime().exec("logcat ${BuildConfig.APPLICATION_ID}:V *:S")
process = Runtime.getRuntime().exec("logcat -f " + "/storage/emulated/0/"+"Logging.txt")
} catch (e: Exception) {
e.printStackTrace()
}
Do we need to run this command only once or multiple times, as on Android 11 Chromebook it is working fine when run once, and on Android 10 Tablet it stops writing to file when run once, when i run it again then it writes to the same file
you have to run this snippet every time for storing all logs to file, it dumps only current logcat content. you have fixed file name so further calls are adding text to already existing file (note that this may cause duplicated lines, if only one new appeared in log, as method is storing whole output without clearing it)
Related
Recently, I am trying Android sub process with Runtime.getRuntime().exec(command) and found that I can destroy a NodeJS http server but cannot destroy a Go http server.
for node and go binary, it is available from Termux;
node http server: https://github.com/stallpool/halfbase/tree/master/nodejs/tinyserver/index.js
go http server: https://github.com/stallpool/halfbase/blob/master/golang/tinyserver/main.go
For node sub process, it can be started in an Android Service and p.waitFor(); when it is time, it can be killed by p.destroy()
However, for go sub process, it can be started but cannot be killed by p.destroy() even p. destroyForcibly(); in this article https://medium.com/honestbee-tw-engineer/gracefully-shutdown-in-go-http-server-5f5e6b83da5a , it makes sure a go server can be closed gracefully and I tried it but p.destroy() still does not work.
It is appreciated if anyone can light me a way to kill the process. thx!
just figured out a hack way; not elegant; guide me to a better solution if any!
Log.d("AppDebug", p.javaClass.getName())
// from above log
// we can know Android use "java.lang.UNIXProcess" as implementation of java.lang.Process
// to make sure the sub process is killed eventually
if (p.isAlive()) {
val klass = p.javaClass
if (klass.getName().equals("java.lang.UNIXProcess")) {
Log.d("AppDebug", "force terminate sub process ..")
try {
val f = klass.getDeclaredField("pid");
f.setAccessible(true);
val pid = f.getInt(p);
// XXX: buggy here, if getInt throw an error, the filed is exposed!
f.setAccessible(false);
android.os.Process.killProcess(pid);
Log.d("AppDebug", "force terminating done.")
} catch (e: Exception) {
Log.d("AppDebug", "force terminating failed.")
}
} else {
Log.d("AppDebug", "force terminating not supported.")
}
}
sorry for my misleading. currently I totally understand why my go server cannot be killed after I add some log about ps -ef before/after kill the process.
actually I use go run main.go to start the server; however, go run main.go will compile the code and generate a binary file in tmp folder; then it will spawn a child process (execute the binary); when I did p.destroy(), it merely kill the go process but the child server process remains there.
the correct solution is, get pid like above code; and use ps -o pid= --ppid=<pid> to get children tree and kill all processes for a cleanup.
I have an android app. I have a few users who have a recurring problem: When the app shuts down, every file the app saved is gone. Every folder created is gone. Everything is completely wiped back to square one.
I am carefully saving the game data during every transition and game event, so I am very confident that this is not a case of the user crashing out before the data can be written. Somehow, the data that IS being written but then it's just not persisting after the app is removed from memory.
So-- has anyone had this situation and solved it? The only thing I can imagine is that there's some kind of "filesystem.commit" command I need to call after writing the files, but I can't find that documented anywhere.
Please help!
(Edit) I'm using native code to read and write files. The code I use to write a file is this:
bool WriteFile(char *theFilename, char *theDataPtr, int theLen)
{
FILE* aFile=fopen(theFilename,"w+");
if(!aFile) {Alert("unable to create file %s with error %d", theFilename, errno);return false;}
if(aFile) fclose(aFile);
aFile=fopen(theFilename,"w+b");
if(!aFile) {Alert ("unable to open file %s", theFilename);return false;}
if (aFile)
{
fwrite(theDataPtr, 1, theLen,aFile);
fclose(aFile);
return true;
}
return false;
}
Note:No customers are reporting any alert popups, which are just normal Android message boxes. Also note that this code works on almost every other system-- there's just a few customers that get the wiped data, so I was wondering if it's some weird security or some extra step I need to do to be 100% compatible with all systems.
(Edit) One more piece of information... this is the Java code I use to get the storage path for the app... all files that I try to write are put in this folder.
private void SetFilePath()
{
String storagePath = getFilesDir().getAbsolutePath();
// SDCARD
try {
String storageState = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(storageState))
storagePath = getExternalFilesDir(null).getAbsolutePath();
} catch (Exception e) {
Log.v(IDS.LOG,
"No permission to access external storage, missing android.permission.WRITE_EXTERNAL_STORAGE");
}
SetFilePathNative(storagePath); // Tells the native code the path
mStorageDir = storagePath;
}
In Eclipse, I notice that Logcat only retains a few dozen entries and deletes the older ones as soon as a new one come in. Is there a way to prevent this? I need my app to run for a long time and not lose any entries because my app eventually hangs or crashes after a few days, and I want to see if something in Logcat has been recorded.
I am not sure if this is the most elegant solution to the problem, but you can always increase the LogCat message size in Eclipse.
Window -> Preferences -> Android -> LogCat -> Maximum number of LogCat messages to buffer
The default is 5000, I believe. You can set it to be very high if you are planning to run your application for a long time.
i think you need to increase this show image
Here's a better solution:
Set the Default Uncaught Exception Handler. Whenever the app crashes, this will be called with the exception. Simply write a log entry saying it crashed then dump the logcat to a file. Finally, make sure you re-throw the exception to make sure the app crashes and funky things don't happen. Note: This is per thread, keep that in mind.
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
Log.e("TAG", "---My app crashed just now---", ex);
//TODO: Dump logcat to file
throw new RuntimeException(ex);
}
});
if you want to keep your app running for days.. its better you capture your logs from adb shell.
the common shell command would be :
logcat -c \\ to clear previous logs
logcat -v time>yourLogs.txt & \\ to capture fresh logs
First thing my app does is checking for "su" since it's necessary for the app to work. Even though it sometimes work, often after typing "killall packageName" in the terminal. I've done a simple test application and I can't get it to work every time.
Code where it happens:
String[] args = new String[] { "su" };
Log.v(TAG, "run(" + Arrays.toString(args) + ")");
FutureTask<Process> task = new FutureTask<Process>(new Callable<Process>() {
#Override
public Process call() throws Exception {
return Runtime.getRuntime().exec(args);
}
});
try {
Executors.newSingleThreadExecutor().execute(task);
return task.get(10, TimeUnit.SECONDS);
} catch (Throwable t) {
task.cancel(true);
throw new IOException("failed to start process within 10 seconds", t);
}
Complete project: https://github.com/chrulri/android_testexec
Since this app does nothing more than running exec() in the first place, I cannot close any previously opened file descriptors as mentioned in another stackoverflow question: https://stackoverflow.com/a/11317150/1145705
PS: I run Android 4.0.3 / 4.0.4 on different devices.
3c71 was right about open file descriptors. In my case, it was the AdMob SDK which caused the problems since it was sometimes (re-)loading the Ads from the web at the sime time I tried to call exec(..) leaving me hanging in a deadlock.
My solution is to fork a "su" process ONCE and reuse it for all commands and load the Ads AFTER forking that process.
To use Runtime.exec safely you should wait for the process to finish and consume the output and error streams, preferably concurrently (to prevent blocking):
http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html
I am new to android world.
I have made an application of a user registration. It was working fine. but when i tried to add a spinner to my activity file, it was showing an error in avd, like,
The Application Registration (Process com.students) has stopped
unexpectedly. please try again
comes.
and my log cat is showing the error
"11-12 10:42:06.816: E/dalvikvm(313): Unable to open stack trace file
'/data/anr/traces.txt': Permission denied"
What is actually that error? How can i get rid of that?
You are trying to access the external storage. Make sure you have necessary permission defined in your Manifest file. This can be done by adding
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
This error has nothing to do with your app. Its referring stack trace file that gets generated when your app crashes so the user can report it to the publisher. The reason you are seeing that error is that your app was not installed through the android market so it does not have permission to write to that file. Errors that your app is generating during debug can be seen in LogCat and a stack trace will be dumped there describing the error.
This was a problem I had when I was new to Android. Then I learned that the message about being unable to write to traces.txt was not the actual problem with the program.
The solution to this problem is thus to find and correct the actual (unrelated to this message) reason the program is crashing. Then this message (which reflects a configuration problem in the crash reporting system) will no longer occur.
The operation on /data/anr/traces.txt need root or system user chmod.
Ref ActivityManagerService#dumpStackTraces code:
public static File dumpStackTraces(boolean clearTraces, ArrayList<Integer> firstPids,
ProcessCpuTracker processCpuTracker, SparseArray<Boolean> lastPids, String[] nativeProcs) {
String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
if (tracesPath == null || tracesPath.length() == 0) {
return null;
}
File tracesFile = new File(tracesPath);
try {
if (clearTraces && tracesFile.exists()) tracesFile.delete();
tracesFile.createNewFile();
FileUtils.setPermissions(tracesFile.getPath(), 0666, -1, -1); // -rw-rw-rw-
} catch (IOException e) {
Slog.w(TAG, "Unable to prepare ANR traces file: " + tracesPath, e);
return null;
}
dumpStackTraces(tracesPath, firstPids, processCpuTracker, lastPids, nativeProcs);
return tracesFile;
}
And I handle the problem in the shell as following.
adb root
adb shell touch /data/anr/traces.txt
adb shell kill -3 ${APP_PID}