daggerサンプルコードの最初から、メソッドなどの関係が分からなかったので、理解しようと頑張った
なんとなく勉強会などで説明を聞いていて
DIとかよりまず処理の流れがよく分かっていませんでした。。
@Moduleのついているクラス@Providesがついているメソッドを使うと@Injectのところに入れてくれるとかは聞いていた
public class MainActivity extends Activity{ @Inject Test test; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); ObjectGraph.create(new TestModule()).inject(this); } } @Module(injects = MainActivity.class) public class TestModule { @Provides Test provideTest() { return new Test(); } }
こんなイメージだった
これだとMainActivity.testに入れる変数をTestModuleから提供される感じだった
そんな感じで公式のdaggerのサンプルを読もうとした
サンプルコードの最初はこういう感じ
public class CoffeeApp implements Runnable { @Inject CoffeeMaker coffeeMaker; @Override public void run() { coffeeMaker.brew(); } public static void main(String[] args) { ObjectGraph objectGraph = ObjectGraph.create(new DripCoffeeModule()); CoffeeApp coffeeApp = objectGraph.get(CoffeeApp.class); coffeeApp.run(); } }
このmainを実行する
CoffeeMakerはこうなっている
class CoffeeMaker { @Inject Lazy<Heater> heater; // Don't want to create a possibly costly heater until we need it. @Inject Pump pump; public void brew() { heater.get().on(); pump.pump(); System.out.println(" [_]P coffee! [_]P "); heater.get().off(); } }
普通に考えるのがDripCoffeeModuleの中に、CoffeeApp.coffeeMakerに変数を入れる@Providesが書いてあるとか思うでしょう?
でも
@Module( injects = CoffeeApp.class, includes = PumpModule.class ) public class DripCoffeeModule { @Provides @Singleton Heater provideHeater() { return new ElectricHeater(); } }
Heaterなどは提供してくれる処理があるけど、 PumpModuleなどをたどっていってもCoffeeMakerを提供してくれる処理はないです
daggerはInjectって書いてあるところのクラスを勝手にnewして入れてくれるっぽいです。
つまりdaggerはobjectGraph.getや@Providesが付いているメソッドの引数などでオブジェクトが必要になったタイミングで以下のように動くみたいです
if @Moduleが付いているクラス and @Providerの付いている返り値がCoffeeAppのメソッドがある: それを使って作る else if CoffeeAppに@Injectが付いているコンストラクタがある: それを使って作る else : new CoffeeApp();#(CoffeeAppのクラスの中には@Injectがついているメンバ変数を含んで、injects=CoffeeApp.classのModuleが必要)
こんなイメージです
サンプルコード
public class MyActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); ObjectGraph.create(new TestModule()).get(Test.class).hello(); } } @Module(injects = Test.class) public class TestModule { @Provides public SayHello provideSayHello() { return new SayHello(); } } public class Test { public Test(){ System.out.println("Test created"); } @Inject SayHello sayHello; public void hello(){ sayHello.hello(); } } public class SayHello { void hello(){ System.out.println("hello"); } }
Test created hello
間違いなどがありましたらご指摘ください
AndroidWearかどうかを判定する
ライブラリを作っている時に、AndroidのスマホかAndroidWearかどうしても判定したい時があって、
どうすればいいのかわからなかったので、考えました(いい方法があったら教えて下さい)
WebViewのパッケージがないことを思い出してそれを判定するとか考えたりしましたが、何か微妙なので、、、
adb shell cat system/build.prop
して
ro.build.characteristics=nosdcard,watch
を発見したので、watchが含まれていることを利用する方法でやることにしました
build.propの中を見るにはSystemPropertiesを利用する必要があり、そのためにはリフレクションが必要だったので、それを使う方法でやりました
こんなかんじです
他にいい方法があればお教え下さい
Androidライブラリプロジェクト(aar)のファイルを直接読み込む
mavencentralにいつかは公開したいけど、まだそこまで行っていないライブラリのファイル(aar)ってありますよね?
そんなときに直接読み込む方法がわからなかったので
ライブラリの方のbuild.gradleはapply plugin: 'com.android.application'をapply plugin: 'android-library'に変えたらなんとかなったけど、
アプリの方は、、
こんなかんじです
Androidライブラリプロジェクト(aar)のファイルを直接読み込む
これで重要なのは
repositories {
mavenCentral()
flatDir {
dirs '../../WearHttp/mobile/build/outputs/aar'
}
}
ここのdirでaarがあるフォルダを指定して、
compile(name:'mobile', ext:'aar')
で実際に読み込んでいます
Androidアプリで初回だけ○○したいというのを簡潔に実装したい
普通に実装すると
こんなかんじになると思う
だけどこういうのを機能を追加するたびに書いていたら苦しい
とりあえずクラスに分けたりすればそれは若干よくなるが、それでも微妙
なので
FirstTimePreferenceというクラスを使って初回だけ○○したいを実現する
こんなかんじでかけたらいい感じなんじゃないだろうか
(Javaの無名クラスの書き方は微妙だが)
ということで作った
Android Wearでスマホからアプリ起動時に、Wearでアプリを起動する方法
Android Wearのアプリってなんなの?Android内にあるアプリとの関係は? - tmenのブログのmobileでリリースビルドにしている必要があります
Wear対応アプリをスマホでアプリ起動時に、WearでActivityを開始する
解説
mobile/MainActiivty.javaで
ノード一覧を取得(つながっているデバイス一覧?)
そして、それぞれのノードに対して、Wearable.MessageApi.sendMessageします。
するとwear/AndroidManifest.xmlにACTIONがBIND_LISTENERで宣言されている、WearableListenerServiceを継承したクラスのonMessageRecievedが呼ばれるので、そこでWearのActivityを起動してあげましょう!
Android Wearのアプリってなんなの?Android内にあるアプリとの関係は?
よく分かっていなかったのですが、少しずつ分かってきました
Android StudioでAndroid Wear向けのアプリを作ろうとすると
MobileとWearディレクトリが作られます。
そして、Android Studioで普通にデバッグビルドしているとそれぞれ片方のみのapkが作られます
MobileならMobile用で、Wear向けのアプリを含みません(本当に合ってるかわからないですが、入っていかない?)
WearむけならWear向けのみです。
しかし Mobile向けのbuild.gradleに以下の設定を追加して、
dependencies {
compile 'com.google.android.gms:play-services:5.0.+@aar'
compile 'com.android.support:support-v4:20.0.+''
wearApp project(':wearable')
}
Mobileをリリースビルドして、携帯端末にインストールすると、、、
Wear端末にアプリがインストールされます!!!
つまりリリースビルドされたMobile向けのapkにはWear向けのアプリが含まれているようです!!
これで前回の記事
Android Wear向けのアプリがリリースできない!!と思ったらできる!? - tmenのブログ
を解決して、リリースできました!!
Android Wear向けのアプリがリリースできない!!と思ったらできる!?
アップロードできませんでした
バージョン番号が 19 以下の SDK を使用する必要があります。
だそうです。。。
そしてminSDKを19にするとこう怒られる
Error:Execution failed for task ':wear:processDebugManifest'.
> Manifest merger failed : uses-sdk:minSdkVersion 19 cannot be smaller than version 20 declared in library com.google.android.support:wearable:1.0.0
自分が1日で作ったアプリがリリースできない。。。
無念。。。
と思っていたのですが、
https://developer.android.com/training/wearables/apps/packaging.html
を読んだら、、という話