‘Android’ カテゴリーのアーカイブ

shun

Android プロジェクトを Linux CUI 環境でビルドする

ちょっと分かり辛いタイトルですが、この記事では Android プロジェクトを Linux CUI 環境でビルドします。

前提

Vagrant (VirtualBox) 上で Arch Linux を使用して試していますが、Ubuntu や CentOS でも手順に大きな差は無いはずです。但しメモリを割と食うので 2GB 程度割いておいたほうがいいかもしれません。

$ vagrant init terrywang/archlinux
# Vagrantfile

config.vm.provider "virtualbox" do |vb|
# Customize the amount of memory on the VM:
vb.memory = "2048"
end
$ vagrant up && vagrant ssh
ビルド対象は support library や Play Services が使用されている以下のプロジェクトを試します。
googlesamples/android-play-location: BasicLocationSample

$ git clone git@github.com:googlesamples/android-play-location.git

JDK が入っていない場合は入れておきます。

# Arch Linux

# https://aur.archlinux.org/packages/jdk/
$ curl -LO https://aur.archlinux.org/cgit/aur.git/snapshot/jdk.tar.gz \
&& tar -zxf jdk.tar.gz \
&& cd jdk
# PKGBUILD、.install を確認する
$ makepkg -sri
SDK のインストールLinux 版の SDK アーカイブを確認し、ダウンロードします。ここは色々やっていると容量が大きくなっていって仮想マシンの場合はディスクを食い潰しやすいので、/vagrant 配下に置いてホストマシンに容量を委ねたほうがいいかもしれません。

$ cd /vagrant
# 執筆時点の最新
$ curl -LO http://dl.google.com/android/android-sdk_r24.3.4-linux.tgz
$ tar -zxf android-sdk_r24.3.4-linux.tgz
# 環境変数を設定
$ export ANDROID_HOME=/vagrant/android-sdk-linux
次に SDK 内で必要な項目をダウンロードします。platform、build-tools、また必要に応じて support library、Play Services を使用する場合はそれぞれ extra-android-m2repository、extra-google-m2repository を取得します。

$ cd $ANDROID_HOME

# 使用する platform、build-tools の名前を確認
$ ./tools/android list sdk --all
# GUI の無い環境の場合、--no-ui が無いとエラー
# google-m2repository は --all が無いと入らないので注意
$ ./tools/android update sdk --no-ui --all --filter android-23,build-tools-23.0.1,extra-android-m2repository,extra-google-m2repository
aapt が見つからない問題リソース xml ファイルを処理する aapt が 32bit アプリケーションなので 64bit OS ではビルドが通らない場合があります。

java.io.IOException: Cannot run program "/vagrant/android-sdk-linux/build-tools/23.0.2/aapt": error=2, No such file or directory
この為 32bit 版のライブラリを入れておきます。

# Arch Linux

# 以下を参考に Multilib を有効にする
# https://wiki.archlinux.org/index.php/Multilib

$ sudo pacman -S lib32-glibc lib32-zlib lib32-gcc-libs
Ubuntu はこの辺りが参考になるようです。
Android Studioでaaptが見つからないエラーを解決する方法 – Qiita

Let’s ビルド

ここまでくるとあとはビルドするのみです。やりましたね。

$ cd android-play-location/BasicLocationSample/
# release ビルドを行う場合は build.config で署名情報を設定する
$ ./gradlew assembledebug
# 以下のディレクトリにバイナリが出力される
$ ls app/build/outputs/apk/
app-debug.apk app-debug-unaligned.apk
番外上記の SDK ダウンロードの面倒を見てくれる gradle plugin も存在するようです。
Android – Gradle SDKManagerPluginによるSDKパッケージの依存関係解決 – Qiita

が、執筆時点では以下の issue の通りうまく動作していない面もあり、私もうまく動かすことが出来ませんでした。
Android build tools version 23.0.2 not being downloaded. · Issue #101 · JakeWharton/sdk-manager-plugin

総括

Android の環境が無いけどちょっと他人のプロダクトを試したい場合や CI サーバーでビルドを行いたい場合に便利だと思います。次回があれば Docker コンテナに押し込んでみたりします。

参考記事

android update sdkのfilterで指定できる項目名の確認方法 | memorandum
CentOS6.x 64bit のCUI環境にAndroid環境を構築する – Qiita


shun

cordova でプラットフォーム固有の orientation を指定する

最近ハイブリッドアプリを検討する機会があり、cordova 由来のプロジェクト、PhoneGap や ionic 等を触っています。

さて、これらのアプリも基本的には Web の技術で実装するとはいえプラットフォームとの協調を設定する部分はあり、それらが記載されているのがプロジェクトルートにある config.xml です。

よく設定が必要となる項目に画面回転があると思います。アプリの要件で縦固定となることは少なくありません。ゲームであれば横固定となることもあるでしょう。config.xml では以下の項目を指定します。


この orientation にはプラットフォーム固有の値を持たせることが出来、Android であれば一例として sensorLandscape という値があります。sensorLandscape は横固定だが上下はセンサーに従うという設定です。
これをドキュメントに記載されているコードを参考に追記すると、以下のようになります。


これで画面横向き、Android においては sensorLandscape が適用され…るかと思いきや、どうもそうでは無いようです。
少なくとも今試している cordova (v5.4.1) では通常の preference があるとそちらが優先されるようなので、プラットフォーム固有のコードを適用させたい場合は共通の設定は削除する必要があります。


上記でビルドが通り、orientation が適用されます。他プラットフォームでもビルドは可能で、その場合プラットフォーム指定が無ければ default 指定が適用されるようです。

該当箇所っぽいコードを見るとプラットフォーム固有の指定がある場合はそちらを優先させてくれるような実装に見てとれます。恐らく意図しない挙動だとは思うのですが、軽い気持ちで issue でも投げに行くか〜と覗きに行くと JIRA でキッチリやっている様子で思わず身が竦んでしまいました。いい感じに直ってくれるといいんですが…。


shun

Kotlin の便利な機能 3 選

主に Android の界隈で最近にわかに取り上げられている Kotlin ですが、しばらく使ってみて便利だと感じている機能を 3 つ紹介します。

ラムダ式(SAM 変換)

私が Kotlin を試すきっかけになった機能です。Kotlin にはラムダ式があり、イベントリスナーのような Java でメソッドをひとつ持つインターフェース(Single Abstract Method と表現したりする)を簡潔に記載することが出来ます。

textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context,
textView.getText(),
Toast.LENGTH_SHORT).show();
}
});

こういうのが

textView.setOnClickListener { view ->
Toast.makeText(this,
textView.text,
Toast.LENGTH_SHORT).show()
}

こういう感じでシンプルに書けます。こちらの記事など分かり易くて参考になりました。

高階関数、リスト処理

Kotlin 使い初めの頃は Java の感覚でリスト処理を拡張 for 文でやっていましたが、Kotlin は高階関数をサポートしており、標準ライブラリにはリスト処理の関数もあります。ラムダ式が使える時点で気付くべきだった…。

arrayListOf(1, 2, 3).map { i -> i * 2 }

arrayListOf(1, 2, 3).map { it * 2 }

fun twice(i: Int): Int { return i * 2}
arrayListOf(1, 2, 3).map { ::twice }

// いずれも [2, 4, 6] の ArrayList を返す

ラムダ式の引数が 1 つの場合は、2 つ目の例のように暗黙に it という名前で引数を定義してくれます。
また 3 つ目の例のように関数参照を渡すことも出来ます。

関数脳が弱いので高階関数はまだまだ使い熟せてなく、ひとまずリスト処理からでも初めて勉強していく所存です。

6.2 リスト – プログラミング言語Kotlin 解説
Higher-Order Functions and Lambdas

データクラス

Kotlin にはデータクラスを簡単に定義出来る data 修飾子があります。lombok の @data アノテーションに近い感覚ですね。

data class Data(
var nickname: String,
val status: String = "ok",
val code: String,
)

val data1 = Data("foo", "ok", "code1")
val data2 = Data(nickname = "bar", code = "code2")

クラス本体の記述は省略可能なのでこれだけです。データクラスには equals()/hashCode()/toString()/copy() が自動的に定義されます。
データクラスの機能では無いですが、Kotlin はデフォルト引数や名前付き引数もサポートしているので初期化時のパラメータも省略出来ます。

所感

Ruby のような言語だと高階関数やラムダ(ブロック)はよくある機能ですが、これを Java が必要なシチュエーションでも使っていけるのはかなりありがたいです。Kotlin は Java との親和性を意識している為、既存の Java ライブラリのような資産を苦無く使える場合が多いのも強みですね。

他にも Java コードで書かれたクラスの getter/setter をプロパティよろしく扱うことが出来たり、どんどん使い易くなっています。割と Android 目線に寄った内容になってしまいましたが、もっと便利な機能はたくさんあるはずなので是非リファレンスも見てみて下さい。フル PDF やオンライン実行環境も置いてあります。
1.0 のリリースも近付いてきているようでこれからも目が離せません。


この記事は業務時間のうち 20% の捗らない時間を利用して書かれました。進捗ダメです…。

uchida

Android-ProgressDialogFragmentというライブラリを作りました。

1

1.Android-ProgressDialogFragmentというライブラリを作りました。
https://github.com/YuichiUchida/Android-ProgressDialogFragment
 ロード中はこういう感じになります。

2

2.今まではこういう感じに作っていました。

ListFragmentなどがこういう実装になっていますね。

3

この方式は下の画像のように2つの画面を重ね
ロード中にはコンテンツ部分を消し、プログレス画面を表示し、
ロードが終るとコンテンツを表示し、プログレス画面を消すという方式になっています。

長所としては、できあがった奇麗な画面だけを表示できることですが
たくさんの画面に使うと動作が重く感じるようになってきます。

このライブラリは、やり方はほとんど同じですが
コンテンツ部分を常に表示し、プログレス画面だけを制御します。

3.使い方
Gradleに下記のように追記します。

support-v4ライブラリを使う場合

dependencies {
compile 'me.yuichi0301:pdfragment:1.1.+'
}

ライブラリを使用しない場合

dependencies {
compile 'me.yuichi0301:pdfragment-native:1.1.+'
}

あとはProgressDialogFragment継承して使用します。

public class SampleFragment extends ProgressDialogFragment {
// your code of fragment
}

ActionBarSherlockを使う場合


dependencies {
    compile 'com.android.support:support-v4:21.0.3'
    compile('me.yuichi0301:sherlockpdfragment:1.1.+') {
        exclude module: 'support-v4'
    }
}

public class SampleFragment extends SherlockProgressDialogFragment {
    // your code of fragment
}
uchida

GradleでAndroid部品を社内共有しよう!

1.はじめに
  Androidの開発をやっていると、前のプロジェクトで使った部品を次のプロジェクトでも
  使いたいなんてことがでてくると思います。しかし、公開されているリポジトリに
  登録できるような内容の部品じゃないということはよくあると思います。
  ということで、社内のリポジトリにGradleでAndroid部品を共有する内容を書いていきます。

2.手順
  ①gitlabにリポジトリを作成(社内ではgitlabを使っているため)
  ②ライブラリプロジェクトを作成し、AARをリポジトリに登録
  ③②のライブラリを使うプロジェクトの作成

1

3.gitlabにリポジトリを作成
  テスト的にこういう画像のカスタムビューを持つライブラリにします。
  ということでプロジェクト名は「Android-BaseLine」にしました。

4.BaseLineライブラリを作成します。
  EclipseだとAARが使えないためAndroid Studioを使用します。

5.BaseLineViewはこんな感じ

2

package com.lancard.baseline;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

public class BaseLineView extends View {

public BaseLineView(Context context, AttributeSet attrs) {
super(context, attrs);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

Paint paint = new Paint();
paint.setColor(Color.rgb(0, 49, 236));
//paint.setStrokeWidth(5);

int height = getHeight();
int width = getWidth();

int y = 0;
while(y6.AAR作成用にbuild.gradleを書きます。
  ここのbuild.gradleになります。

元のソース

apply plugin: 'com.android.application'

android {
compileSdkVersion 21
buildToolsVersion "21.1.1"

defaultConfig {
applicationId "com.lancard.baseline"
minSdkVersion 18
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}

次のように書き換えます。

apply plugin: 'android-library'
apply plugin: 'maven-publish'

android {
compileSdkVersion 21
buildToolsVersion "21.1.1"

defaultConfig {
applicationId "com.lancard.baseline"
minSdkVersion 18
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}

android.libraryVariants
publishing {
publications {
maven(MavenPublication) {
groupId 'com.lancard.lib'
artifactId 'baseline-aar'
version '1.0'
artifact source: file("${project.buildDir}/outputs/aar/${project.name}-release.aar")
}
}
repositories {
maven {
url "file:${projectDir}/maven-repo"

}
}
}

  <やっていること>
  ①apply plugin: 'com.android.application'→apply plugin: 'android-library'で
   アプリケーションプロジェクトからライブラリプロジェクトに
  ②apply plugin: 'maven-publish'を追加しMaven Publishプラグインを使えるようにする。
  ③ publishingを追加し、公開するファイルの設定をします。

(ちなみにURLはリポジトリ管理ツールで運用されていれば
    直接転送できgit pushする必要はありません。)

3

7.Gradleのタスクを実行します。
  Maven Publishプラグインを使用すると、「maven(MavenPublication) 」の名前から
  publishMavenPublicationToMavenRepositoryというタスクができるので実行します。

4

以下のようにmaven-repoというディレクトリができますので全て
  3.で作成したgitリポジトリにpushします。

5

このようになったでしょうか。

8.BaseLineViewを使うプロジェクトを作成し、build.gradleを以下のように追記し、buildタスクを実行します。

apply plugin: 'com.android.application'

android {
compileSdkVersion 21
buildToolsVersion "21.1.1"

defaultConfig {
applicationId "com.lancard.hoge"
minSdkVersion 18
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
buildTypes {
release {
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
}
}

repositories {
maven {
url "https://{社内gitlab}/{username}/android-baseline/raw/master/maven-repo"
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.lancard.lib:baseline-aar:1.0'
}

lintはとりあえず、オフにしています。

9.以下のように「com.lancard.baseline.BaseLineView」を使用するxmlを書いて実行できれば成功です。




10.バージョンがあがっていくとリポジトリはこのようになります。

6

11.SSLクライアント認証している場合
  社内のリポジトリがSSLクライアント認証している場合が多いと思います。
  SSLクライアント認証している場合は、gradleラッパーのJVMオプションで
  証明書のパスを設定する必要があります。
  プロジェクト配下にあるgradlewのDEFAULT_JVM_OPTSを以下のように書き換えます。

7

DEFAULT_JVM_OPTS=" \
-Djavax.net.ssl.keyStore=証明書のパス \
-Djavax.net.ssl.keyStoreType=pkcs12 \
-Djavax.net.ssl.keyStorePassword=証明書のパスワード \
"

  あとはgradleコマンドではなくgradlewを実行するようにします。


./gradlew build
yoshida

長崎国体・大会アプリがリリースされました!

長崎がんばらんば国体・長崎がんばらんば大会実行委員会様提供、弊社設計・開発による長崎国体アプリがリリースされました!
競技の日程や組合せ、会場付近の施設など、観戦をトータルにサポートするアプリになっております。
5月24・25日はリハーサル大会も開催されますので、是非ダウンロードしてください!

uchida

Android Bootstrapを試してみた。

Android Bootstrapを試してみたので、忘れないように手順をメモとして残しておきたいと思います。

(1)
  環境変数は以下のようにしました。
    export JAVA_HOME=/Library/Java/Home
    export ANDROID_SDK=$ANDROID_HOME
    export ANDROID_TOOLS=$ANDROID_SDK/tools

export PATH=${PATH}:${ANDROID_TOOLS}
    export PATH=${PATH}:${ANDROID_HOME}/platform-tools

(2)
  下記のサイトからandroid-bootstrapをダウンロードします。
  http://www.androidbootstrap.com/

アプリ名とパッケージ名を以下のように入れて「Generate Your App」ボタンを押します。

(3)
  (2)でダウンロードした、android-bootstrapのディレクトリで
  「mvn clean package」コマンドを実行します。
  mvnコマンドがない場合は、「brew install maven」

(4)
  Android Studioを起動します。
  もっていない場合は、以下のサイトからダウンロードしてください。
  http://developer.android.com/sdk/installing/studio.html

(5)
  Open Projectを選択します。

(6)
  android-bootstrapのpom.xmlを選択します。

(7)
  SDK Managerを起動します。

(8)
  APIレベル14、16をダウンロード・インストールします。

(9)
  maven projectで「Reimport All Maven Projects」ボタンを押します。

(10)
  FileメニューのProject Structureを選択します。

(11)
  Projectを選択肢、Project SDKでAndroidを選択します。

(12)
  Modulesを選択し、「~apklib-com.viewpagerindicator_library_2.4.1」を選択します。
  下部の「+」ボタンを押して、Jars or directoriesを選択します。

(13)
  「com.viewpagerindicator_library_2.4.1」の中にあるandroid-support-v4.jarを選択します。

(14)
  CMD+F9でrebuildingします。

(15)
  RunのEdit Congifrationsを選択します。

(16)
  「+」ボタンを押してAndroid Applicationを選択します。

(17)
  Nameに「BootstrapTest USB」と入力します。
  Moduleでcom-lancard-testを選択します。
  Target DeviceでUSB deviceを選択します。

(18)
  com.lancard.test.ui.view.CapitalizedTextViewの下記の行が、通らなかったのでひとまずコメントアウトしました。

//setTypeface( Typeface.createFromAsset(context.getAssets(), “fonts/Roboto-Regular.ttf”) );

(19)
  携帯とPCをつなぎ、メニューのRunからRun ‘BootstrapTest USB’を選択します。

(20)
  下記の内容を入力してテストできます。
  Email Address:demo@androidbootstrap.com
  Password:android

こういう感じのものがAndroid2.3などでも動くというのは嬉しいですね。

uchida

Androidアプリのメモリリークを調査する

Androidでメモリリークを調査することがあったので手順を記述します。

1.Eclipseをダウンロードします。
    そこから!?と思うかもしれませんが一応書いておきます。

http://www.eclipse.org/downloads/

ここからEclipse Classic 4.2.1をダウンロードします。

(※http://developer.android.com/sdk/index.htmlここから、
    EclipseとSDKが一括のものがダウンロード出来ますが
    プラグインが上手く入らなかったのでこれは使いませんでした。)

2.ADTをインストールします。
    1)Help→Install New Software
    2)addボタンを押して、以下のように設定します。
    3)適当に必要なものをインストールします。

3.BIRTプラグインをインストールします。
    1)Help→Install New Software
    2)Work withで「Juno – http://download.eclipse.org/releases/juno」を選択します。
    3)BIRTEnginをチェックします。
    4)インストールします。

4.Memory Analyzerプラグインをインストールします。
    1)Help→Install New Software
    2)Work withで「Juno – http://download.eclipse.org/releases/juno」を選択します。
    3)Memory Analyzerをチェックします。(Generale Purpose Toolsの中にあります。)
    4)インストールします。

5.DDMSのPerspectiveを開きます。
    1)対象のプロセスを選択して、「Dump HPROF file」を押します。
    2)表示されたダイアログで「Leak Suspects Report」をチェックし、「Finish」を押します。

メモリリークの詳細が表示されます。

uchida

Androidで影を描いてみる。

ずっと前からブログのネタとして暖めていた、Androidで影を描く方法を書きたいと思います。

先に書いたソースを載せます。

import android.content.Context;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.View;

public class ShadowView extends View {

private Paint white = null;
private Paint black = null;
private Paint shadow = null;

private RectF rect = null;
private RectF shadowRect = null;

public ShadowView(Context context) {
super(context);

white = new Paint();
white.setColor(Color.WHITE);
white.setAntiAlias(true);

black = new Paint();
black.setStyle(Paint.Style.STROKE);
black.setAntiAlias(true);

shadow = new Paint();
shadow.setStyle(Paint.Style.FILL);
shadow.setColor(Color.argb(112, 0, 0, 0));
BlurMaskFilter blur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);
shadow.setMaskFilter(blur);

rect = new RectF(50f,100f,250f,200f);

float diff = 30f;
shadowRect = new RectF(50f + diff,100f + diff,250f + diff,200f + diff);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

//背景を描画
drawBackground(canvas);

//角丸の矩形の影
canvas.drawRoundRect(shadowRect, 50, 50, shadow);

//角丸の矩形の背景(白)
canvas.drawRoundRect(rect, 50, 50, white);

//角丸の矩形の枠線(黒)
canvas.drawRoundRect(rect, 50, 50, black);
}

/**
* 背景を描画
* @param canvas
*/
private void drawBackground(Canvas canvas){
Paint paint = new Paint();
paint.setColor(Color.rgb(214, 233, 255));

int height = getHeight();
int width = getWidth();

int y = 0;
while(y0)影が分かりやすいようになんとなく用意した背景

1)まず影をつけたいものを描きます。

2)それを右下にずらした矩形を作ります。

右下に30ずらしてます。
rect = new RectF(50f,100f,250f,200f);
↓
float diff = 30f;
shadowRect = new RectF(50f + diff,100f + diff,250f + diff,200f + diff);

3)それを影っぽいペイントで描画します。

4)あとは、影→背景→枠の順で描画して完了。

なんか書いてみたら、ずっと暖めていた割に簡単だった・・。
暖めすぎたか・・。

ポイントは、影のペイントは、ぼかし効果をいれるところです。
BlurMaskFilter blur = new BlurMaskFilter(8, BlurMaskFilter.Blur.NORMAL);