Java」タグアーカイブ

Android SDKに統合された難読化ツール「ProGuard」を試す


GingerbreadことAndroid2.3のリリースに合わせて公開された新しいSDKとEclipseプラグイン、個人的に一番興味があったのは難読化ツール「ProGuard」が統合されたことです。

少々解説しておくと、Javaは比較的リバースエンジニアリングに弱いというか、コンパイル済みのファイルから結構なところまでソースコードが復元できてしまうので、リバースエンジニアリングから防御するためには、変数名やメソッド名を意味のない値にする(例えばgetDate()というメソッドをa()にしてしまう)ツールが有効で、そんなツールがProGuardです。変数名やメソッド名が短くなることにより、アプリケーションのファイルサイズが小さくなるというメリットもあります。

さて、新しいSDK+Eclipseプラグイン環境でProGuardを使うためには、まずプロジェクト内のdefault.propertiesに

proguard.config=proguard.cfg

という内容を追記します。ここでproguard.cfgはProGuardの設定ファイルで、新しい環境でAndroidプロジェクトを作るとある程度お仕着せのproguard.cfgが自動でプロジェクトに含まれます。既存のプロジェクトにproguard.cfgを追加する方法がわからなかったので、自分は空のAndroidプロジェクトを1個つくってproguard.cfgを拝借しましたw。基本的にはこれだけで、リリース用ビルドを行う(「Export Signed Application Package…」を実行する)時に自動的にProGuardで処理してくれます。

さて、これでProGuardが万全かというとそうでもありません。自分の場合Twitterライブラリ「Twitter4J」で少々つまづきました。まず、通常のビルドでは必要とされていない依存ライブラリがProGuardで必要とエラー表示されたので、proguard.cfgに以下の記述を追加。

-libraryjars (JARファイルへのパス)/slf4j-api-1.6.1.jar
-libraryjars (JARファイルへのパス)/commons-logging-1.1.1.jar
-libraryjars (JARファイルへのパス)/log4j-1.2.16.jar

ここで(JARファイルへのパス)はライブラリが存在するパス(相対・絶対のどちらでもOK)です。

これでProGuardは正常終了してアプリケーションファイルが生成できるようになりますが、実際に動かしてみるとTwitter4J関係のところで異常終了してしまいます。厳密にコードを追えば原因を特定できるのでしょうが、もともとTwitter4Jはソースが公開されているライブラリで難読化する意味が無いと考えたので、proguard.cfgに以下の記述を追加してまるっと難読化の対象から外してみました。

-keepclasseswithmembers  class twitter4j.**
{
    *;
}

ここで「twitter4j.**」というのは、twitter4jパッケージ配下の任意深さの階層の全て、要は「まるっと」という意味です。

これでTwitter4J部分のプログラムも動くようになりました。ちなみにどのクラスがどんな名前にされたかは、proguardフォルダのmapping.txtに出力されるので、設定を調整するときの参考にすると良いと思います。

参考までに拙作「twicca マルチ画像プラグイン」の場合、ファイルサイズが234KB→176KBに削減されました。変数名やメソッド名を書き換えるという性質上、リリースビルドでひと通りテストを行うことが必須となりますが、少しでもファイルを軽くしたい、自分のコードを守りたいという人にとって試す価値のあるツールだと思います。

ケータイメールTwitter投稿ツールをGAE/J→自宅サーバーに移した


先週末から今日の午前中くらいにかけて、Google App Engine for Java(GAE/J)で稼働していた「ケータイでメールを送信すると写真は画像サービスに、本文はTwitterに反映する」という自分用アプリをメンテナンスしていました。というのも、画像のファイルサイズがある程度以上大きくなってしまうとGAE/Jの実行時間制限(30秒)に引っかかって強制中断されてしまうことが結構あったのです。

しかもたちの悪いことに、強制中断されても画像自体は画像サービスに正しく反映される場合があるので、投稿をリトライさせるとその都度同じ画像が何度も投稿され、ちょっとしたDoS攻撃のように。GAE/Jの実行時間制限を回避するために処理を分割しようにも、画像サービス側が制限時間内に応答しないとなすすべなし。

さすがにこれはおっかないということで、自宅サーバー(CentOS)にJava+Tomcatをインストールしてそちらにアプリ一式を移植しました。DataStoreやら画像の変換やらGAE/Jに依存していた処理を削除し、シンプルに「メール受信→画像投稿→Twitter投稿」だけをする感じで。リトライ処理とかはバッサリ削除しましたが、今のところは順調なようです。自分しか使わないアプリなのでまあいいかとw。

ちなみに受信したメールをServletに受け渡す方法はこちらが参考になりました。

Servletでメール処理 (Utilz)

【メモ】Androidアプリを署名するためのキーストアを「keytool」で操作


Androidアプリの配布時には、ウィザードに従いバイナリを署名するのですが、その時によくわからずキーストアをたくさん作ってしまって収集がつかなくなることもあるのではないでしょうか。私もそうですw。

実はJDKのbinフォルダにあるkeytoolコマンドを利用して、キーストアを管理することが出来ます。

私は以下の手順で、複数のキーストアに散らばったキーを1ファイルのキーストア内にまとめました。

1. キーストア内のキーの名前を変更して、名前がかぶらないようにする。

$ keytool -keystore C:\KeyStoreFile -changealias -alias FROM_NAME -destalias TO_NAME

このコマンドで、C:\KeyStoreFile内のキー「FROM_NAME」が「TO_NAME」に名称変更されます。

2. マージ先のキーストアを1個決めて、そのキーストアに他のキーストアをマージする

$ keytool -importkeystore -srckeystore C:\SourceKeyStoreFile -destkeystore D:\DestKeyStoreFile

このコマンドで、C:\SourceKeyStoreFile内の全てのキーがD:\DestKeyStoreFile内にコピーされます。

その他キーストアやキーのパスワード変更など、結構便利な処理が出来ます。詳しくはこちらをどうぞ。

keytool – 鍵と証明書の管理ツール

Twitter4JでUser StreamによるTwitterタイムラインのリアルタイム更新に挑戦


Twitterクライアントの動作検証をする目的で、TwitterのUser Stream APIを使ったTwitterタイムラインのリアルタイム更新に挑戦してみました。とはいえAPIをナマで叩くのはちょっとハードルが高すぎたので、Twitter APIのJavaラッパーである「Twitter4J」を利用します。

作ったアプリはこんな感じ。Twitter4JはJavaのライブラリなので、アプリもSwingを使ったJavaアプリです。Swingなんて触ったの何年ぶりだろうw。動作検証なのでGUIは超手抜きw。モザイクをかけているところが受信したTwitterタイムラインですが、これじゃなんのことかさっぱりわかりませんねww。

TwitterUserStream

これだけだと何なので、最低限のサンプルコードなど置いておきますね。

// User Stream APIを開始する
private void startUserStream()
{
	// Configureationを生成するためのビルダーオブジェクトを生成
	ConfigurationBuilder builder = new ConfigurationBuilder();
 
	// コンシューマーキーとアクセスキーを設定
	builder.setOAuthConsumerKey( CONSUMER_KEY );
	builder.setOAuthConsumerSecret( CONSUMER_SECRET );
	builder.setOAuthAccessToken( ACCESS_TOKEN );
	builder.setOAuthAccessTokenSecret( ACCESS_TOKEN_SECRET );
 
	// 現行のTwitter4JではAPIのデフォルト呼び先がbetastream.twitter.comになっているので修正
	builder.setUserStreamBaseURL( "https://userstream.twitter.com/2/" );
	 
	// Configurationを生成
	Configuration conf = builder.build();
	 
	// TwitterStreamを生成
	TwitterStreamFactory factory = new TwitterStreamFactory(conf);
	twitterStream = factory.getInstance();
	 
	// イベントを受け取るリスナーオブジェクトを設定
	twitterStream .setUserStreamListener( new MyStreamAdapter());
	 
	// User Streamの取得をスタート
	twitterStream.user();
}
 
// イベントを受け取るリスナーオブジェクト
class MyStreamAdapter extends UserStreamAdapter
{
 
	// ステータス更新のハンドラ
	@Override
	public void onStatus(Status status) {
	super .onStatus(status);
	 
	// ステータスを受け取って何かをする
	System.out.println(status.getText());
}

処理の流れはコメントを見ていただければ大筋分かるのではないでしょうか。注意する点は、現行バージョンのTwitter4JではUser Stream APIの呼び先がbetastream.twitter.comになっているので、Configurationオブジェクトで設定を上書きすることくらいでしょうか。まあそのうちアップデートで修正されるとは思いますが。

これでstartUserStreamメソッドを実行すると、User Stream APIによりタイムラインの更新がズラズラと表示されます。結構感動しましたw。せっかくなのでこのサンプルコードが何かの参考になれば幸いです。

iPhoneアプリをJavaで開発


iSpectrum (FlexyCore)

FlexyCoreの「iSpectrum」は、iPhoneアプリをJava言語で開発することができる環境です。開発したアプリケーションをオープンにすることを義務付ける「iSpectrum Open」は無料で使えますが、非オープンソースアプリケーションを開発する際には有償版が必要とのこと(価格は未記載)。

サンプルコードをちょっと読んだ感じでは、iPhoneSDKのAPIとほぼ同じ内容のJavaクラスを持っており、あくまでiPhoneというかCocoaの流儀で、でも言語はJavaでという感じで開発するようです。Javaの特徴としてメモリ管理が自動化される(ガベージコレクション)のは魅力的ですね。