GithubHelp home page GithubHelp logo

appspector / android-sdk Goto Github PK

View Code? Open in Web Editor NEW
41.0 4.0 9.0 12.42 MB

AppSpector is a debugging service for mobile apps

Home Page: https://appspector.com

android debug http http-proxy sqlite-android java debugging-tool debugger-visualizer networking mobile-development logging remote-logging remote introspection sqlite monitoring logs logger

android-sdk's Introduction

AppSpector

With AppSpector you can remotely debug your app running in the same room or on another continent. You can measure app performance, view database content, logs, network requests and many more in realtime. This is the instrument that you've been looking for. Don't limit yourself only to simple logs. Debugging doesn't have to be painful!

Installation

Each app you want to use with AppSpector SDK you have to register on our service through the web (https://app.appspector.com) or the desktop app. After adding the application navigate to app settings and copy API key.

Add AppSpector SDK to your project

GitHub release

Add AppSpector dependency to buildscript in your project-level build.gradle

buildscript {
  repositories {
      jcenter()
      google()
      maven { url "https://maven.appspector.com/artifactory/android-sdk" }
  }
  
  dependencies {
      classpath "com.appspector:android-sdk-plugin:1.+"
  }
}

Modify your app-level build.gradle

apply plugin: 'com.android.application'
// Put AppSpector plugin after Android plugin
apply plugin: 'com.appspector.sdk'

// Add AppSpector maven repository
repositories {
    maven { url "https://maven.appspector.com/artifactory/android-sdk" }
}

dependencies {
    implementation "com.appspector:android-sdk:1.+"
}

In case when you don't want to have AppSpector SDK in your release APK use AppSpector NO-OP artifact

dependencies {
    debugImplementation "com.appspector:android-sdk:1.+"
    releaseImplementation "com.appspector:android-sdk-noop:1.+"
}

Initialize AppSpector SDK

import android.app.Application;

import com.appspector.sdk.AppSpector;

public class AmazingApp extends Application {

   @Override
   public void onCreate() {
      super.onCreate();
      
      // We recommend to start AppSpector from Application#onCreate method
      
      // You can start all monitors
      AppSpector
            .build(this)
            .withDefaultMonitors()            
            .run("API_KEY");
            
      // Or you can select monitors that you want to use
      AppSpector
            .build(this)
            .addPerformanceMonitor()
            .addHttpMonitor()
            // If specific monitor is not added then this kind of data won't be tracked and available on the web
            .addLogMonitor()
            .addScreenshotMonitor()
            .addSQLMonitor()
            .run("API_KEY");
   }

}

Use End-To-End encryption to protect your data

AppSpector SDK collects and stores user data including logs, database content and network traffic. All of this can contain sensitive data so to protect your privacy we offer an additional module with E2EE feature. It allows you to encrypt all data AppSpector sends from or to your device and be sure only you can decrypt it. Due to security reasons encrypted sessions are only available in desktop application.

To use encryption you must select the Enable End-To-End encryption option during the registration of your app using desktop application (previously registered application can't be updated to support encryption).

After that, you need to add the android-sdk-encryption module to your dependencies declaration. So, your app-level build.gradle should contain the next lines:

apply plugin: 'com.android.application'
// Put AppSpector plugin after Android plugin
apply plugin: 'com.appspector.sdk'

// Add AppSpector maven repository
repositories {
    maven { url "https://maven.appspector.com/artifactory/android-sdk" }
}

dependencies {
    implementation "com.appspector:android-sdk:1.+"
    implementation 'com.appspector:android-sdk-encryption:1.+'
}

Finally, enable encryption by putting the enableEncryption to SDK configuration. The client Public Key you can find on the application settings screen.

AppSpector
            .build(this)
            .withDefaultMonitors() 
            .enableEncryption("CLIENT_PUBLIC_KEY")
            .run("API_KEY");

Build and Run

Build your project and see everything work! When your app is up and running you can go to https://app.appspector.com and connect to your application session.

Configure

SDK start/stop

After calling the run method the SDK starts data collection and data transferring to the web service. From that point you can see your session in the AppSpector client.

Since we recommend to keep SDK initialization in the onCreate() method of your Application, the SDK provides methods to help you control AppSpector state by calling stop() and start() methods. You are able to use these methods only after AppSpector was initialized.

The stop() tells AppSpector to disable all data collection and close current session.

AppSpector.shared().stop();

The start() starts it again using config you provided at initialization.

AppSpector.shared().start();

As the result new session will be created and all activity between stop() and start() calls will not be tracked.

To check AppSpector state you can use isStarted() method.

AppSpector.shared().isStarted();

Custom device name

You can assign a custom name to your device to easily find needed sessions in the sessions list. To do this you should add the desired name as a value for AppSpector.METADATA_KEY_DEVICE_NAME key to the metadata dictionary:

AppSpector
            .build(this)
            .withDefaultMonitors()
            .addMetadata(AppSpector.METADATA_KEY_DEVICE_NAME, "YOUR_DEVICE_NAME")
            .run("YOUR_API_KEY");

Also, the SDK allows managing the device name during application lifetime using

the setMetadataValue method to change device name

AppSpector.shared().setMetadataValue(AppSpector.METADATA_KEY_DEVICE_NAME, "NEW_DEVICE_NAME");

or the removeMetadataValue to remove your custom device name

AppSpector.shared().removeMetadataValue(AppSpector.METADATA_KEY_DEVICE_NAME);

Support SQLCipher

For browsing and running SQL queries in the SQLCipher database you need to perform a couple of additional steps. First of all, add the sqlcipher-extension module to your app/build.gradle file under the main sdk module. So, it'll look like that:

dependencies {
    implementation 'com.appspector:android-sdk:1.+'
    implementation 'com.appspector:sqlcipher-extension:1.+'
}

After that, create DatabaseConnectionFactory and pass it as an argument of the addSQLMonitor method.

Let's imagine your project contains SQLCipher database with "my_encrypted_db" name and other SQLite ones:

AppSpector
            .build(this)
            .withDefaultMonitors()
            .addSQLMonitor(new SQLiteMonitor.DatabaseConnectionFactory() {
                @NonNull
                @Override
                public DatabaseConnection createDatabaseConnection(@NonNull Database database) {
                    if ("my_encrypted_db".equals(database.name)) {
                        return new SQLCipherDatabaseConnection(database, "password");
                    }
                    return new SQLiteDatabaseConnection(database);
                }
            })
            .run("YOUR_API_KEY");

Filtering your data

Sometimes you may want to adjust or completely skip some pieces of data AppSpector gather.

Filtering HTTP requests and responses

For this aim, the HTTP monitor provides the interface HTTPFilter which can be pass to addHttpMonitor(HTTPFilter) method.

Let's say we want to skip our auth token from requests headers. Here is a sample of this filter:

public class TokenFilter implements HTTPFilter {
    @Nullable
    @Override
    public HttpRequest filter(HttpRequest request) {
        if (request.getHeaders().containsKey("YOUR-AUTH-HEADER")) {
             request.getHeaders().remove("YOUR-AUTH-HEADER");
        }
        return request;
    }

    @Nullable
    @Override
    public HttpResponse filter(HttpResponse response) {
        return response;
    }
}

Filtering SharedPreferences values and files

The SharedPreferences monitor allows specifying files you want to observe by using SharedPreferencesSourceFactory.

  1. To observe all SharedPreferences files it provides SharedPreferencesSourceFactory.all() method. By default, the monitor uses this value.
  2. To ignore some files it provides SharedPreferencesSourceFactory.excludeFiles("preferences_name") method, where "preferences_name" is a name of ignored file. You may pass as many file names as you want.
  3. To observe only specified file it provides SharedPreferencesSourceFactory.only("preferences_name") method, where "preferences_name" is a name of file for observing. This method also receives as many argumens as you want.

In additinal, the monitor allows to provide SharedPreferencesMonitor.Filter for removing or modifying some values before sending data on client.

Let's say you want to remove key_1 and modify key_2 preferences in the file preferences_name. So, your filter will look like that:

public class SimpleSharedPreferencesFilter implements SharedPreferencesMonitor.Filter {
    @NonNull
    @Override
    public Map<String, PreferenceValue> filter(@NonNull String fileName, @NonNull Map<String, PreferenceValue> values) {
        if (fileName.equals("preferences_name")) {
            values.remove("key_1");
            if (values.containsKey("key_2")) {
                values.put("key_2", PreferenceValue.stringValue("modified value"));
            }
        }
        return values;
    }
}

For applying these customizations, you need to use one of these methods: addSharedPreferenceMonitor(SharedPreferencesMonitor.Filter), addSharedPreferenceMonitor(SharedPreferencesSourceFactory), addSharedPreferenceMonitor(SharedPreferencesSourceFactory, SharedPreferencesMonitor.Filter).

Filtering Logs

To filter logs you need to implement LogMonitor.Filter and pass it to addLogMonitor(LogMonitor.Filter) method.

Let's consider an example where we want to change a log level to WARN for all messages with word token:

public class LogFilter implements LogMonitor.Filter {
  
    @Nullable
    @Override
    public LogEvent filter(LogEvent event) {
        if (event.message.contains("token")) {
             event.level = LogLevel.WARN;
        }
        return request;
    }
}

Applying filters

Let's provide the created filtes to monitors:

AppSpector
            .build(this)
            .withDefaultMonitors()
            .addHttpMonitor(new TokenFilter())
            .addSharedPreferenceMonitor(new SimpleSharedPreferencesFilter()) 
            .addLogMonitor(new LogFilter())
            .run("YOUR_API_KEY");

Getting session URL

Sometimes you may need to get URL pointing to current session from code. Say you want link crash in your crash reporter with it, write it to logs or display in your debug UI. To get this URL you have to add a session start callback:

AppSpector.shared().setSessionUrlListener(new SessionUrlListener() {
    @Override
    public void onReceived(@NonNull String sessionUrl) {
        // Save url for future use...
    }
});

Disable background data collection

By default, AppSpector SDK is active until the application is killed by Android OS, even if no activities left. It may lead to unnecessary data collection and long sessions for inactive apps. We provide API to disable data collection for a case when the app has no started activities.

AppSpector
        .build(this)
        .collectDataInBackground(false) // Set this flag to disable data collection if no activities left
        .withDefaultMonitors()
        .run("YOUR_API_KEY");

Using OkHttp interceptor instead of AppSpector Gradle Plugin

If you don't want to use AppSpector Gradle Plugin you could use an alternative way to intercept HTTP requests and responses. You can manually add AppSpectorOkHttp3Interceptor to your OkHttpClient (Or AppSpectorOkHttp2Interceptor for old version of OkHttpClient). Also, don't forget to remove AppSpector plugin from your app/build.gradle file.

new OkHttpClient.Builder()
  .addInterceptor(new AuthenticationInterceptor()) // for example, it adds auth token to you request
  .addInterceptor(new AppSpectorOkHttp3Interceptor()) // it will track your requests and responses
  .build()

Experimental support for URLConnection requests

At the current moment, the SDK provides API for manual setup in your codebase. To use it in the project, firstly, you need to add the urlconnection-extension gradle dependency:

dependencies {
    implementation 'com.appspector:android-sdk:1.+'
    implementation 'com.appspector:urlconnection-extension:1.+'
}

After that, replace the url.openConnection() calls with UrlInstrument.openConnection(url). Let's say we have the method to get google page and we want to track this request:

import java.net.HttpURLConnection;
import java.net.URL;

public void getGooglePage() {
    HttpURLConnection connection = null;
    try {
        connection = (HttpURLConnection) new URL("https://google.com").openConnection();
        if (connection.getResponseCode() == 200) {
            //Read data from connection.inputStream
        }
    } catch (IOException ex) {
        Log.d("UrlConnectionSample", "Request was failed", ex);
    } finally {
        if (connection != null) {
            connection.disconnect();
        }
    }
}

After integration of the SDK, it'll be looks like this one:

import com.appspector.sdk.urlconnection.instrumentation.UrlInstrument;
import java.net.HttpURLConnection;
import java.net.URL;

public void getGooglePage() {
    HttpURLConnection connection = null;
    try {
        connection = (HttpURLConnection) UrlInstrument.openConnection(new URL("https://google.com"));
        if (connection.getResponseCode() == 200) {
            //Read data from connection.inputStream
        }
    } catch (IOException ex) {
        Log.d("UrlConnectionSample", "Request was failed", ex);
    } finally {
        if (connection != null) {
            connection.disconnect();
        }
    }
}

And that's it! Note: Calling the disconnect method is important for us. It's a marker that the request was completed.

Logger integration with Timber

If Timber has been integrated into your project you can easily use it with AppSpector:

Timber.plant(new Timber.DebugTree() {
    @Override
    void log(int priority, String tag, @NotNull String message, Throwable t) {
        Logger.log(priority, tag, message, t)
    }
})

Features

AppSpector provides many monitors that tracks different activities inside your app:

SQLite monitor

Provides browser for sqlite databases found in your app. Allows to track all queries, shows DB scheme and data in DB. You can issue custom SQL query on any DB and see results in browser immediately.

SQLite monitor

HTTP monitor

Shows all HTTP traffic in your app. You can examine any request, see request/response headers and body. We provide XML and JSON highliting for request/responses with formatting and folding options so even huge responses are easy to look through.

Http monitor

Logs monitor

Displays all logs generated by your app.

Logs

AppSpector Logger

AppSpector Logger allows you to collect log message only into AppSpector service. It is useful when you log some internal data witch can be leaked via Logcat. AppSpector Logger has the same API with android.util.Log class.

Logger.d("MyTAG", "It won't be printed to the Logcat");

Location monitor

Most of the apps are location-aware. Testing it requires changing locations yourself. In this case, location mocking is a real time saver. Just point to the location on the map and your app will change its geodata right away.

Location

Performance monitor

Displays real-time graphs of the CPU / Memory / Network / Disk / Battery usage.

Performance

Screenshot monitor

Simply captures screenshot from the device.

Screenshots

SharedPreferences monitor

Provides browser and editor for SharedPreferences.

SharedPreferences

File System monitor

Provides access to the application internal folder. So, using this monitor you're able to download, remove or upload files, create folders and just walk through app's folders.

File System

Custom Events monitor

The monitor allows you to send any data that you want to see. The SDK provides a simple API to send your events. Here is an example:

CustomEventsSender.send(new MyCustomEvent())

In the example, the MyCustomEvent class implements the CustomEventPayload interface like here:

public class MyCustomEvent implements CustomEventPayload {
    @NonNull
    @Override
    public String getName() {
        return "Custom Event";
    }

    @NonNull
    @Override
    public String getCategory() {
        return "Application";
    }

    @NonNull
    @Override
    public Map<String, Object> getPayload() {
        final  Map<String, Object> payload = new HashMap<>();
        payload.put("sampleDate", new Date());
        payload.put("sampleBool", false);
        payload.put("sampleInt", 42);
        payload.put("sampleString", "Test");
        return payload;
    }
}

Commands Monitor

The monitor provides an opportunity to trigger your code remotely from AppSpector dashboard. The triggered code should be wrapped in AppSpector's CommandCallback and registered to SDK. The command allows you to pass params to your code and declare the result type.

Let's say you need to show the Toast with the specified text and return an int value.

Here is the declaration of your command which requires a message argument and has an Integer result.

@Command(value = "Show message", category = "Application")
public class ShowToastCommand extends BaseCommand<Integer> {
    @Argument(isRequired = true)
    public String message;
}

And here is the registration of your command and the implementation of CommandCallback.

AppSpector.shared().commands().register(ShowToastCommand.class, new CommandCallback<Integer, ShowToastCommand>() {
    @Override
    public void exec(@NonNull final ShowToastCommand command, @NonNull final Responder<Integer> responder) {
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(getContext(), command.message, Toast.LENGTH_SHORT).show();
                responder.ok(42);
            }
        });
    }
});

This command will appear under the Application category and will have Show message name on the dashboard. You can use your own categories for grouping commands on the dashboard.

Commands can be registered only after running the SDK.

Feedback

Let us know what do you think or what would you like to be improved: [email protected].

Join our slack to discuss setup process and features

android-sdk's People

Contributors

deszip avatar dimdron avatar oleksiikhorunzhyi avatar sergeyzenchenko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

android-sdk's Issues

Confuse DOC's on implementation.

Hello,

I'm new on mobile development and the explanation how to INITIALIZE APPSPECTOR SDK is not obvious to me, srry guys XD

Can someone explain me where should I put the INITIALIZE APPSPECTOR SDK code?

It seems to me that I have to create a file, but...

  • where should I put this file?
  • should I place all the code within the app level build.gradle?

Sorry for my noobness ^^

Thanks!

Documentation for dependencies isn't clear

The buildscript, dependencies and plugins don't mention what file they should go in. Most libraries tell you to put x in your root build.gradle and y in your app level build.gradle. This increased the overhead of me installing and using AppSpector.

Error during initialization

Hi, I have a problem with the library integration, I'm going to run the library for the first time but blocks my application and closes it.

2018-10-08 11:06:22.496 13270-13270/com.civico.app.beta E/AndroidRuntime: at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) 2018-10-08 11:06:22.496 13270-13270/com.civico.app.beta E/AndroidRuntime: at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.appspector.sdk.instrumentation.SQLiteInstrument.execSQL(SQLiteInstrument.java:259) at com.pushwoosh.internal.network.g.onCreate(Unknown Source:29) at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:294) at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:194) at com.pushwoosh.internal.network.g.a(Unknown Source:8) at com.pushwoosh.NetworkReceiver.onReceive(Unknown Source:33) at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$-android_app_LoadedApk$ReceiverDispatcher$Args_52166(LoadedApk.java:1317) at android.app.-$Lambda$FilBqgnXJrN9Mgyks1XHeAxzSTk.$m$0(Unknown Source:4) at android.app.-$Lambda$FilBqgnXJrN9Mgyks1XHeAxzSTk.run(Unknown Source:0) at android.os.Handler.handleCallback(Handler.java:789) at android.os.Handler.dispatchMessage(Handler.java:98) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6938) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

Release version do not generate online session

I'm maybe not understanding the README, but:

In case when you don't want to have AppSpector SDK in your release APK use AppSpector NO-OP artifact

dependencies {
    debugImplementation "com.appspector:android-sdk:1.+"
    releaseImplementation "com.appspector:android-sdk-noop:1.+"
}

My understanding is that if I do not put this in my project, AppSpector should log in release Signed Bundle / APK?

If yes, it didn't work for me. I do create a private release and download it to my phone.
I can't see my session in online tabs but if I start a debug version with another phone, it is working fine.

Any ideas?

Proguard rules

Hello, what are the recommended proguard rules for your SDK? Because it does not work out of the box, it throws lot of warnings like

Warning: com.appspector.sdk.instrumentation.OkHttp2Instrument$CallWrapper: can't find superclass or interface com.squareup.okhttp.Call
Warning: com.appspector.sdk.instrumentation.OkHttp2Instrument$CallbackWrapper: can't find superclass or interface com.squareup.okhttp.Callback
Warning: com.appspector.sdk.core.connection.socket.TLSSocketFactory: can't find referenced class com.squareup.okhttp.TlsVersion
Warning: com.appspector.sdk.core.connection.socket.TLSSocketFactory: can't find referenced class com.squareup.okhttp.TlsVersion
Warning: com.appspector.sdk.core.connection.socket.TLSSocketFactory: can't find referenced class com.squareup.okhttp.TlsVersion
Warning: com.appspector.sdk.instrumentation.OkHttp2Instrument: can't find referenced class com.squareup.okhttp.OkHttpClient
Warning: com.appspector.sdk.instrumentation.OkHttp2Instrument: can't find referenced class com.squareup.okhttp.OkHttpClient

however If I suppress this warnings with

-dontwarn com.appspector.sdk.**

it then crashes at runtime on

 java.lang.InternalError: Thread starting during runtime shutdown
        at java.lang.Thread.nativeCreate(Native Method)
        at java.lang.Thread.start(Thread.java:730)
        at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:941)
        at java.util.concurrent.ThreadPoolExecutor.processWorkerExit(ThreadPoolExecutor.java:1009)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1151)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
        at java.lang.Thread.run(Thread.java:761)

I even tried to keep all appspector classes but no change.

Anyway its a great tool but our testers are using proguarded app so its as close to production as possible.

issue with appspector 1.4.4 and kotlin 1.4.x

If I run appsepector 1.4.4 with kotlin 1.4.x, studio complains with below error. FYI) appsepctor 1.4.3 has no problem.

/Users/[USER]/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.6.0/7857e365f925cfa060f941c1357cda1f8790502c/kotlin-stdlib-common-1.6.0.jar!/META-INF/kotlin-stdlib-common.kotlin_module: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.6.0, expected version is 1.4.1.

Suddenly, I saw this error today.

AppSpector causes a crash after adding dependency on Flipper

I have appsepctor in a sample app and it works fine.

Then I added the dependencies for Flipper (no other flipper code was added yet) and I got a crash.

    implementation "com.appspector:android-sdk:1.+"
    debugImplementation 'com.facebook.flipper:flipper:0.23.4'
    debugImplementation 'com.facebook.soloader:soloader:0.5.1'
    releaseImplementation 'com.facebook.flipper:flipper-noop:0.23.4'
Crash:
2019-08-09 13:46:13.710 23253-23253/com.example.sample E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.sample, PID: 23253
    java.lang.BootstrapMethodError: Exception from call site #4 bootstrap method
        at okhttp3.internal.Util.<clinit>(Util.java:87)
        at okhttp3.internal.Util.skipLeadingAsciiWhitespace(Util.java:321)
        at okhttp3.HttpUrl$Builder.parse(HttpUrl.java:1313)
        at okhttp3.HttpUrl.get(HttpUrl.java:917)
        at okhttp3.CertificatePinner$Pin.<init>(CertificatePinner.java:271)
        at okhttp3.CertificatePinner$Builder.add(CertificatePinner.java:334)
        at com.appspector.sdk.AppSpector.<init>(AppSpector.java:4)
        at com.appspector.sdk.AppSpector.b(AppSpector.java:10)
        at com.appspector.sdk.AppSpector.a(AppSpector.java:3)
        at com.appspector.sdk.e.create(AppSpector.java:1)
        at com.appspector.sdk.Builder.run(Builder.java:3)
        at com.example.sample.MainActivity.onCreate(MainActivity.kt:41)
        at android.app.Activity.performCreate(Activity.java:7136)
        at android.app.Activity.performCreate(Activity.java:7127)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Android 12 support

Hi!

In our project we are using the latest version of AppSpector SDK (1.4.3) and after upgrading some devices to Android 12 we stopped seeing sessions in AppSpector web app.

When we can expect support for Android 12? Are there any temporary workarounds that will allow us using AppSpector?

Couldn't create outDir

Running ./gradlew buildBetaDebug on my Android app now shows this at the very end of the logs. Any idea?

Couldn't create outDir /Users/coltonidle/Android/Projects/busGoRound/app/build/intermediates/transforms/AppspectorSDKPlugin/beta/debug/43
Couldn't create outDir /Users/coltonidle/Android/Projects/busGoRound/app/build/intermediates/transforms/AppspectorSDKPlugin/beta/debug/176
Couldn't create outDir /Users/coltonidle/Android/Projects/busGoRound/app/build/intermediates/transforms/AppspectorSDKPlugin/beta/debug/94
Couldn't create outDir /Users/coltonidle/Android/Projects/busGoRound/app/build/intermediates/transforms/AppspectorSDKPlugin/beta/debug/42
Couldn't create outDir /Users/coltonidle/Android/Projects/busGoRound/app/build/intermediates/transforms/AppspectorSDKPlugin/beta/debug/106
Couldn't create outDir /Users/coltonidle/Android/Projects/busGoRound/app/build/intermediates/transforms/AppspectorSDKPlugin/beta/debug/60
Couldn't create outDir /Users/coltonidle/Android/Projects/busGoRound/app/build/intermediates/transforms/AppspectorSDKPlugin/beta/debug/181

... +200 more lines

This doesn't seem to actually break anything, but I figured I would flag it.

Session doesn't start in Google Play Console's Internal testing build

Hi! We have used Firebase for a long time to test our .apks, but now we are moving to Firebase .aab testing, which uses Play Console's Internal testing to distribute builds. I saw in one of the closed issues that you don't allow starting sessions in applications from Play Market.
Any suggestions/workarounds on this case? Our QA's are struggling since AppSpector stopped working.
Please let me know if you need any additional info

Consider adding a no-op artifact

There are a lot of libraries that can be used for debugging and they typically have a no-op artifact so you can decide to leave out the library easily where you would like to.

An example of this is leak-canary:

  debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.3'
  releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.3'

Build failed

Could you check please the following issue:

Android Studio logs:

Caused by: com.android.builder.dexing.DexArchiveBuilderException: Failed to process ...\build\intermediates\transforms\AppspectorSDKPlugin\debug\148

Caused by: com.android.tools.r8.utils.AbortException: Error: ...\build\intermediates\transforms\AppspectorSDKPlugin\debug\148\module-info.class, Illegal class file: Class module-info is missing a super type. Class file version 53.

AppSpector version is 1.1.5
AndroidStudio version is 3.4.2

Also don't work for 1.1.2 AppSpector version

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.