This question already has answers here:
How do I obtain crash-data from my Android application?
(30 answers)
Closed 5 months ago.
I'm currently developing an android app. I noticed a very rare error which leeds to a crash of my app. Unfortunately, I had my smartphone never connected to my pc when it occured. So, is there a way to automatically save all logs (and especially the thrown runtimeexceptions) to a file when my app starts, so that I can copy this file to my pc and analyse the error? The file should be overwritten on every start of my app, so that it contains only the logs of the last run... How can I achieve that?
regards
You can find help by following this link Writing crash reports into device sd card
You don't need to add external library.
import com.wordpress.doandroid.Training.R;
import android.app.Activity;
import android.os.Bundle;
public class CaptureExceptionActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Sets the default uncaught exception handler. This handler is invoked
// in case any Thread dies due to an unhandled exception.
Thread.setDefaultUncaughtExceptionHandler(new CustomizedExceptionHandler(
"/mnt/sdcard/"));
String nullString = null;
System.out.println(nullString.toString());
setContentView(R.layout.main);
}
}
And the Handler implementation
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.os.Environment;
import android.util.Log;
public class CustomizedExceptionHandler implements UncaughtExceptionHandler {
private UncaughtExceptionHandler defaultUEH;
private String localPath;
public CustomizedExceptionHandler(String localPath) {
this.localPath = localPath;
//Getting the the default exception handler
//that's executed when uncaught exception terminates a thread
this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
}
public void uncaughtException(Thread t, Throwable e) {
//Write a printable representation of this Throwable
//The StringWriter gives the lock used to synchronize access to this writer.
final Writer stringBuffSync = new StringWriter();
final PrintWriter printWriter = new PrintWriter(stringBuffSync);
e.printStackTrace(printWriter);
String stacktrace = stringBuffSync.toString();
printWriter.close();
if (localPath != null) {
writeToFile(stacktrace);
}
//Used only to prevent from any code getting executed.
// Not needed in this example
defaultUEH.uncaughtException(t, e);
}
private void writeToFile(String currentStacktrace) {
try {
//Gets the Android external storage directory & Create new folder Crash_Reports
File dir = new File(Environment.getExternalStorageDirectory(),
"Crash_Reports");
if (!dir.exists()) {
dir.mkdirs();
}
SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy_MM_dd_HH_mm_ss");
Date date = new Date();
String filename = dateFormat.format(date) + ".STACKTRACE";
// Write the file into the folder
File reportFile = new File(dir, filename);
FileWriter fileWriter = new FileWriter(reportFile);
fileWriter.append(currentStacktrace);
fileWriter.flush();
fileWriter.close();
} catch (Exception e) {
Log.e("ExceptionHandler", e.getMessage());
}
}
}
Don't forget to add this permission in the manifest WRITE_EXTERNAL_STORAGE
Related
I'm a newbie in Android Development. I want to get metadata from Shoutcast Server, and found streamscraper to be the easiest one to use. But my problem is, I don't know how to use it. The homepage itself only showing something like in how to use it:
import java.net.URI;
import java.util.List;
import net.moraleboost.streamscraper.Stream;
import net.moraleboost.streamscraper.Scraper;
import net.moraleboost.streamscraper.scraper.IceCastScraper;
public class Harvester {
public static void main(String[] args) throws Exception {
Scraper scraper = new IceCastScraper();
List streams = scraper.scrape(new URI("http://host:port/"));
for (Stream stream: streams) {
System.out.println("Song Title: " + stream.getCurrentSong());
System.out.println("URI: " + stream.getUri());
}
}
}
Searched anywhere and found no project sample of how to use this. I hope one of you can post the code of how to use it, or make a tutorial for it.
No need to use external libraries. The following pages give you:
Current song: http://yourstream:port/currentsong?sid=#
Last 20 songs: http://yourstream:port/played.html?sid#
Next songs: http://yourstream:port/nextsongs?sid=#
An Android java class which prints the current song:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
public class NowPlaying {
public void CurrentSong() {
try
{
URL url = new URL("http://www.mofosounds.com:8000/currentsong?sid=#");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
catch(Exception e)
{
System.out.println(e.toString());
}
}
}
Note: the nextsongs?sid=#feature must be supported by the player of the stream.
I have a class developed in eclipse (on the same computer ) and I am trying to bring it over to Android Studio. Android Studio gives me an error, it cannot resolve symbol HttpsURLConnection
On Oracle's website and it is said the class is in java.net.URLConnection, when I import it the line is greyed saying it was already imported.
code:
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Date;
public class cBitTrex {
static int test;
/////////////////////////////////////////////////////////////////////
// Run code to talk to server on a thread
// Every onunce in a while code to tal to server will freex
// WEcall thread methed run and then wait for thread to exit with a time out
public class cThread extends Thread{
String reply=null;
String url;
public void run()
{
String ireply;
error="";
ireply="";
try {
ireply="";
URL myurl = new URL(url);
System.out.println("Open thread connection");
// This is where the error is
HttpsURLConnection con = (HttpsURLConnection)myurl.openConnection();
con.setConnectTimeout(15000);
System.out.println("Get input thread stream");
InputStream ins = con.getInputStream();
System.out.println("Create reader");
InputStreamReader isr = new InputStreamReader(ins);
System.out.println("Creat buffer threadreader");
BufferedReader in = new BufferedReader(isr);
String inputLine;
System.out.println("THREAD Read indata2");
int t;
while ((t= in.read()) != -1)
{
ireply+=(char)t;;
}
System.out.println("finish Read indata");
} catch (Exception e)
{
error=new String(e.getMessage());
System.out.println("Exception in getting data from API server");
reply=null;
}
// Set return valur at end of thread so if thread call tiimout we will not
// get any data
reply=ireply;
}
};
..
...
}
This class you are searching for does not exist, at least in Android. The one that is provided by the Android SDK is java.net.HttpURLConnection. By the way, something you really have to take into account is programming for Android is not just like normal Java, it has some special rules. The correct documentation to search at is the one located in the Android SDK official Page.
Beside that, your error can be that you were importing in Eclipse a Library that you are not using anymore in Android Studio.
I'm trying to serve a small file on my desktop using NanoHTTPD. The server starts fine but due to some unknown reason, it is unable to serve files. The same program works fine in Android. Can anyone give me some pointers? It's being more than an hour but I've got no clue. Here is my desktop version of NanoHTTPD server:
package com.desktopserver;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLConnection;
import java.util.Map;
import com.desktopserver.NanoHTTPD.Response.Status;
public class MainClass {
static int PORT = 8080;
static WebServer MyServer;
static FileInputStream fis;
static BufferedInputStream bis;
public static void main(String[] args) {
MyServer = new WebServer();
try {
MyServer.start();
System.out.println("Webserver Started # PORT:8080");
} catch (IOException e) {
e.printStackTrace();
}
}
public static class WebServer extends NanoHTTPD {
String MIME_TYPE;
public WebServer() {
super(PORT);
}
#Override
public Response serve(String uri, Method method,
Map<String, String> header, Map<String, String> parameters,
Map<String, String> files) {
try {
File file=new File("/home/evinish/Music/Meant_to_live.mp3");
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
MIME_TYPE= URLConnection.guessContentTypeFromName(file.getName());
System.out.println("\nMIME TYPE: "+MIME_TYPE);
System.out.println("\nFILE NAME: "+file.getName());
} catch (IOException ioe) {
System.out.println("File IO Exception");
}
return new NanoHTTPD.Response(Status.OK, MIME_TYPE, bis);
}
}
}
I do get this output, but that's it:
Webserver Started # PORT:8080
What am I missing here? Thanks a lot for your help.
Because you don't use "ServerRunner" class. ServerRunner hold you server to until any key press.
But in real application this don't work you want some change in NanoHTTPd file
line no 196 to
myThread.setDaemon(false);
I have used a tutorial and arrived at this result which works in an emulator, but it ceases to work on a real Android device.
The code is given here and all other Android permissions required are set; internet and write to external device are set.
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import org.apache.http.util.ByteArrayBuffer;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;
public class main extends Activity {
private final String PATH = "/mnt/sdcard/Pictures/";
TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView)findViewById(R.id.textView1);
DownloadFromUrl(PATH + "dwnldimg.png");
ImageView iv = (ImageView) findViewById(R.id.imageView1);
Bitmap bmp = BitmapFactory.decodeFile(PATH + "dwnldimg.png");
iv.setImageBitmap(bmp);
}
public void DownloadFromUrl(String fileName) {
try {
URL url = new URL("http://192.168.1.4/evilempire.jpg"); //you can write here any link
File file = new File(fileName);
long startTime = System.currentTimeMillis();
tv.setText("Starting download......from " + url);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();;
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
/*
* Read bytes to the Buffer until there is nothing more to read(-1).
*/
ByteArrayBuffer baf = new ByteArrayBuffer(50);
int current = 0;
while ((current = bis.read()) != -1) {
baf.append((byte) current);
}
FileOutputStream fos = new FileOutputStream(file);
fos.write(baf.toByteArray());
fos.close();
tv.setText("Download Completed in" + ((System.currentTimeMillis() - startTime) / 1000) + " sec");
} catch (IOException e) {
tv.setText("Error: " + e);
}
}
}
Prime lib will help you, but to learn Android you need to know AsyncTask. Android have the UI Thread where the Activity runs, so if you do complicate operation that block the Android OS will throw a Force Close.
So what you have to know is that if you need to do a download task or any operation that will eventually block the UI thread you can have to use Threads. The easy Android approach is AsyncTask.
I think this simple example will guide you to understand the AsyncTask.
http://developer.android.com/reference/android/os/AsyncTask.html
First of all your doing network operations on the main ui thread, which will result in a anr on pre-3.0 and a NetworkOnMainThreadException on 3.0+. Secondly I built Prime which is a whole lot easier at loading remote images.
The sun JVM supports a -XX:+HeapDumpOnOutOfMemoryError option to dump heap whenever a java process runs out of heap.
Is there a similar option on Android that will make an android app dump heap on an OutOfMemoryException? It can be difficult to try to time it properly when using DDMS manually.
To expand upon CommonsWare's answer:
I have no idea if this works, but you might try adding a top-level exception handler, and in there asking for a heap dump if it is an OutOfMemoryError.
I followed his suggestion successfully in my own Android app with the following code:
public class MyActivity extends Activity {
public static class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
#Override
public void uncaughtException(Thread thread, Throwable ex) {
Log.e("UncaughtException", "Got an uncaught exception: "+ex.toString());
if(ex.getClass().equals(OutOfMemoryError.class))
{
try {
android.os.Debug.dumpHprofData("/sdcard/dump.hprof");
} catch (IOException e) {
e.printStackTrace();
}
}
ex.printStackTrace();
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Thread.currentThread().setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
}
}
After the dump is created, you need to copy it from your phone to your PC: Click "Turn on USB storage" on the phone, find the file and copy it to your hard drive.
Then, if you want to use the Eclipse Memory Analyzer (MAT) to analyze the file, you will need to covert the file: hprof-conv.exe dump.hprof dump-conv.hprof (hprof-conv is located under android-sdk/tools)
Finally, open the dump-conv.hprof file with MAT
I have no idea if this works, but you might try adding a top-level exception handler, and in there asking for a heap dump if it is an OutOfMemoryError.
Here is an improved version. On top of the original implementation this implementation also supports:
Catching Out of Memory errors on all threads (not only on the main thread)
Identifying Out of Memory errors even when it's hidden inside a different error. On some instances the Out of Memory error is encapsulated inside a Runtime error.
Invoking the original default uncaught exception handler too.
Only works in DEBUG builds.
Usage: Call the static initialize method in your Application class in the onCreate method.
package test;
import java.io.File;
import java.io.IOException;
import java.lang.Thread.UncaughtExceptionHandler;
import android.os.Environment;
import android.util.Log;
import com.example.test1.BuildConfig;
public class OutOfMemoryDumper implements Thread.UncaughtExceptionHandler {
private static final String TAG = "OutOfMemoryDumper";
private static final String FILE_PREFIX = "OOM-";
private static final OutOfMemoryDumper instance = new OutOfMemoryDumper();
private UncaughtExceptionHandler oldHandler;
/**
* Call this method to initialize the OutOfMemoryDumper when your
* application is first launched.
*/
public static void initialize() {
// Only works in DEBUG builds
if (BuildConfig.DEBUG) {
instance.setup();
}
}
/**
* Keep the constructor private to ensure we only have one instance
*/
private OutOfMemoryDumper() {
}
private void setup() {
// Checking if the dumper isn't already the default handler
if (!(Thread.getDefaultUncaughtExceptionHandler() instanceof OutOfMemoryDumper)) {
// Keep the old default handler as we are going to use it later
oldHandler = Thread.getDefaultUncaughtExceptionHandler();
// Redirect uncaught exceptions to this class
Thread.setDefaultUncaughtExceptionHandler(this);
}
Log.v(TAG, "OutOfMemoryDumper is ready");
}
#Override
public void uncaughtException(Thread thread, Throwable ex) {
Log.e(TAG, "Uncaught exception: " + ex);
Log.e(TAG, "Caused by: " + ex.getCause());
// Checking if the exception or the original cause for the exception is
// an out of memory error
if (ex.getClass().equals(OutOfMemoryError.class)
|| (ex.getCause() != null && ex.getCause().getClass()
.equals(OutOfMemoryError.class))) {
// Checking if the external storage is mounted and available
if (isExternalStorageWritable()) {
try {
// Building the path to the new file
File f = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
long time = System.currentTimeMillis();
String dumpPath = f.getAbsolutePath() + "/" + FILE_PREFIX
+ time + ".hprof";
Log.i(TAG, "Dumping hprof data to: " + dumpPath);
android.os.Debug.dumpHprofData(dumpPath);
} catch (IOException ioException) {
Log.e(TAG,"Failed to dump hprof data. " + ioException.toString());
ioException.printStackTrace();
}
}
}
// Invoking the original default exception handler (if exists)
if (oldHandler != null) {
Log.v(TAG, "Invoking the original uncaught exception handler");
oldHandler.uncaughtException(thread, ex);
}
}
/**
* Checks if external storage is available for read and write
*
* #return true if the external storage is available
*/
private boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
Log.w(TAG,"The external storage isn't available. hprof data won't be dumped! (state=" + state + ")");
return false;
}
}