I'm trying to use Jsoup 1.6.0 in my Android application, but for some reason it crashes. I simplified my code to:
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
public class JsoupTestActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
Document d = Jsoup.connect("http://www.google.com").get();
} catch (Exception e) {
Toast t = Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG);
t.show();
}
}
}
But whenever I run the above on my phone (in USB debugging mode) or on the emulator, I get the message that my program has unexpectedly crashed--an error wasn't even caught. If I replace the contents of the try block with
Jsoup.connect("http://www.google.com");
the program works fine, so it seems like the get() method is causing the problems...
FYI, in my AndroidManifest.xml I did include
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
in the correct place, and R.layout.main is the default layout that the ADT generates when you create a new project. I'm using Android API level 7 for this project. How do I get this to work?
Try to download new version of Jsoup and paste jsoup-1.6.x.jar in libs folder from your project.
you can't do Network operations from the UI thread, so you should take the JSoup.connect() out of your onCreate() and use an ASyncTask
Related
I have an app that crashes at random times when I don't have a computer nearby to view logcat. Therefore I want to write the reason for a fatal error / every error to a file on my phone that I can read later to debug. I tried using try catch, but I am looking for a complete solution, like a command I enter once and it captures every crash and saves it, like an observer above the code respectively a kind of virtual box.
Which command helps me here?
Using a file for this is a bad idea - Not only do you possible have to worry about extra permissions but you also have to write a fair amount of code.
There are many libraries out there to catch Exceptions and log them for you.
Furthermore in a live environment this won't work at catching bugs since you can't ask users to send them a log file.
I use Fabric (Firebase)
https://firebase.google.com/docs/crashlytics/get-started
You're probably looking for Thread.UncaughtExceptionHandler or even better, Firebase Crashlytics.
I to wanted something similar, the solution that I came up with that works a bit was a Debug Log activity in the app that reads the logcat output in to a TextView.
I then Start this activity from a Menu Item or Button to show previous crashes.
Normally Android Studio Logcat window is just opening a remote shell on to the device with ADB and running the logcat command on the Android Device.
This method runs the logcat command on the Device itself without the need of a remote shell, but you need some Java code in your app to do this.
(This Extra Activity has to be in the Same App as you only have permission to see you own App's logcat)
(This does not always seem to pick up always all Log output but it does pickup crashes)
NOTE
The try and catch in this example code has nothing to do with trying to catch the errors Alex is Hunting as some people thought but to catch a possible error in the logcat display code. The logcat text shown by this Activity will show stack traces of those errors Alex is hunting.
This could then be run after restarting the app.
Code to do this is (Note you need to replace the "YOUR_APPS_TAG" with the Log TAG used by your app) See https://developer.android.com/studio/command-line/logcat for the filter specs
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class DebugLogActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_debug_log);
try {
Process process = Runtime.getRuntime().exec("logcat -d -D -v long " + "YOUR_APPS_TAG" + ":V *:E");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
StringBuilder log=new StringBuilder();
String line = "";
while ((line = bufferedReader.readLine()) != null) {
log.append(line );
log.append(System.getProperty("line.separator"));
}
TextView tv = (TextView)findViewById(R.id.debugLog);
tv.setMovementMethod(new ScrollingMovementMethod());
tv.setTextIsSelectable(true);
tv.setText(log.toString());
} catch (IOException e) {
if (BuildConfig.LOG) {
Log.e("YOUR_APPS_TAG", "DebugLogActivity:onCreate:" + e.toString() + Arrays.toString(e.getStackTrace()));
}
}
}
}
The xml (actvitiy_debug_log.xml) for this extra activity
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".debuglogActivity">
<TextView
android:id="#+id/debugLog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars = "vertical"
/>
</androidx.appcompat.widget.LinearLayoutCompat>
Example ScreenShot of running Activity after a crash
You can then copy and paste the text out and send it to yourself or just read it in the app.
I'm currently implementing a UI crawler for hybrid Android apps (i.e., Android apps implemented using PhoneGap), and the crawler requires periodic restarts to generate a model of the UI. Here, by "restart", I mean uninstall the app, do a fresh install of the same app, and resume execution of the crawler. (The idea is to get to the same initial state as before. One could argue that I can just reload the initial HTML page, but this would only work if the app does not save and reuse any data like login information, etc. The data needs to be fresh - i.e., what it was when the app was installed for the first time).
I'm quite new to Android app development, so I decided to test out what is perhaps the most naive method possible. The test code I've written is shown below. The method testReinstall() runs as an Android JUnit test, and I'm using Robotium 4.3 to execute clicks and other events on the app.
package com.example.googleauthenticator.test;
import java.io.IOException;
import android.test.ActivityInstrumentationTestCase2;
import com.example.googleauthenticator.MainActivity;
import com.jayway.android.robotium.solo.By;
import com.jayway.android.robotium.solo.Solo;
public class ReinstallTest extends ActivityInstrumentationTestCase2<MainActivity> {
private Solo solo;
public ReinstallTest() {
super(MainActivity.class);
}
#Override
protected void setUp() throws Exception {
super.setUp();
solo = new Solo(getInstrumentation(), getActivity());
}
public void testReinstall() {
//Reinstall app
Runtime rt = Runtime.getRuntime();
Process pr;
try {
pr = rt.exec("adb uninstall com.example.googleauthenticator"); //Uninstall
pr.waitFor();
pr = rt.exec("adb install GoogleAuthenticator.apk"); //Install
pr.waitFor();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException ie) {
// TODO Auto-generated catch block
ie.printStackTrace();
}
System.out.println("Reinstall done!");
//Perform some action
if (solo.waitForWebElement(By.id("add"))) {
solo.clickOnWebElement(By.id("add"));
}
}
#Override
protected void tearDown() throws Exception{
solo.finishOpenedActivities();
super.tearDown();
}
}
I tried running the above code and it seems like it was able to successfully uninstall the app (or, at the very least, I know for a fact that the data/data/com.example.googleauthenticator folder was removed). However, the app does not get reinstalled (i.e., the data/data/com.example.googleauthenticator folder is still not there), and I presume this is related to the fact that by the time the first call to pr.waitFor() is reached, testReinstall() terminates due to a "Process crash", and the following message appears in the LogCat:
11-08 17:08:32.763: W/PluginManager(9285): Can't find plugin: com.example.googleauthenticator
What am I missing here? Is there a better/more correct way?
EDIT: To be clear, I'm also getting the following error message:
11-08 17:33:40.883: D/WebKit(14828): Unabled to create LocalStorage database path /data/data/com.example.googleauthenticator/app_database/localstorage
You cannot remove the application you are testing, infact exiting the application you are testing will mean that your test stops running this is because with instrumentation your test and your application are the same process.
Just because you cannot do what you want via robotium/instrumentation though does not mean what you want to do is impossible, you will just need to use an automation tool not based on instrumentation that runs off device, Calabash for example will automatically reinstall the application for you depending on if you use the correct annotation, this might be a better fit for what you want to do.
I have a problem with jsoup on android. I have seen the other posts and tried solutions that were suggested there ( re-adding the jars, calling android fix tool, etc.)
I have added the jsoup jar to my android project (using build path), and added the required
internet permission to my manifest.
<uses-permission android:name="android.permission.INTERNET" />
but when I am trying to run my application I am getting
Could not find method org.jsoup.Jsoup.connect, referenced from method com.example.test.MainActivity.onCreate
I have tried to use the android fix tool but it did not solve the problem.
All I have is a main activity and I am trying to call
Document doc = Jsoup.connect("http://en.wikipedia.org/").get();
attached is part of my code
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
Document doc = Jsoup.connect("http://en.wikipedia.org/").get();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
You are trying to run your connection in your main thread. Use AsyncTask and it will work.
I.E.
public class JsoupParser extends AsyncTask...
Why you have to use AsyncTask for network connections in android?
AsyncTask is an abstract helper class that enables you to use the UI thread correctly, while performing background operations in a different thread, without having to really handle threads or controllers. Since android is implemented using a single thread model, each time you launch an application, a new thread will be created.
Imagine you have a single thread model where you at a button click will parse a website using Jsoup. This would have worked fine in earler android versions, though you would have had a non-responsive screen until the network operation is done. The AsyncTask will run in the background enabling your screen to still be responsive while another thread takes care of the network communication.
Take a look in the API:
AsyncTask
NetworkOnMainThreadException
Delete all statements like:
System.out.println(something);
It worked for me, realizing this took me 2 hours.
In you normal activity
use this
public static int SDK_INT = android.os.Build.VERSION.SDK_INT;
and before fetching Document
write this inside try block
if (SDK_INT >= 10) {
ThreadPolicy tp = ThreadPolicy.LAX;
StrictMode.setThreadPolicy(tp);
}
it worked for me
I have a PhoneGap application that works fine but occasionally is known to have bugs. I would like to catch them and send them to a Google Doc with ACRA
I have been following the ACRA wiki steps here http://code.google.com/p/acra/wiki/BasicSetup?tm=6
The ACRA documentation says I should create an Application class and then point my AndroidManifest at it by naming the Application the same as that class.
That didn't work, or at least it didn't catch any errors I tested it with.
I thought this would be the best bet, but it isn't logging anything and still Force Closes the app when I force a NullPointer exception error.
#ReportsCrashes(formKey = "dFhqOGY3cVVGc0w4UUxGa2E2Y3RL...",
mode = ReportingInteractionMode.NOTIFICATION)
public class myPhoneGap extends DroidGap
{
#Override
public void onCreate(Bundle savedInstanceState)
{
ACRA.init(this.getApplication());
super.onCreate(savedInstanceState);
super.init();
super.loadUrl("file:///android_asset/www/index.html");
}
}
I'm pretty sure you have to set up another activity that extends Application like this:
package jq.test;
import android.app.Application;
import org.acra.*;
import org.acra.annotation.*;
#ReportsCrashes(formKey = "xxxxxxxxxxxxxxxxxxxxxxxxx")
public class MyApplication extends Application {
#Override
public void onCreate() {
// The following line triggers the initialization of ACRA
ACRA.init(this);
super.onCreate();
}
}
and then in your manifest change the name of the application to the name of the class. I'm pretty sure that that's it but I have a question for you.....how do you get the formkey from Google Docs? I can't remember how to do that lol and its not posted anywhere. It really should be in the acra wiki but its not.
This question already has answers here:
capturing and sending logcat output by email or to server
(2 answers)
Closed 9 years ago.
I installed the .apk file in the device then run that application at this time suppose i am getting any exception then application will be crash. At this time i want to see that exception in the device without using Eclipse Logcat. It means i want send that exception to file(means some path in the device like sdcard/downloads/a.txt)in the device using Log.
Generally some applications are working properly in the emulator but in case of device we got some exceptions. so thats why i want see that particular exception in the device using Log.
Is it possible? How can i implement this? can anybody help me.
Myapplication classs:
package com.ibkr.roadbrake;
import org.acra.*;
import org.acra.annotation.*;
import android.app.Application;
import android.os.Bundle;
#ReportsCrashes(formKey = "dDJ5VFhURVNHakhSa3hfTndteFd6Smc6MQ")
public class MyApplication extends Application
{
#Override
public void onCreate()
{
// The following line triggers the initialization of ACRA
ACRA.init(this);
super.onCreate();
}
public Bundle getCrashResources()
{
Bundle result = new Bundle();
String RES_TOAST_TEXT = null;
result.putInt(RES_TOAST_TEXT, R.string.crash_toast_text);
return result;
}
}
thanks
Log4j or slf4j can also be used as logging frameworks in Android together with logcat. See the project android-logging-log4j and log4j support in Android. Configuring logging to a (rotating) file(s) is very easy.
static {
final LogConfigurator logConfigurator = new LogConfigurator();
logConfigurator.setFileName(Environment.getExternalStorageDirectory() + "myapp.log");
logConfigurator.setRootLevel(Level.DEBUG);
// Set log level of a specific logger
logConfigurator.setLevel("org.apache", Level.ERROR);
logConfigurator.configure();
}