[AS3] Android Studio でもANE用のjarを作りたい

2016/10/2

こんにちは。きんくまです。

久しぶりにANEを作る必要がありまして。
それで、以前作ってたときよりいろいろと変わってました。
前は、エディタがeclipse版だったのですが、いまはAndroid Studioになったので、jarファイルを作るまでの手順がいろいろと変わってました。

今回のお題としては、ふだんAndroidの開発をしない人がANE用のjarファイルを取り出すところまでのメモです。
いまどき、AIR?ANE?それ誰トクなの?状態ですが、誰かの役にたつかもしれないので、、。

Android Studioをインストール

Androidの開発は、以前はeclipseだったのですが、いまはAndroid Studioになっていました。
私はいまは、AIRの開発はIntellj IDEAでやっているので、同じJetBrainsさん製ということでちょっと親近感がわきます!

ここのインストールの手順は適当にやってくださいw

新規Androidプロジェクトつくった後に、新規モジュールでAndroid Libraryを追加

新規のAndroidプロジェクトを作った後に、新規モジュールでAndroid Libraryを追加します。

File > Project Structure

左上の + ボタンからAndroid Libraryを追加します。
1番目のキャプチャはモジュールがすでに追加済みのものです。
appモジュールの下に、すでに新規のLibraryのモジュールが追加されています。

and_studio_jar1

and_studio_jar2

libs フォルダにFlashRuntimeExtensions.jarを追加

さきほど作った新規モジュールのディレクトリの中のlibsフォルダにFlashRuntimeExtensions.jarを追加します。

FlashRuntimeExtensions.jarは AIR SDKの中の以下のパスの中にあります。

libs/android/FlashRuntimeExtensions.jar

and_studio_jar3

これだけだと、さきほどのjarファイルを同期してくれなかったので、適当にプロジェクト設定のライブラリのところを選択して
三角ボタンを上げ下げしたら、読み込んでくれました。
もっと正式なやりかたがあると思うんだけど、今回は気にしないw

and_studio_jar4

Javaコードを書く

今回は、別アプリから自分のアプリを立ち上げられたときに、URLSchemeの情報を得るANEを作ったのでそれ用のコードです。
メソッドは2つで、ファイル名を得るやつと、ファイルを特定の位置にコピーするやつです。

なんでこんなの作るのかというと、Androidは別アプリから立ち上げられると、だいたい2種類のURLスキームが送られてきます。

ファイル
file://

コンテント
content://

の2種類です。他にもあるかもしれないけど、今回は必要ないので無視。

このとき、contetの方だと、ファイル名やパスがよくわかないのです。さらにいうと、Kitkat以降はパスがうまく取得できないみたいで、しょうがないのでファイルを自分がわかる位置にコピーして、コピーしたファイルをいろいろいじろうという目的です。

AndURLSchemeUtil.java

package com.kumade.ane.andurlschemeutil;

import android.util.Log;

import com.adobe.fre.FREContext;
import com.adobe.fre.FREExtension;

/**
 * Created by kinkuma on 10/1/16.
 */

public class AndURLSchemeUtil implements FREExtension {
    public static final String TAG = "AndURLSchemeUtil";

    @Override
    public FREContext createContext(String arg0) {
        return new AndURLSchemeUtilContext();
    }

    @Override
    public void dispose() {
        Log.d(TAG, "Extention disposed.");
    }

    @Override
    public void initialize() {
        Log.d(TAG, "Extension initialized");
    }
}

AndURLSchemeUtilContext.java

package com.kumade.ane.andurlschemeutil;

import android.util.Log;

import com.adobe.fre.FREContext;
import com.adobe.fre.FREFunction;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by kinkuma on 10/1/16.
 */

public class AndURLSchemeUtilContext extends FREContext {
    public static final String TAG = "AndURLSchemeUtil";

    @Override
    public void dispose() {
        Log.d(TAG, "context disposed.");
    }

    @Override
    public Map<String, FREFunction> getFunctions() {
        Map<String, FREFunction> functions = new HashMap<String, FREFunction>();

        functions.put("getFileNameFromURL", new getFileNameFromURLFunc());
        functions.put("copyFile", new CopyFileFunc());

        return functions;
    }
}

CopyFileFunc.java

package com.kumade.ane.andurlschemeutil;

import android.content.Context;
import android.net.Uri;

import com.adobe.fre.FREContext;
import com.adobe.fre.FREFunction;
import com.adobe.fre.FREObject;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * Created by kinkuma on 10/1/16.
 */

public class CopyFileFunc implements FREFunction {

    @Override
    public FREObject call(FREContext context, FREObject[] args) {
        String sourceURLStr = null;
        String destPath = null;
        try{
            sourceURLStr = args[0].getAsString();
            destPath = args[1].getAsString();
        }catch(Exception e){
            e.printStackTrace();
            return null;
        }
        if(sourceURLStr == null || destPath == null){
            return null;
        }
        boolean copyResult = copyFile(context.getActivity(), sourceURLStr, destPath);
        FREObject freObj = null;
        try{
            freObj = FREObject.newObject(copyResult);
        }catch(Exception e){
            e.printStackTrace();
        }
        return freObj;
    }

    public boolean copyFile(Context context, String sourceURLStr, String destPath){
        Uri uri = Uri.parse(sourceURLStr);
        if(uri == null){
            return false;
        }
        InputStream inputStream = null;
        OutputStream outStream = null;
        boolean success = true;
        try{
            inputStream = context.getContentResolver().openInputStream(uri);
            outStream = new FileOutputStream(destPath);
            byte[] buffer = new byte[4 * 1024];
            int read;
            while((read = inputStream.read(buffer)) != -1){
                outStream.write(buffer, 0, read);
            }
            outStream.flush();
        }catch(Exception e){
            e.printStackTrace();
            success = false;
        } finally {
            if(outStream != null){
                try{
                    outStream.close();
                }catch(Exception e){
                    e.printStackTrace();
                    success = false;
                }
            }
            if(inputStream != null){
                try{
                    inputStream.close();
                }catch(Exception e){
                    e.printStackTrace();
                    success = false;
                }
            }
        }
        return success;
    }
}

getFileNameFromURLFunc.java

package com.kumade.ane.andurlschemeutil;

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;
import android.util.Log;

import com.adobe.fre.FREContext;
import com.adobe.fre.FREFunction;
import com.adobe.fre.FREObject;

/**
 * Created by kinkuma on 10/1/16.
 */

public class getFileNameFromURLFunc implements FREFunction {
    public static final String TAG = "AndURLSchemeUtil";

    @Override
    public FREObject call(FREContext context, FREObject[] args) {
        String url = null;
        try{
            url = args[0].getAsString();
        }catch(Exception e){
            e.printStackTrace();
            return null;
        }
        if(url == null){
            return null;
        }
        Uri uri = Uri.parse(url);
        String fileName = getFileNameFromURL(context.getActivity(), uri);
        if(fileName == null){
            return null;
        }

        FREObject freObj = null;
        try{
            freObj = FREObject.newObject(fileName);
        }catch(Exception e){
            e.printStackTrace();
        }
        return freObj;
    }

    public String getFileNameFromURL(Context context, Uri uri){
        String fileName = null;
        if(uri.getScheme().equalsIgnoreCase("content")){
            String prop = MediaStore.MediaColumns.DISPLAY_NAME;
            String[] proj = { prop };

            Cursor cursor = null;
            try {
                cursor = context.getContentResolver().query(
                        uri,
                        proj,
                        null,
                        null,
                        null);
                cursor.moveToFirst();
                int columnIndex = cursor.getColumnIndexOrThrow(prop);
                fileName = cursor.getString(columnIndex);
            }catch(Exception exception){
                Log.d(TAG, exception.getMessage());
            }finally {
                if(cursor != null){
                    cursor.close();
                    cursor = null;
                }
            }

        }else{
            fileName = uri.getLastPathSegment();
        }
        return fileName;
    }
}

サンプルなんで、あんましコードは気にしないでください、、。

Build Variantsをreleaseに

Build Variantsっていうウインドウというのか設定タブがあるので、それを開いてLibraryモジュールをreleaseにしておきます。

and_studio_jar5

いよいよビルドじゃー(jarだけに)

ビルドします。

ここ最初よくわかってなかったんですが、nodeのgulpみたいな感じで、gradleっていうタスクランナーっていうかビルドツールみたいのが入ってました。

それで、Libaryモジュールのbuildの中から

1. clean
2. build

を選択します。

and_studio_jar6

jarはどこ?

ビルドされたjarファイルはどこなの?ってことなんですが、以下のパスにあります。

2019/02/22修正 Android Studio 3.2.1

プロジェクトフォルダ/モジュール名/build/intermediates/intermediate-jars/release/classes.jar

以前のパス

プロジェクトフォルダ/モジュール名/build/intermediates/bundles/release/classes.jar

まとめ

おつかれさまでした!これでjarファイルができたので、あとはいろいろやってane作ってください。
ちなみにいうと、Androidは意外と大丈夫だったりするんですが、iOS用のANEを作ろうとしたら、Xcode8だとDevicesの中のlogがログをはかなくなってしまい、すんごくデバッグしづらかったです。
なんかクラッシュレポートと、メモリの状態しか見せてくれなくなってた、、、。これでどうやってデバッグしろと、、。

というわけでメモでしたー。

LINEで送る
Pocket

自作iPhoneアプリ 好評発売中!
フォルメモ - シンプルなフォルダつきメモ帳
ジッピー電卓 - 消費税や割引もサクサク計算!

LINEスタンプ作りました!
毎日使える。とぼけたウサギ。LINEスタンプ販売中! 毎日使える。とぼけたウサギ

ページトップへ戻る