fly1tkg blog

SimpleでXMLをParseする

JavaでXMLをParseするライブラリの一つにSimpleというものがあります。こいつはAndroidにも使えるので紹介します。

Simpleとは

POJOなオブジェクトに特定のannotationをつけると、そのオブジェクトとXMLを簡単に相互変換出来るようになる。すごくいいやつ。

http://simple.sourceforge.net/

インストール

Downloadのページから最新版をダウンロードします。

http://simple.sourceforge.net/download.php

ダウンロードした中身のjarフォルダの中身をAndroid Projectのlibsフォルダに入れればOK

Mavenを利用しているならpom.xmlに

<dependency>
    <groupId>org.simpleframework</groupId>
    <artifactId>simple-xml</artifactId>
    <version>2.6.9</version>
</dependency>

を記述すればOK

サンプル

本家のTutorialから、XML –> POJOオブジェクトの方法について。

例えば以下のようなXMLがあった場合、

<root id="123">
   <message>Example message</message>
</root>

これを以下のPOJOの中にいれたい

@Root(name = "root")
public class Example {
 
    @Element(name = "message")
    private String text;
 
    @Attribute(name = "id")
    private int index;
 
    public String getMessage() {
        return text;
    }
 
    public int getId() {
        return index;
    }
}

この変換処理はSimpleを使えばこんなに簡単

String xml = "<root id="123"><message>Example message</message></root>";
        Serializer serializer = new Persister();
        try {
            Example example = serializer.read(Example.class, xml);
        } catch (Exception e) {
            e.printStackTrace();
        }

ネストしたオブジェクトに変換する

XMLが深くネストしている場合はこんな感じ。要素名がクラス名やメンバ変数名を一致している場合はnameのプロパティを省略出来ます。

<configuration id="1234">
   <server port="80">
      <host>www.domain.com</host>
      <security ssl="true">
         <keyStore>example keystore</keyStore>
      </security>
   </server>
</configuration>
@Root
public class Configuration {
 
   @Element
   private Server server;
 
   @Attribute
   private int id;
 
   public int getIdentity() {
      return id;
   }
 
   public Server getServer() {
      return server;          
   }
}
 
public class Server {
 
   @Attribute
   private int port;
 
   @Element
   private String host;
 
   @Element
   private Security security;
 
   public int getPort() {
      return port;          
   }
 
   public String getHost() {
      return host;          
   }
 
   public Security getSecurity() {
      return security;          
   }
}
 
public class Security {
 
   @Attribute
   private boolean ssl;
 
   @Element
   private String keyStore;
 
   public boolean isSSL() {
      return ssl;          
   }
 
   public String getKeyStore() {
      return keyStore;          
   }
}

同じ要素が連続しているときはListに変換できる

<propertyList name="example">
   <list>
      <entry key="one">
         <value>first value</value>
      </entry>
      <entry key="two">
         <value>first value</value>
      </entry>
      <entry key="three">
         <value>first value</value>
      </entry>
      <entry key="four">
         <value>first value</value>
      </entry>
   </list>
</propertyList>
@Root
public class PropertyList {
 
   @ElementList
   private List<Entry> list;
 
   @Attribute
   private String name;
 
   public String getName() {
      return name;
   }
 
   public List getProperties() {
      return list;
   }
}
 
@Root
public class Entry {
 
   @Attribute
   private String key;
 
   @Element
   private String value;
 
   public String getName() {
      return name;
   }
 
   public String getValue() {
      return value;
   }
}

必須では無いノードを指定する

XMLの中に必須ではないノードがある場合、required = falseのオプションの指定が必要です。

<optionalExample id="10">
   <address>Some example address</address>
</optionalExample>
@Root
public class OptionalExample {
 
   @Attribute(required=false)
   private int version;
 
   @Attribute
   private String id;
 
   @Element(required=false)
   private String name;  
 
   @Element
   private String address;
 
   public int getId() {
      return id;
   }
 
   public int getVersion() {
      return version;
   }
 
   public String getName() {
      return name;
   }
 
   public String getAddress() {
      return address;
   }
}

その他の使い方等

本家サイトに大量に乗っているので参考にしてください。

http://simple.sourceforge.net/download/stream/doc/tutorial/tutorial.php

http://simple.sourceforge.net/download/stream/doc/examples/examples.php

AndroidのアニメーションBackportライブラリ「NineOldAndroids」を使う

AndroidのアニメーションのパッケージってちゃんとAPI Level 1から準備されていて、1年前僕が始めて受託でアプリ作ったときは、iPhoneに負けまいと壮絶なコードを書いたものです。あのときは若かったなー、受託のコードにどれだけ力入れてるんだって。(いや、いまでも受託アプリに大分力入ったコード書いてるぞ、、、こういう性格なんだな)

で、その昔っからあるanimationだと色々不都合で、ちょっと前につ部のミーティングで発表したスライドがこれ。

このなかでAnimationのBackportライブラリについて一言書いてあるのだけれど、僕はNineOldAndroidsというライブラリが良いんじゃないかなと思います。

NineOldAndroids
http://nineoldandroids.com/

こいつはHoneyCombで実装されたAnimationをBackPortするライブラリです。

これをつくったのはJakeWhartonさん。そう、あのActionBarSherlockを公開している人ですね。

簡単に使い方を説明します。

まずはダウンロード

NineOldAndroids – DownLoad
http://nineoldandroids.com/#download

ZIPでもTGZでもよいので、ダウンロードして展開してください。

WorkSpaceにNineOldAndroidsを追加

Eclipseを開いて、左側のPackage Exploreの上で右クリック -> import -> Android -> Existing Android code into Workspaceと選択

先ほどダウンロードしたファイルのlibraryフォルダとsampleフォルダを選択すればOK。これでサンプルが動くようになります。

サンプル以外でNineOldAndroidsを使う

Package Exploreで使いたいProjectを右クリック -> Propertiesを選択。

ウインドウが開いたら左側のメニューからAndroidを選択

Libraryの項目で先ほどのLibrary ProjectをAddすればOK。これで使えるようになります。

使い方

基本的にはHoneyComb以降のandroid.animationパッケージのクラスがそのまま使えるようになります。android.animation.*のかわりにcom.nineoldandroids.*をimportすれば使えます。sampleコードがいろんなアニメーションのデモをしているのでそちらを参考にしながらかくといいです。

参考) android.animation
http://developer.android.com/reference/android/animation/package-summary.html

Android YouTube Player APIをつかったアプリ内YouTube再生

以前[WebViewを使ったYoutubeの再生方法][1]は紹介しましたが、アプリ内でYoutubeを再生する方法がもう一つあります。それはAndroid YouTube Plugin APIを利用した方法です。

Googleの日本の人のエントリーがこちら
http://googledevjp.blogspot.jp/2013/01/android-youtube-player-api-webview.html

Android YouTube Player APIを利用してみてメリットとデメリットを以下にまとめました。

メリット

  • JavaのネイティブコードでYouTubeの再生制御ができる。
  • フルスクリーン表示や画面回転の制御が簡単

他にも上記リンクの人が言及しています。

デメリット

  • 端末のYouTubeアプリが最新になっている必要がある。(時間がたてば解決しますが)
  • 基底クラスにcom.google.android.youtube.player.YouTubeBaseActivityを使う必要があるのでActionBarSherlockとか3rdのライブラリとの菱形継承問題(まあもう片方がオープンソースならばどうにでもなりますが)

で、使い方が以下リンクに書かれているのですが、英語じゃ分かんねえよって人のために、簡単にサンプルコードを動かすまでの手順を紹介します。

YouTube Android Player API
https://developers.google.com/youtube/android/player/

アプリの登録

まずはGoogle APIs Consoreでプロジェクトを作成します。これを利用するにはGoogleのアカウントが必要です。

以下リンクを開いて、Create Projectをクリックしてください

Google APIs Consore
https://code.google.com/apis/console

もし他のプロジェクトが既にある場合は、左側のメニューからCreateをクリックすると新たにProjectを作成することができます。

YouTube Data API v3をONにする

左メニュのServiceの項目を選択し、下の方にあるYouTube Data API v3をONにします。

API Keyの発行

左側のメニューからAPI Accessをクリックします

Create Android Keyを押します

ダイアログが開きますが、何も入力せずCreateボタンを押すと全てのアプリで利用できるKeyを発行できます。(ここについては詳しくは後日かけたらいいな)

この部分のKeyを利用します。

ライブラリとサンプルコードを入手する

ライブラリは以下リンクの右側にあるdownloadってかいてあるところからダウンロードできます。

YouTube Android Player API – Download<br /> <a href="https://developers.google.com/youtube/android/player/downloads/">https://developers.google.com/youtube/android/player/downloads/</a>

サンプルコードをインポートする

Eclipseを起動して Package Exploreの上で右クリック、import -> Android -> Existing Android code into workspaceを選択します。

先ほどダウンロードした中身のsampleを選択してインポートします。

srcフォルダのcom.examples.youtubeapidemoパッケージのDepeloperKey.javaを開きます

<div id="highlighter_983196">
  <pre class="brush: java; gutter: true">public static final String DEVELOPER_KEY = null;</pre>
</div>

となっている所を先ほどのDeveloper Keyを入力してください。

これでアプリを起動すれば、YouTube Android Player APIのサンプルコードを動かすことができます。<br /> <br /> <!-- blog_widget -->

<br /> <ins class="adsbygoogle"<br /> style="display:inline-block;width:300px;height:250px"<br /> data-ad-client="ca-pub-6228702140385127"<br /> data-ad-slot="3243171800"></ins><br />

[1]: http://blog.fly1ncu.com/2013/01/android-webview-youtube/ “WebViewをつかったYouTubeの再生方法”

Androidの非同期通信ライブラリをつかう その2- Android Asynchronous Http Client

続き書くとか言って、半年も書いていなかった。簡単ですが続きを書きます。

Android Asynchronous Http Clientとは?

Androidの非同期通信ライブラリの一つ、詳しくは前回のエントリー記事を参照してください。
僕の調査によるとFxCameraにも使われていますね。このライブラリ。(LICENSE.txtからの確認なので、ソースコードのみの利用かもしれませんが)

半年で変わったことと言えば、同期通信が出来るようになったことですね。(ライブラリ名とレポジトリ名に反してない?)。AsyncTaskなどとの相性で追加したようですが、、、

MyAsyncHttpClientを作る

オススメの使い方としてMyAsyncHttpClientを作ることです。そうすることで、自分の好みにセッティングした通信を行うことが出来ます。

public class MyAsyncHttpClient extends AsyncHttpClient {
    public MyAsyncHttpClient() {
        // ここに設定を書く
    }
}

userAgentを設定する

AsyncHttpClientのデフォルトのuserAgentはAndroid Asynchronous Http Client/VERSION (http://loopj.com/android-async-http/)です。デバッグ等のことを考えるとアプリのパッケージ名やバージョンといった文字列に変更した方が良さそうです。userAgentの変更はAsyncHttpClient#setUserAgent(String userAgent)で任意のものに変更することができます。

setUserAgent("MyApp ver1.0");

Time out時間を設定する

Time outの時間もメソッドが準備されています。AsyncHttpClient#setTimeOut(int timeOut)です。こちらはデフォルトで10秒です

setTimeOut(8);

Basic認証のためのユーザー名とパスワードをセットする

setBasicAuth("user", "password");

注意点

MyAsyncHttpClientを準備したはいいけど、いざ使うときにAsyncHttpClientで実装しないようにしてください(自戒)

(前回)Androidの非同期通信ライブラリをつかう その1- Android Asynchronous Http Client

WebViewでYoutubeを再生する

初期状態のWebViewではYouTubeのiframeを埋め込んだサイトを表示できません。

マニフェストの設定を行う

Youtubeの再生には以下の設定が必要です。

  • user-permissionのInternet
  • hardware accelarationの有効化
<uses-permission
        android:name="android.permission.INTERNET"/>
 
<application
        android:allowBackup="true"
        android:hardwareAccelerated="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

 

WebViewのJavascriptとPluginをONにする

以下ソースを参考にJavascriptとPluginをONにします。mWebViewはWebViewのメンバ変数名です。

private void initWebView() {
        mWebView = (WebView) findViewById(R.id.webView);
 
        // WebViewの設定
        WebSettings settings = mWebView.getSettings();
        settings.setJavaScriptEnabled(true);
        if (Build.VERSION.SDK_INT > 7) {
            settings.setPluginState(PluginState.ON);
        } else {
            settings.setPluginsEnabled(true);
        }
 
        String html = "";
        html += "<html><body>";
        html += "<iframe width="560" height="315" src="http://www.youtube.com/embed/MU9Srs04sFU?rel=0" frameborder="0" allowfullscreen></iframe>";
        html += "</body></html>";
 
        mWebView.loadData(html, "text/html", null);
    }

再生中に他のアクティビティに移動すると再生されっぱなしになってしまう

以下のコードを追加する

@Override
    protected void onResume() {
        super.onResume();
        try {
            WebView.class.getMethod("onResume").invoke(mWebView);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    @Override
    protected void onPause() {
        super.onPause();
        try {
            WebView.class.getMethod("onPause").invoke(mWebView);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

サンプルコード

GitHub上に公開してあります。

https://github.com/fly1tkg/android-youtube-webview-sample

追記) Youtube Android Player APIをつかった方法を書きました

http://blog.fly1ncu.com/2013/02/android-youtube-player-api/ ‎

ProgressBarのぐるぐるをカスタマイズ

AndroidのProgressBarのぐるぐるをカスタマイズする方法全然見つからなかったのでメモ

drawableフォルダにこれを入れる。android:drawableには変えたいぐるぐるの画像を入れます。

<?xml version="1.0" encoding="utf-8"?>
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/progress"
    android:pivotX="50%"
    android:pivotY="50%" />

で、これをlayoutのProgressBarに適用。android:interminateDrawableの部分ですね。

<ProgressBar
           android:id="@+id/mProgressBar"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:indeterminateDrawable="@drawable/progressbar_bg" />

回転のスピードはDurationとか変えてみたんだけど、いまいち分からず。

AndroidでProguardによる難読化

AndroidアプリはJavaで書かれていますが、Javaはデコンパイルが容易です。そのため簡単にソースコードが丸見えになってしまいます。そのためにソースコード難読化がです。ProguardはJavaのソースコードを難読化するツールで、最新のADTにはAndroidで簡単に使えるようになっています。以下に現在最新のADT20で行った方法をメモしておきます。

使い方

project.propertiesのproguard.configの行をアンコメント(先頭の#を消す)します。
その後 File > Export > Export Android Applicationでリリースビルドをします。

# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

たったこれだけでソースコードの難読化ができます。

難読化の結果はprojectフォルダの中に生成されたproguardフォルダの中の4つのテキストファイルに出力されます。

  • dump.txt –> apkファイルの構成
  • mapping.txt –> 難読化されたクラスやメソッドなどの履歴
  • seeds.txt –> 難読化されていないクラスなどのリスト
  • usage.txt –> 削除されたコードのリスト

mapping.txtを開いてみるとクラス名やメソッド名がどのように変更されたかを見る事ができます。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
android.support.v4.app.ActivityCompatHoneycomb -> android.support.v4.app.a:
void invalidateOptionsMenu(android.app.Activity) -> a
android.support.v4.app.BackStackRecord -> android.support.v4.app.b:
android.support.v4.app.FragmentManagerImpl mManager -> a
android.support.v4.app.BackStackRecord$Op mHead -> b
android.support.v4.app.BackStackRecord$Op mTail -> c
int mNumOp -> d
int mEnterAnim -> e
int mExitAnim -> f
int mPopEnterAnim -> g
int mPopExitAnim -> h
int mTransition -> i
int mTransitionStyle -> j
boolean mAddToBackStack -> k
boolean mAllowAddToBackStack -> l
java.lang.String mName -> m
boolean mCommitted -> n
int mIndex -> o
int mBreadCrumbTitleRes -> p
java.lang.CharSequence mBreadCrumbTitleText -> q
int mBreadCrumbShortTitleRes -> r
java.lang.CharSequence mBreadCrumbShortTitleText -> s

このようにクラス名やメソッド名が1~2文字程度の英字に置き換わります。

Proguardの仕組み

Proguardにはコードの短縮、最適化、難読化、事前検証の4つのステップがあります。

コードの短縮や最適化のステップで、使用していないクラスやメソッドを削除したり変数の折りたたみを行ったりする事で、ソースコードの圧縮を行います。

難読化のステップではクラス名やメソッド名などを1~2文字の英数字で置き換え、難読化をさせます。

事前検証のステップではProguardでの処理で問題が無いかチェックします。

proguardの設定ファイルは2カ所に分かれておいてあって、1つは/tools/proguard/proguard-android.txt
こちらはapkにするときのproguard全体の設定が書かれています。

もう一つはprojectフォルダの中のproguard-project.txt こちらにprojectごとの設定を書きます

注意点

ProguardはピュアなJavaのコードに対してはきちんと動くようですが、Androidの様にxmlなどの静的なファイルを参照したり、いろいろしてると、誤作動で使用しているクラスやメソッドが消されてしまうことがあります。
基本的にはusage.txtと見比べながら、必要なコードが消されていないかや、mapping.txtを見てリネームしてはいけないものがリネームされていないかをチェックする必要があります。

ライブラリとしてjarを使用している場合

-libraryjar <jarのパス> のオプションをproguard-project.txtに追加します

-libraryjars ./libs/actionbarsherlock-plugin-maps-4.1.0.jar
-libraryjars ./libs/android-async-http-1.4.0.jar
-libraryjars ./libs/jsonpullparser-core-1.4.jar
-libraryjars ./libs/twitter4j-core-android-2.2.6.jar

また一般的なオープンソースのライブラリであれば、StackOverFlowとかで推奨の設定が書かれていたりします。
例えばtwitter4jであればこれ http://stackoverflow.com/questions/7721397/how-to-make-proguard-ignore-external-libraries

-keep class javax.** { *; }
-keep class org.** { *; }
-keep class twitter4j.** { *; }

-keep オプションは指定したクラスを難読化しないというオプションです

ライブラリプロジェクトを使用している場合

library projectを参照している場合は.R.classがよく消されます。
特にlibrary projectの中のdrawableなどのresourceを参照している場合です。

-keep class <パッケージ名>.R { *; }

などで消されないようにしましょう

Android NDKでJNIのメソッドを読んでいる場合

ラッパーのクラスを-keepメソッドで難読化しないようにしましょう。
nativeを読んでいるメソッドはProguard側で使用されていないメソッドとして消される場合があります

最後に

Proguardを使用したからといって、定数の中身まで難読化はされません。パスワードなどを平文でapkに含めないようにしましょう。

Androidの非同期通信ライブラリをつかう その1- Android Asynchronous Http Client

Androidで通信するのめんどくさいです。めんどくさい理由が2つあります

  • そもそもHttpClientのコード書くのがめんどくさい。
  • 非同期通信をするのがめんどくさい。

1つ目は僕の主観かもしれないですが、めんどくさい。だいたい毎回同じようなコードなので僕はコピペです。しかしコピペするならライブラリを使用するのがスマートですよね。

2つ目については、Androidで通信するときってメインのスレッドでやると、そこで描画の処理が止まってフリーズしているように見えるので別スレッドで非同期に通信するのが一般的ですよね。
Honeycomb以降だと標準でStrictModeからNetworkOnMainThreadExceptionが投げられます。もちろん例外を投げられないように設定する事も可能ですが、やっぱり非同期のほうがユーザーに優しいです。
じゃあAsyncTask使うか!ってなるのですが、ちょっとした通信も全部これで書くのは、いささかやりたくない。

そんなあなたにAndroid Asynchronous Http Client
作者はloopj(James Smith)さん。Githubの写真がイケメンです。Apache2.0ライセンスで公開されています。
あのInstagramもこのライブラリを使用しているそうです

特徴

  • Callbackベースで非同期通信の処理ができる
  • Multipartでファイルのアップロードができる(Android標準のライブラリでできないのです、ぷんぷん)
  • ライブラリは25KBと小さいので、オーバーヘッドが少ない
  • gzipの設定とかその他もろもろHttpClientにいい感じの設定をやってくれといてくれる
  • バイナリのダウンロードももちろん対応、画像ファイルのダウンロードも楽々です
  • etc…

使い方

Projectフォルダのlibsフォルダに http://loopj.com/android-async-http/ からDownloadできるandroid-async-http-1.4.1.jar(現在の最新)を入れます。
一昔前はビルドパスを通すという作業をしていましたが、最新のADTではlibsフォルダに入れるだけで大丈夫なようです。(実は最近知りました、ADTのアップデートもちゃんと追わないとだめですねorz)
またGithubからcloneしてProject Libraryとして使用してもOKです。https://github.com/loopj/android-async-http

あとは通信したいところで以下のようなコードを書きます。

AsyncHttpClient client = new AsyncHttpClient();
client.get("http://www.google.com", new AsyncHttpResponseHandler() {
    @Override
    public void onSuccess(String response) {  
     // ここに通信が成功したときの処理をかく
        System.out.println(response);
    }
});

通信に失敗したときの処理(ステータスコードが200じゃなとき)は、AsyncResponseHandlerのonFailureをOverrideしたメソッドに書く事ができます。

AsyncHttpClient client = new AsyncHttpClient();
client.get("http://www.google.com", new AsyncHttpResponseHandler() {
    @Override
    public void onSuccess(String response) {  
     // ここに通信が成功したときの処理をかく
        System.out.println(response);
    }
  @Override
    public void onFailure(Throwable error, String response) {  
     // ここに通信が失敗したときの処理をかく
        System.out.println(response);
    } 
});

テキストデータだけではなくバイナリデータもロードする事ができます。これで画像などのファイルもダウンロードできます。

AsyncHttpClient client = new AsyncHttpClient();
client.get("画像のアドレス", new BinaryHttpResponseHandler() {
    @Override
    public void onSuccess(byte[] binaryData) {  
     // ここに通信が成功したときの処理をかく
    }
  @Override
    public void onFailure(Throwable error, byte[] binaryData) {  
     // ここに通信が失敗したときの処理をかく
    } 
});

GETやPOSTのメソッドでパラメーターをつけたいときもこんな感じ。ちなみにAsyncHttpClient#PostでPostメソッドで通信できるし、PUTやDELETEも準備されています。

RequestParams params = new RequestParams();
params.put("key", "value");
params.put("more", "data");
AsyncHttpClient client = new AsyncHttpClient();
client.post("POSTしたいURL", params, new AsyncHttpResponseHandler() {
    @Override
    public void onSuccess(String response) {  
     // ここに通信が成功したときの処理をかく
        System.out.println(response);
    }
});

RequestParamsは以下のようにも追加する事ができます。

// パラメータが1つしかないとき
RequestParams params = new RequestParams("single", "value");
 
// Mapで指定するとき
HashMap<String, String> paramMap = new HashMap<String, String>();
paramMap.put("key", "value");
RequestParams params = new RequestParams(paramMap);

基本的な使い方はこんな感じです。

このライブラリの僕なりの使い方はまた今度書きます。

(次回)Androidの非同期通信ライブラリをつかう その2- Android Asynchronous Http Client