/Yakhont

The high-level Android components library for data loading, location, lifecycle callbacks and more.

Primary LanguageJavaApache License 2.0Apache-2.0

Яхонт делает невозможное Yakhont - break limits now

Yakhont: high-level Android components for data loading, location, lifecycle callbacks and many more

Yakhont is an Android high-level library offering developer-defined callbacks, loader wrappers and adapters, fully automatic cache, location-awareness, dynamic permissions handling, lifecycle debug classes, advanced logging and many more helpful developer-oriented issues.

There is also the Yakhont Weaver - a small but powerful utility which manipulates the compiled Java bytecode and can be used separately, without the Yakhont library (you will find more info below).

Now you can load data in just one line of code (please refer to the simplified demo for the working example):

new Retrofit2CoreLoadBuilder<>(/* your parameters here */).create().startLoading();

And take location in just a couple of lines (the working example is in the simplified demo too):

@CallbacksInherited(LocationCallbacks.class)
public class YourActivity extends Activity implements LocationListener {
    @Override
    public void onLocationChanged(Location location, Date date) {
        // your code here
    }
}

Yakhont extends the Application.ActivityLifecycleCallbacks approach to support your own callbacks creation, that allows to customize handling of almost every lifecycle state of your Activities and Fragments - and even without changing their sources (especially useful for libraries developers).

The powerful loader wrappers and adapters, which (in simplest, but very typical case) allows loading and binding data in nearly one line of code, are abstracting you away from things like loaders management, caching, progress dialogs (fully customizable), errors handling and low-level threading; don't miss the swipe-to-refresh and both RxJava and RxJava 2 support too.

In short, the data loaders and adapters features are:

  • automatic (but fully customizable) data binding
  • automatic and absolutely transparent cache
  • fully asynchronous
  • forced timeouts
  • both RxJava and RxJava 2 support
  • both Retrofit and Retrofit 2 support
  • swipe-to-refresh
  • device orientation changing support
  • fully customizable GUI progress (via Dagger 2)
  • and last but not least: if Retrofit does not meet your requirements, you can add support for any other library

In addition, there are the location features which includes:

So, the features the Yakhont provides are:

  • developer-defined callbacks to customize lifecycle of Activities and Fragments - and even without changing their sources
  • powerful (but very easy in use) data loaders and adapters
  • automatic (but fully customizable) data binding
  • self-configurable transparent cache which adjusts database structure 'on the fly'
  • out-of-the-box location awareness: just annotate your Activity and you're done
  • dynamic permissions handling, powered by user-defined callbacks
  • debug classes with strict mode and lifecycle logging - for all kinds of Activities and Fragments (can be enabled even for 3rd-party components via simple, but effective Yakhont preprocessor)
  • advanced logging with e-mail support (auto-disabled in release builds) and more.

All kinds of Activities and Fragments (Applications too) are supported: it's not necessary to derive them from any predefined ones (with one exception - you will need it for lifecycle debug).

The Yakhont AAR is about 320 KB (except the full version, which is about 530 KB).

Yakhont supports Android 2.3 (API level 9) and above (core version requires Android 3.0 (API level 11) as a minimum).

Note: Location API requires Android 4.0 (API level 14); please visit Android Developers Blog for more information.

Demo and Releases

Releases are available here, demo applications can be downloaded from the latest release ( demo and simplified demo ).

Versions

  • core: works with native Android Fragments
  • support: works with support Fragments (android.support.v4.app.Fragment etc.)
  • full: core + support + debug classes for most of Activities and Fragments

Usage

Add the following to your build.gradle (you can use build.gradle files from demo and simplified demo as working examples).

  1. Update the buildscript block:
buildscript {
    repositories {
        // your code here, usually just 'jcenter()'
    }
    dependencies {
        classpath 'com.github.akhasoft:yakhont-weaver:0.9.19'
    }
}

Note: the Yakhont components (com.github.akhasoft:yakhont...) are available from both jcenter and mavenCentral.

  1. Update the android block:
android {
    // your code here
    
    // fixed DuplicateFileException
    packagingOptions {
        exclude 'META-INF/rxjava.properties'
    }
}
  1. Update the dependencies block:
dependencies {
    implementation    'com.github.akhasoft:yakhont:0.9.19'
    // or
    // implementation 'com.github.akhasoft:yakhont-full:0.9.19'
    // or
    // implementation 'com.github.akhasoft:yakhont-support:0.9.19'
}

And if you're about to customize Yakhont using build-in Dagger 2, something like following lines are required:

dependencies {
    implementation      'com.google.dagger:dagger:2.10'
    annotationProcessor 'com.google.dagger:dagger-compiler:2.10'
    compileOnly         'javax.annotation:jsr250-api:1.0'
}
  1. The code below forced to build release version only. If you want to build the debug version, please replace 'debug' with 'release':
android.variantFilter { variant ->
    if (variant.buildType.name == 'debug') {
        variant.setIgnore(true)
    }
}

Note: for the moment Yakhont Weaver can't handle both debug and release at the same time.

  1. The code which runs Yakhont Weaver:
String[] weaverConfigFiles = null
boolean weaverDebug = false, weaverAddConfig = true

android.registerTransform(new akha.yakhont.weaver.WeaverTransform(weaverDebug, android.defaultConfig.applicationId,
    android.bootClasspath.join(File.pathSeparator), weaverConfigFiles, weaverAddConfig))

Or (to avoid using the Transform API) you can try the following:

String[] weaverConfigFiles = null
boolean weaverDebug = false, weaverAddConfig = true

android.applicationVariants.all { variant ->
    JavaCompile javaCompile = variant.javaCompile
    javaCompile.doLast {
        new akha.yakhont.weaver.Weaver().run(weaverDebug, android.defaultConfig.applicationId,
            javaCompile.destinationDir.toString(), javaCompile.classpath.asPath,
            android.bootClasspath.join(File.pathSeparator), weaverConfigFiles, weaverAddConfig)
    }
}

Here the Yakhont Weaver manipulates the Java bytecode just compiled, which makes possible to alternate classes implementation (e.g. add / modify callbacks in Activities and Fragments) without changing their source code.

Note: the Google "Jack and Jill" technology is not supporting bytecode manipulation (at least, for the moment).

  1. Finally, don't forget to add to your AndroidManifest.xml something like code snippet below:
<application ...>

    ...
    
    <provider
        android:authorities="your_package_name.provider"
        android:name="akha.yakhont.BaseCacheProvider"
        android:enabled="true"
        android:exported="false" />
        
</application>        

Note: "your_package_name" is a placeholder, you should provide real name, e.g. "com.mypackage".

Weaver: usage and configuration

The Yakhont Weaver is a small but powerful utility which manipulates the compiled Java bytecode (e.g. in Yakhont demo applications it customizes "Activity.onStart()" and other callbacks).

By default the Yakhont Weaver uses configuration from it's JAR, but you can provide your own configuration file(s) as a parameter (see above). The "weaverAddConfig = true" means adding your configuration (if not null) to the default one; "weaverAddConfig = false" forces the Yakhont Weaver to replace default configuration with yours (even if null).

The Yakhont Weaver is a standalone utility which means it can be used in any application even without Yakhont library - just specify "weaverAddConfig = false" and provide your own configuration file.

Proguard

ProGuard directives are included in the Yakhont libraries. The Android Plugin for Gradle automatically appends these directives to your ProGuard configuration.

Anyway, it's strongly advised to keep your BuildConfig, model and Retrofit API (also "android.support.v4" classes) as follows (it's just an example from the Yakhont Demo, so please update it according to your application's packages names):

-keep class android.support.v4.** { *; }

-keep class akha.yakhont.demo.BuildConfig { *; }
-keep class akha.yakhont.demo.model.** { *; }
-keep interface akha.yakhont.demo.retrofit.** { *; }

Also, please update the buildTypes block with ProGuard directives for 3rd-party libraries (you can find them here):

buildTypes {
    release {
        minifyEnabled true

        proguardFile 'proguard-google-play-services.pro'
        proguardFile 'proguard-gson.pro'
        proguardFile 'proguard-rx-java.pro'
        proguardFile 'proguard-square-okhttp.pro'
        proguardFile 'proguard-square-okhttp3.pro'
        proguardFile 'proguard-square-okio.pro'
        proguardFile 'proguard-square-picasso.pro'
        proguardFile 'proguard-square-retrofit.pro'
        proguardFile 'proguard-square-retrofit2.pro'
        proguardFile 'proguard-support-v7-appcompat.pro'

        // your code here
    }
}

Build

To check out and build the Yakhont source, issue the following commands:

$ git clone https://github.com/akhasoft/Yakhont.git
$ cd Yakhont
$ ./gradlew --configure-on-demand yakhont-weaver:clean yakhont-weaver:build
$ ./gradlew --configure-on-demand yakhont:clean yakhont:build
$ ./gradlew --configure-on-demand yakhont-demo:clean yakhont-demo:build
$ ./gradlew --configure-on-demand yakhont-demo-simple:clean yakhont-demo-simple:build

Note: you may need to update your Android SDK before building.

To avoid some lint issues (in Android Studio, when running Analyze -> Inspect Code):

  • add yakhont.link,yakhont.see to File -> Settings -> Editor -> Inspections -> Java -> Javadoc issues -> Declaration has Javadoc problems -> Additional Javadoc Tags
  • add yakhont.dic to File -> Settings -> Editor -> Spelling -> Dictionaries

Communication

Information and Documentation

Known Issues

If during project building you got something like Exception below, kill the Gradle daemon (or just restart your PC).

Execution failed for task ':app:transformClassesWithWeaverTransformForDebug'.
> com.myproject.MyActivity class is frozen

Bugs and Feedback

For bugs, questions and discussions please use the Github Issues.

License

Copyright (C) 2015-2017 akha, a.k.a. Alexander Kharitonov

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.