【初心者向け】Androidで独自SDKの作り方

2017年7月10日

Androidで自前SDKを作る機会はあまりないかもしれませんが、作り方を紹介したいと思います。サンプルはリポジトリにアップしてあります。Growth-Hack-Studio/GHS-SDK-Sample

環境&前提

  • Android Studio(v2.3.1)&Gradle(v3.3)を使用して作成します。
  • jar形式で配布するようにします。

手順

今回は下記手順で進みます。

  1. Android Studioでプロジェクト作成
  2. SDK用モジュール追加
  3. アプリから呼び出し
  4. ビルド設定追加

1. Android Studioでプロジェクト作成

Android Studioの新規プロジェクト作成のフローに沿って新規プロジェクトを作成します。

2. SDK用モジュール追加

File > New > New Module… からAndroid Libraryを追加します。

このようにモジュールが追加されます。

初期ではクラスが無いためghssamplesdk/src/main/java以下にファイルを作成しておきます。

package app.sample.ghs.tokyo.ghssamplesdk;

import android.util.Log;

public class GHSSDK {

    public static void hello() {
        Log.d("GHSSDK", "hello, World.");
    }
}

3. アプリから呼び出し

1で作成したアプリから2で作成した適当なクラスを呼んでみます。
アプリの依存関係にSDKを追加します。app/build.gradle

dependencies {
    // ...
    compile project(':ghssamplesdk') // sdkプロジェクトを追加
}

これでアプリからSDKを参照できます。起動時にSDKのhello()を呼んでみます。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        GHSSDK.hello();
    }
}

アプリをビルド&実行すると、ログにhello, World.とでると思います。
これでアプリからSDKが参照できるようになりました。

4. ビルド設定追加

4.1 jarファイル取り出し & Rename

ghssamplesdk/build.gradleに下記のコードを追加します。タスクについてはGradle勉強会を社内でやったときの資料(Gradleを使えるようになるために)を見てもらうとわかりやすいかと思います。

// 変数
def sdkVersion = '1.0.0'
def sdkName = 'GHS-Sample-SDK'
def sdkDir = 'build/sdk'

// 古いsdkファイルを削除
task clearJar(type: Delete) {
    delete fileTree(dir: sdkDir)
}

// リリース用Jarをコピーし、sdkDirに格納
task makeJar(type: Copy) {
    from('build/intermediates/bundles/default/')
    into(sdkDir)
    include('classes.jar')
    rename('classes.jar', "${sdkName}-${sdkVersion}.jar")
}
// デバッグ用Jarをコピーし、sdkDirに格納
task makeJarDebug(type: Copy) {
    from('build/intermediates/bundles/debug/')
    into(sdkDir)
    include('classes.jar')
    rename('classes.jar', "${sdkName}-${sdkVersion}-debug.jar")
}

// makeJarコマンドでclearJar, build, makeJarDebugを実行するようにする
makeJar.dependsOn(clearJar, build, makeJarDebug)

追加後に下記コマンドを実行するとjarファイルがghssamplesdk/build/sdkにできます。

$ ./gradlew -p ghssamplesdk makeJar

4.2 設定ファイル切り出し

SDKのバージョン等の設定は切り出して設定だけのファイルとしたほうが管理&見通しが良くなります。
gradleは同一モジュール内にあるgradle.propertiesを実行時に読み込んでくれるので、ghssamplesdk/gradle.propertiesファイルを作成します。
先程の変数部を移行してみましょう。

SDK_VERSION=1.0.0
SDK_NAME=GHS-Sample-SDK
SDK_DIR=build/sdk

ghssamplesdk/build.gradleは次のように変更になります。

// 古いsdkファイルを削除
task clearJar(type: Delete) {
    delete fileTree(dir: project.SDK_DIR)
}

// リリース用Jarをコピーし、sdkDirに格納
task makeJar(type: Copy) {
    from('build/intermediates/bundles/default/')
    into(project.SDK_DIR)
    include('classes.jar')
    rename('classes.jar', "$SDK_NAME-$SDK_VERSION.jar")
}
// デバッグ用Jarをコピーし、sdkDirに格納
task makeJarDebug(type: Copy) {
    from('build/intermediates/bundles/debug/')
    into(project.SDK_DIR)
    include('classes.jar')
    rename('classes.jar', "$SDK_NAME-$SDK_VERSION-debug.jar")
}

// makeJarコマンドでclearJar, build, makeJarDebugを実行するようにする
makeJar.dependsOn(clearJar, build, makeJarDebug)

再度実行すると同じ結果が得られていることが確認できると思います。

$ ./gradlew -p ghssamplesdk makeJar

Tips

幾つかSDK作ってきたのでその時のTipsを

非同期処理Tips

通信やファイルIOの処理をメインスレッドやることはユーザが操作できない時間が出てしまい、タブーなことです。SDKは他のアプリに導入してもらうのでSDK原因で動作が重くなることは避けなければいけません!
自身で実装する場合、SDK内で1つExecutorを作成しそれを使い非同期処理を行います。

public class GHSSDK {

    static ScheduledExecutorService sExecutor = Executors.newScheduledThreadPool(2);

    public static void hello() {
        Log.d("GHSSDK", "hello, World.");
    }

    public static void asyncTask() {
        sExecutor.execute(new Runnable() {
            @Override
            public void run() {
                // do io task.
            }
        });
    }
}

頻発するのが「APIからデータ取得後にXX処理を行う」というものです。多くの場合は同期処理と非同期処理が必要でコールバック関数を用意して、それようのインターフェイス作って等自前でやると非常に面倒くさいです。[Java]FutureTaskをChainぽくするこれを参考に実装すると見通しよくなるかもしれません。ご参考まで…。

以上、長くなりましたが独自でSDK作る場合は参考にしていただけたらと思います。