投稿履歴: プログラム

開発メモ/Proguardのすすめ

Proguardって、ソースを暗号化するためということで、無料アプリなら別にソース見られたっていいじゃん!とか考えていませんか?

Proguardってそれだけじゃなくてソースコードの圧縮→apkの容量削減にも役立ちます。
でも一つ間違えたらExceptionとか見えなくなるので設定には注意が必要です。

さて、最新のADTでプロジェクトを作るとproject.propertiesに下記の項目が追加されています

proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt

ここの内容はproguardの設定を読み込むライフを指定しているのですが、まずSDK内のtools\proguard\proguard-android.txtを読みます。
そして追加でプロジェクト内のproguard-projectを読みます。
この中で前者ではActivityの名前を難読化から外したりしてくれていますので細かい設定は不要です。(Activity名変えちゃうとマニフェストと整合性が取れなく落ちてしまいます)

で、そのままでも使えるのですが(外部ライブラリがない場合)、そのままだとExceptionの発生した行数などがすべてUnknown Sourceとなってしまいます。
なので、
プロジェクト内のproguard-project.txtに下記を追加してあげます
-renamesourcefileattribute ProGuard <-ソースをProguard文字列に置換します
-keepattributes SourceFile,LineNumberTable <-ソースファイル、行数属性を変換せず維持します

基本的にはこれだけでOKです。

ただ、外部jarなどのライブラリをロードしている場合、これらが難読化されてしまうと思うように動きません。(※下記はAdmobを例にします)
同様にproguard-project.txtに下記を追加します
-libraryjars \libs\GoogleAdMobAdsSdk-6.1.0.jar <-ライブラリをつかうよー
-keep class com.google.ads.** {*;} <-この名前空間は変換しないでね
-dontwarn com.google.ads.** <-この名前空間は警告を出さないでね

これでOKです。dontwarnはいるのかわからないですが、警告がでてリリースビルドができなかったのでぐぐって追加しました。

あとは、エクスポートしたパッケージでテストをしてみるといいです。

SwitchPreferenceがおかしな件

Android4.0から採用されましたSwitch

スイッチとはこういうのですね



これのPreference版です。

さてこのSwitchを下記のように指定しました


もちろんちゃんと表示されます。

で全く気付かなかったんですが、このSwitchPreferenceを複数設置しているPreferenceActivityにて
画面をスクロールすると。。。。

なぜか、ONにした後、スクロールして戻ってくるとOFFになってたりしました。
(ListViewのgetView()処理でうまくかけていない状態みたいな感じでした)

でも別のアプリではうまく動いていたので差分を見てみるとうまく動いていたアプリはSwitchPreferenceを継承したクラスを使用していたのです。
でも書いているソースはこんな感じ

public class SwitchPreference extends android.preference.SwitchPreference{



	/**
	 *
	 * 設定画面呼び出し時に呼ばれる
	 * @param context
	 * @param attrs
	 */
    public SwitchPreference(Context context, AttributeSet attrs) {
        super(context, attrs);

    }



    /**
     * データバインド時に呼び出される
     */
    @Override
    protected void onBindView(View view) {
       super.onBindView(view);
    }

}


いやなんもしてないですやん・・・

でもこれだと上の事象が解消されるのです。
実際ほかのアプリに対して適用したら解消されてしまいました。

よくわかりません。バグでしょうか?それとも私の指定がおかしいのでしょうか。

ご存知の方教えてください

Switchを利用するときの注意

現在Android 4.0以降はswitchで、それ未満はCheckBoxをと
include等を使用してXMLレイアウトを作成していて実行してみました。

Aアプリ NG
Bアプリ NG
Cアプリ OK

switch関連(switchPreference)も使うと
落ちるんです。

android.widget.Switchの651行目でぬるぽします。

半日ほどハマリました

08-24 16:58:41.155: E/AndroidRuntime(13624): FATAL EXCEPTION: main
08-24 16:58:41.155: E/AndroidRuntime(13624): java.lang.NullPointerException
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.widget.Switch.jumpDrawablesToCurrentState(Switch.java:651)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.view.ViewGroup.jumpDrawablesToCurrentState(ViewGroup.java:5137)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.view.View.onAttachedToWindow(View.java:9602)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.view.View.dispatchAttachedToWindow(View.java:9904)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2301)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.view.ViewGroup.addViewInner(ViewGroup.java:3483)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.view.ViewGroup.addViewInLayout(ViewGroup.java:3420)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.widget.ListView.setupChild(ListView.java:1864)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.widget.ListView.makeAndAddView(ListView.java:1818)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.widget.ListView.fillDown(ListView.java:687)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.widget.ListView.fillDown(ListView.java:666)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.widget.ListView.fillFromTop(ListView.java:757)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.widget.ListView.layoutChildren(ListView.java:1668)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.widget.AbsListView.onLayout(AbsListView.java:1873)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.view.View.layout(View.java:11434)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.view.ViewGroup.layout(ViewGroup.java:4331)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1666)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1524)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.widget.LinearLayout.onLayout(LinearLayout.java:1429)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.view.View.layout(View.java:11434)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.view.ViewGroup.layout(ViewGroup.java:4331)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.widget.FrameLayout.onLayout(FrameLayout.java:443)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.view.View.layout(View.java:11434)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.view.ViewGroup.layout(ViewGroup.java:4331)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1666)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1524)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.widget.LinearLayout.onLayout(LinearLayout.java:1429)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.view.View.layout(View.java:11434)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.view.ViewGroup.layout(ViewGroup.java:4331)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.widget.FrameLayout.onLayout(FrameLayout.java:443)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.view.View.layout(View.java:11434)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.view.ViewGroup.layout(ViewGroup.java:4331)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1489)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2442)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.os.Handler.dispatchMessage(Handler.java:99)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.os.Looper.loop(Looper.java:137)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at android.app.ActivityThread.main(ActivityThread.java:4441)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at java.lang.reflect.Method.invokeNative(Native Method)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at java.lang.reflect.Method.invoke(Method.java:511)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:823)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:590)
08-24 16:58:41.155: E/AndroidRuntime(13624): 	at dalvik.system.NativeStart.main(Native Method)

違いを見つけてみると単純なこと
CアプリだけtargetSDKを指定していました。
A,BはminSDKだけでした。
みなさんきちんとtargetSDKは指定しましょう。

ってかこれってもしかしてAndroid側の不具合なのかな?
もし不具合ならIssueしたいけどやり方がわかりません。。。

Android2.3(GB)で端末起動時にサービスを開始させる方法で4.0(ICS)では動かない

miruker apps内のアプリの中でGカレンダー通知のみ
端末起動時にアラームサービスを起動しているのですが、
ICSで起動時にサービスが動いていないということに気づきました。

マニフェストで

<receiver android:name=".Reciever" ><android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
	<action android:name="android.intent.action.BOOT_COMPLETED"/>
	<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
こんな感じでintentを受け取ると端末起動時に処理をすることができます。
(注:ただしこれの場合はSDカードなどにアプリを移動している場合は受け取れません。
 (intent発行よりSDカードがマウントされるのが後だからだと思われます)

でGBでは動いていたんですけど、ICSで動いていなく調べたら、こちらのパーミッションがいる模様。

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
これの追加でなんなく動きました

Androidアプリでmonkeyテストをする方法

どうやらこれでできるようようです。
adb shell monkey -p [packagename] -v [実行する回数]

やる前にデータはきちんとバックアップとってからするかテスト機でしないと
大変なことになりますよー。



ContactsContractのgoogle+データ

Quick電話帳を開発していて、google+との連携を調べていました。

結論からするとgoogle+との連携方法は2つあります。

1つはcom.google.android.apps.plus.phone.UrlGatewayActivityに対して
profileのIDをデータとして渡してあげる方法

intent.setClassName(com.google.android.apps.plus,com.google.android.apps.plus.phone.UrlGatewayActivity);
intent.putExtra(customAppUri, ProfileID);

そしてもう一つの方法が、Contactと同期をとった場合にできる方法ですが、
こちらの場合は上のIDを取得することができません。
さてどうするか。

/** GooglePlusのデータ **/
Cursor cursorGPlus = con.getContentResolver().query(Data.CONTENT_URI,
new String[]{Data._ID,Data.DATA3,Data.DATA4,Data.DATA5},
Data.MIMETYPE +”=? AND ” + Data.CONTACT_ID +”=?” ,
new String[]{GooglePlusData.MIME_TYPE,StringUtility.toString(retData.getContactId())}, null);
if(cursorGPlus != null){
while(cursorGPlus.moveToNext()){
GooglePlusData gpData = new GooglePlusData(“”,cursorGPlus.getString(3), cursorGPlus.getString(1), cursorGPlus.getInt(0));
retData.getGooglePlus().add(gpData);
}
cursorGPlus.close();
}

こんな感じで取得しています。
Data.CONTENT_URIの中に、google+の連絡先データも入っています。
さて、この中でData3に入っているメッセージですが、実はここのデータはハングアウトをかいしーとかのメッセージが入っているのです。
さて、多言語対応という事で言語を変えてみたら、これが変わりません。。。
どのタイミングで言語情報が適用されるか調べてみたところどうやら、データを同期するタイミング(書き込むタイミング)の言語情報で
ここのメッセージを書き込んでいるようです。
ですので、一度、アカウントからgoogle+の同期設定を外し、言語を変更、再度gooogle+の同期を設定することで、言語が変わります。

ADTなどのVerを上げてからEclipseがエラーを吐く

Android requires compiler compliance level 5.0 or 6.0. Found ‘1.4’ instead. Please use Android Tools > Fix Project Properties.

これです。

これなんですけど、Eclipseのウィンドウ - 設定 - コンパイラーの準拠レベルが1.7とかになっていたらはくんですけど、自分の設定をみるとちゃんと1.6になっている。

こんな時は一度1.7にしてから適用して再度1.6にして適用したりするとなおります。

PreferenceActivityのレイアウトをカスタマイズする方法

ふとPreferenceActivityのレイアウトをカスタマイズしたいとおもってみたものの
さてどうするんだと思ったところ
どうやら、@android:id/listのIDのListViewを持つとカスタマイズできることが判明。

下記のようにしたらうまくいきました。

<ソースファイル>
onCreate内の処理

this.setContentView(R.layout.preference);
<今度はxmlの中のレイアウト>
addPreferencesFromResource(R.xml.settings_layout_extension);
//ここでうちのアプリはActionBarもどきのViewを突っ込んでます
super.initialize();
super.setTitle(R.string.keyPrefLayoutExtensionTitle);

<XMLファイル>

xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="@id/rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="?WindowStyle"
>
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
/>



新しいアプリ作ってます。

現在電話帳のアプリを作ってます。

コンセプトはとにかく機能は絞って軽く!
機能アクセスはシンプルに!
電話帳登録はしません!(とりあえず最初は)ほかのアプリに任せます!

電話帳って登録とかいろいろ機能あるものはあるんですけど
私の考えでは電話帳ってなんしか電話をしやすくするためのものという
考えがあって、いろいろ使いやすいように工夫中です。

こんな感じです。

一応無料でのリリースで、表示関連のカスタマイズはアプリ内課金とする予定です。

少し画面ができたので、下記にアップ!

リリースめどは6月上旬ごろです。

要望あればメールでもなんでもください。もしかしたらとりこまれるかも!?


ListViewにImageBottunを設置するとクリックできない

通常ListViewのアイテム内に、CheckBoxを設置する場合
xmlのCheckBoxのプロパティにfocusable=”false”をセットすると
うまくいくんだけど、ImageButtonではうまくいかなかった。

いろいろ調べた結果コード内のgetViewにて
MyImageButton.setFocusable(false);
を指定するとうまく動いた。

中までは追わないけど、これはバグなんかな??

2 / 41234