Search code examples
javaandroidbroadcastreceiverjsoup

How to solve "UnsatisfiedLinkError" while using Jsoup in an Android BroadcastReceiver?


What I'm Doing:

In my app (Android with minSdkVersion 15), I have a BroadcastReceiver that listens to Intent.ACTION_PACKAGE_ADDED (A new application package has been installed on the device). Whenever that happens, the receiver tries to fetch some data from the internet using Jsoup.


The Problem:

My code below works correctly as long as my app is running in the background when I install another app (say from the Play Store). But if I kill my app and then install another app, my app crashes showing me the "My app has stopped" dialog (because my receiver crashed) as well as this error:

No implementation found for long com.android.tools.profiler.support.network.HttpTracker$Connection.nextId() (tried Java_com_android_tools_profiler_support_network_HttpTracker_00024Connection_nextId and Java_com_android_tools_profiler_support_network_HttpTracker_00024Connection_nextId__)
FATAL EXCEPTION: AsyncTask #1
Process: com.myorg.myapp, PID: 11796
java.lang.RuntimeException: An error occurred while executing doInBackground()
    at android.os.AsyncTask$3.done(AsyncTask.java:325)
    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
    at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
    at java.util.concurrent.FutureTask.run(FutureTask.java:242)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
    at java.lang.Thread.run(Thread.java:761)
Caused by: java.lang.UnsatisfiedLinkError: No implementation found for long com.android.tools.profiler.support.network.HttpTracker$Connection.nextId() (tried Java_com_android_tools_profiler_support_network_HttpTracker_00024Connection_nextId and Java_com_android_tools_profiler_support_network_HttpTracker_00024Connection_nextId__)
    at com.android.tools.profiler.support.network.HttpTracker$Connection.nextId(Native Method)
    at com.android.tools.profiler.support.network.HttpTracker$Connection.<init>(HttpTracker.java:191)
    at com.android.tools.profiler.support.network.HttpTracker$Connection.<init>(HttpTracker.java:186)
    at com.android.tools.profiler.support.network.HttpTracker.trackConnection(HttpTracker.java:280)
    at com.android.tools.profiler.support.network.httpurl.TrackedHttpURLConnection.<init>(TrackedHttpURLConnection.java:49)
    at com.android.tools.profiler.support.network.httpurl.HttpsURLConnection$.<init>(HttpsURLConnection$.java:50)
    at com.android.tools.profiler.support.network.httpurl.HttpURLWrapper.wrapURLConnectionHelper(HttpURLWrapper.java:40)
    at com.android.tools.profiler.support.network.httpurl.HttpURLWrapper.wrapURLConnection(HttpURLWrapper.java:55)
    at org.jsoup.helper.HttpConnection$Response.createConnection(HttpConnection.java:889)
    at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:727)
    at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:706)
    at org.jsoup.helper.HttpConnection.execute(HttpConnection.java:299)
    at org.jsoup.helper.HttpConnection.get(HttpConnection.java:288)
    at com.myorg.myapp.InstallReceiver$PlayStoreFetcher.doInBackground(InstallReceiver.java:76)
    at com.myorg.myapp.InstallReceiver$PlayStoreFetcher.doInBackground(InstallReceiver.java:70)
    at android.os.AsyncTask$2.call(AsyncTask.java:305)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
    at java.lang.Thread.run(Thread.java:761)

My Code:

InstallReceiver.java:

public class InstallReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent.getAction().equals(Intent.ACTION_PACKAGE_ADDED)) {
            String data = new FetchData().execute("URL").get();

            // The rest of my code...
        }
    }

    private static class FetchData extends AsyncTask<String, Integer, String> {    
        @Override
        protected String doInBackground(String... strings) {
            try {
                // This is the cause of the problem
                return Jsoup.connect(strings[0]).get().text();
            } catch (Exception e) {
                return null;
            }
        }
    }
}

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.myorg.myapp">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".Activities.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity android:name=".Activities.PlayStoreActivity"/>
        <activity android:name=".Activities.InstalledAppsActivity"/>
        <activity android:name=".Activities.PredefinedFiltersActivity"/>

        // This is linking my InstallReceiver.java
        <receiver android:name=".InstallReceiver">
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_ADDED" />
                <data android:scheme="package" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

build.gradle:

dependencies {
    compile 'org.jsoup:jsoup:1.11.2'

    // The rest of my dependencies...
}

My Attempts:

  1. I've surround the Jsoup call with a general catch (Exception e) statement, and yet the error is still being thrown.
  2. I looked this error up and found some answers like this one and this one, but none of them seem to address my problem.
  3. I moved the Jsoup call into an IntentService and started that service from my InstallReceiver, but the same error is still being thrown (from the service).
  4. Tried getting HTML using (new URL(url)).openConnection() and got the same error, but now instead of Jsoup it says because of URLConnection.
  5. Used the Thread class instead of AsyncTask, but still getting the same error.

My attempts hint that the error is not really related to Jsoup, it's related to connecting to the internet from the receiver when the app is not running!

I'm guessing that there's an import issue with this HttpTracker$Connection.nextId() that's happening when my app isn't running.

Any idea how to solve this problem?


Solution

  • This usually happens when your'e trying to read a dll/so file that does not exist.
    Since what your'e doing is pretty standard the problem is probably on android studio and not on your code.
    To solve it - simply raise the minimum sdk to 20 (or more). (The advanced network profiler crashes and that is since it's not supported under version 20).