2012/01/28

PreferenceActivityで一個だけPreferenceFragmentを表示する

PreferenceFragmentに対してHeader等を利用せずに一個だけPreferenceFragmentを表示したいと思ったが、中々実現できなかったのでメモ的に。(見た目とか気にしなければ、普通のActivityにトランザクションしても表示できてしまうのかもしれないけど、やってないので分からない)


PreferenceActivityのメソッドを見てみるとstartPreferenceFragment(Fragment, boolean)なんてものがあるのでこれを利用すれば出来るのかなと思ったけれど、トランザクションするView見つかんねーぞ(゚Д゚)ゴルァって怒られる。

これの原因は
全てこいつが悪い。先のメソッドは
この通りただのトランザクションなのに
こんな互換性用のレイアウトを設定してしまうためにR.id.prefsというフラグメントトランザクション用のViewが消失。PreferenceActivityで自分でトランザクションを管理するにはこのViewへの切り替えを抑制する必要がある。



長々と理由を説明しつつ、PreferenceActivityはonCreateで最初に
を読み込むため、 これで1PreferenceActivity-1PreferenceFragmentが出来る。onIsMultiPaneかonIsHidingHeadersのどちらかを上書きしないとタブレット表示時にマルチペインになってしまうかも知れないので、予防的上書き。
ちなみにinitialTitleは画面タイトル(Phoneはタイトル部、TabletはFragment上部のタイトル部分の左)、initialShortTitleはTabletでFragment上部のタイトル部分の右に表示される用のStringリソースIDだとかなんとか。

2011/12/20

AndroidでPhoneとTabletを見分ける方法

Android4.0が出て、4.0.3が出て、対応端末もリリースされ、その端末がPhoneなのかTabletなのかを見分けるって結構重要ですよね。Androidのソースコードを元にPhoneとTabletを見分ける方法の紹介です。


・~Android 3.1
Build.SDK_INT見る。ハニカム以上ならタブレット


・Android 3.1~
この様にリソースにBooleanを定義しておいて、 こんな感じ。PhoneでもWXGAの端末が出てきたりして画面ピクセル数による見分けも出来なくなった今日この頃、PhoneとTabletの最大の違いはPhoneはhdpi(1:1.5)~xhdpi(1:2)なのに対してTabletは総じてmdpi(1:1)で画面に表示出来る内容が多いこと。同じ720pxでもPhoneは360dpなのに対してTabletは720dpとして利用できます。


結論:

2011/12/17

他パッケージ(APK)のclassファイルを読み込む

ちょっと興味があって調べてみた。


結論としては
  • 他のパッケージのクラスファイルは読み込める
  • セキュリティー的に問題あるんじゃね?

某ブログには
  • SharedUserIdを共有して
  • 共有Contextを作成すればできる
なんて書いてあるけどこれは嘘。以下、その方法

まずAndroidの標準的なリソース共有方法であるContextの共有から調べてみた。 これでClassを作成しようとすると怒られます。
。。。ん?
この部分が怪しい。
と言うわけでdalvik.system.PathClassLoaderをちょっと見てみると、 mDexとかmZipとか、何となくAPKパッケージを探していそう。コンストラクタを見てみると ビンゴですね。「:」で第一引数を区切ってそこからdexファイルを取得しようとしています。
PathClassLoaderを生成するときの第一引数はクラス名ではなくAPKファイル名を指定しなければいけないようです。


つまりこういうこと

実際にやってみて驚いたのが、これを実行するのにSharedUserIdが同一である必要は無いし、電子署名が一致してる必要も無いこと。これで既存アプリの中身に直接アクセス出来ちゃいます。
試してはいませんが、リソースにもこれで直接アクセス出来てしまうのかもしれませんね。

ちなみにAndroid4.0でこのPathClassLoaderの継承元がjava.lang.ClassLoaderからdalvik.system.BaseDexClassLoaderに変わっているため、同じ方法でアクセス出来ないかもしれません。要注意。これから調べる。
どうやらAndroid4.0でもいけるっぽい? ソースコードぱっと見アウトに思えたけど、API14エミュで動いた。

最後に、例に挙げているjp.co.noxi.weathernow.Commonは実際のアプリには存在しないクラスです。