Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
Android Infrastructure Overview
Alexey Buzdin
April 24, 2013
Programming
2
620
Android Infrastructure Overview
Alexey Buzdin
April 24, 2013
Tweet
Share
More Decks by Alexey Buzdin
See All by Alexey Buzdin
Make you Gadget Talk: Google Assistant
larchaon
0
65
Writing A Plugin for Android Studio
larchaon
1
78
Marvel of Annotation Processing in Java Mobius 2017
larchaon
0
98
How to Become a Successful Programmer
larchaon
0
56
Kotlin JS: Is it a Thing?
larchaon
0
150
Marvel of Annotations in Java/Android
larchaon
0
67
Testing RESTful services: GoT JavaDay Kiev Edition
larchaon
0
56
Automate the Mobile
larchaon
0
160
Google I/O 2016 Retrospective
larchaon
0
63
Other Decks in Programming
See All in Programming
OSC大阪 パスワード認証は人類には早すぎる ~ IDaaSを使ったソーシャルログインのすすめ ~
authyasan
7
1.4k
はてなリモートインターンシップ2022 フロントエンドブートキャンプ 講義資料
hatena
0
120
まだ日本国内で利用できないAppActionsにトライしてみた / MoT TechTalk #15
mot_techtalk
0
110
和暦を正しく扱うための暦の話
nagise
10
6k
An Advanced Introduction to R
nicetak
0
1.8k
OSSから学んだPR Descriptionの書き方
fugakkbn
4
130
Rによる大規模データの処理
s_uryu
2
630
WordPress(再)入門 - 基礎知識・環境編
oleindesign
1
130
Swift Observation
shiz
3
280
監視せなあかんし、五大紙だけにオオカミってな🐺🐺🐺🐺🐺
sadnessojisan
2
1.5k
ペパカレで入社した私が感じた2つのギャップと向き合い方
kosuke_ito
0
260
あなたと 「|」 したい・・・
track3jyo
PRO
2
1.1k
Featured
See All Featured
Practical Orchestrator
shlominoach
178
8.9k
Bash Introduction
62gerente
601
210k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
351
21k
Six Lessons from altMBA
skipperchong
15
2.3k
VelocityConf: Rendering Performance Case Studies
addyosmani
317
22k
10 Git Anti Patterns You Should be Aware of
lemiorhan
643
54k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
109
16k
Atom: Resistance is Futile
akmur
256
24k
What's new in Ruby 2.0
geeforr
336
30k
Become a Pro
speakerdeck
PRO
6
3.2k
Three Pipe Problems
jasonvnalue
89
8.9k
Facilitating Awesome Meetings
lara
33
4.6k
Transcript
Overview of Android Infrastructure Alexey Buzdin March 2013
@AlexeyBuzdin! ! !
[email protected]
! ! ! LArchaon!
Everyone needs an app....
we need an app too!
Simple CRUD app
Requirement:! ! Support as many android devices as you can!
(phones + tablets)
4.0 4.1–4.2 3.0 2.3 2.2 2.1 Google data, March 2013
None
Ain't that good for a developer
None
None
None
Is there is someone who could solve this?
nope
Ease our pain?
maybe
None
None
Layers Presentation ! Application logic ! Domain Presentation ! Application
logic ! Domain
Presentation ! Application logic ! Domain Presentation ! Application logic
! Domain
Spot the problem
Missing in Android 2.2 • ActionBar! • Fragments (used for
both tablets and phone support)
Solution?
Compatibility libraries Android Support library! ActionBarSherlock! etc
Support Library http://developer.android.com/tools/extras/ support-library.html ! Fragments! Async Stuff! Experimental stuff
Fragments
Example
ActionBar
ActionBarSherlock http://actionbarsherlock.com/
Refreshing list
Pull to Refresh https://github.com/chrisbanes/ Android-PullToRefresh
Presentation ! Application logic ! Domain Presentation ! Application logic
! Domain
Android Runtime On Android you develop in Java ... but
Android does not run Java bytecode !
DalvikVM Dalvik Virtual Machine − Custom VM optimized for mobile
devices − Register-based JVM − More efficient and compact − Use memory efficiently − Dalvik Executable Code (.dex) • 30% fewer instructions • 35% fewer code units • 35% more bytes − Trace JIT compiler (since 2.2)
!35 Android Runtime Android Java = Java language + Dalvik
+ Apache Harmony Android Java API = Java SE – AWT/Swing + Android API Sun-Java = Java language + JVM + JDK
App lifecycle
Activity public class MyActivity extends Activity { ! @Override public
void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } ! }
None
Activity public class MyActivity extends Activity { ! @Override public
void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } ! }
Resources
Activity public class MyActivity extends Activity { ! @Override public
void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } ! }
Context • Context of current state of the application/object
Context • Context of current state of the application/object! •
Context is a handle to the system it provides services like ! − resolving resources ! − obtaining access to databases and preferences
Important any resource taken from context will live as long
as Context does
Context problem public class MyActivity extends Activity { ! @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); String appName = getString(R.string.appName); } ! }
Passing Context public class MyStringProvider { ! Context context; !
public MyStringProvider(Context context) { this.context = context; } ! public String getString(){ return context.getString(R.string.app_name); } ! }
Passing Context
Context problem public class MyActivity extends Activity { ! @Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); String appName = getString(R.string.appName); } ! } Presentation ! Application logic ! Domain Presentation ! Application logic ! Domain
Injection libraries Dependency Injection! • RoboGuice! • Dagger
RoboGuice • Based on Google Guice! • Lightweight! • Multifunctional
(has resource injection)
RoboGuice public class MyActivity extends RoboActivity { ! @Inject MyStringProvider
stringProvider; ! @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ! ((TextView) findViewById(R.id.textView)) .setText(stringProvider.getString()); } ! }
RoboGuice public class MyStringProvider { ! Context context; ! @Inject
public MyStringProvider(Context context) { this.context = context; } ! public String getString(){ return context.getString(R.string.app_name); } }
Notable fact
Minimal context injection public class MyActivity extends RoboActivity { !
int i; ! @Inject MyStringProvider stringProvider; ! @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ! i = 1; ((TextView) findViewById(R.id.textView)) .setText(stringProvider.getString()); } ! }
RoboGuice public class MyStringProvider { ! Context context; ! @Inject
public MyStringProvider(Context context) { this.context = context; } ! public String getString(){ return context.getString(R.string.app_name) + ((MyActivity)context).i; } }
Dagger public class DaggerActivity extends DaggerBaseActivity { ! @Inject DaggerStringProvider
stringProvider; ! @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ! ((TextView) findViewById(R.id.textView)) .setText(stringProvider.getString()); } ! }
Dagger public class DaggerBaseActivity extends Activity { ! @Inject Bus
bus; ! @Override protected void onCreate(Bundle state) { super.onCreate(state); ! DaggerApplication.inject(this); } ! @Override protected void onResume() { super.onResume(); bus.register(this); } ! @Override protected void onPause() { super.onPause(); bus.unregister(this); } }
Dagger public class DaggerApplication extends Application { ! private static
ObjectGraph objectGraph; ! @Override public void onCreate() { super.onCreate(); ! objectGraph = ObjectGraph.create(new DaggerModule(this)); } ! public static <T> void inject(T instance) { if(objectGraph != null) objectGraph.inject(instance); } }
@Module( entryPoints = { DaggerApplication.class, DaggerActivity.class} ) public class DaggerModule
{ private final Context appContext; ! public DaggerModule(Context appContext) { this.appContext = appContext.getApplicationContext(); } ! @Provides @Singleton Bus provideBus() { return new Bus(); } ! @Provides Context provideContext() { return appContext; } ! }
Summary Dagger ! • More customizable! • Compile time injection!
• Easy to use with other libraries! • Requires more code! ! RoboGuice! • Simpler! • Runtime injection! • Out of Box functionality
Problem with views
None
None
Other “Injection” libraries Resource and View “Injection”! • RoboGuice! •
ButterKnife! • AndroidAnnotations
RoboGuice Views Injection public class RoboGuiceActivity extends RoboActivity { !
! @Inject RoboGuiceStringProvider stringProvider; @InjectView(R.id.textView) TextView textView; ! @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ! textView.setText(stringProvider.getString()); } ! }
Butterknife public class DaggerActivity extends DaggerBaseActivity {! ! @Inject DaggerStringProvider
stringProvider;! @InjectView(R.id.textView) TextView textView;! ! @Override! public void onCreate(Bundle savedInstanceState) {! super.onCreate(savedInstanceState);! setContentView(R.layout.main);! Views.inject(this);! ! textView.setText(stringProvider.getString());! }! ! }
AndroidAnnotations @EActivity(R.layout.translate) // Sets content view to R.layout.translate! public class
TranslateActivity extends Activity {! @ViewById // Injects R.id.textInput! EditText textInput;! @ViewById(R.id.myTextView) // Injects R.id.myTextView! TextView result;! @AnimationRes // Injects android.R.anim.fade_in! Animation fadeIn;! @Click // When R.id.doTranslate button is clicked ! void doTranslate() {! translateInBackground(textInput.getText().toString());! }! @Background // Executed in a background thread! void translateInBackground(String textToTranslate) {! String translatedText = callGoogleTranslate(textToTranslate);! showResult(translatedText);! }! ! @UiThread // Executed in the ui thread! void showResult(String translatedText) {! result.setText(translatedText);! result.startAnimation(fadeIn);! } ! }
Presentation ! Application logic ! Domain Presentation ! Application logic
! Domain
Data Source Android has built in SQLite
Data Source ... but lacks ORM! ! Alternatives:! − GreenDAO!
− ORMLite
ORMLite @DatabaseTable(tableName = "accounts") public class Account { @DatabaseField(id =
true) private String name; @DatabaseField(canBeNull = false) private String password; Account() { // all persisted classes must define a no-arg constructor with at least package visibility } }
// you get the SQLiteOpenHelper from your Android Activity ConnectionSource
connectionSource = new AndroidConnectionSource(sqliteOpenHelper); ! // instantiate the DAO to handle Account with String id Dao<Account,String> accountDao = BaseDaoImpl.createDao(connectionSource, Account.class); ! TableUtils.createTable(connectionSource, Account.class); ! String name = "Jim Smith"; Account account = new Account(name, "_secret"); accountDao.create(account) ! Account account2 = accountDao.queryForId(name); connectionSource.close(); ORMLite
Testing
Testing • DVM or JVM! • Automation or Unit Tests
DVM • Requires a separate Test Project! • android.test or
Robotium
Android.test public class SimpleActivityTestStandard extends! ActivityUnitTestCase<SimpleActivity> {! public SimpleActivityTestStandard() {!
super(SimpleActivity.class);! }! ! public void setUp() throws Exception {! startActivity(new Intent(getInstrumentation().getTargetContext(),! SimpleActivity.class), null, null);! }! ! ! public void testLayout() {! SimpleActivity activity = getActivity();! assertNotNull(activity.findViewById(R.id.button1));! Button view = (Button) activity! .findViewById(com.example.test.target.R.id.button1);! assertEquals("My Button 1", view.getText());! }! }
Robotium ! public void testPreferenceIsSaved() throws Exception {! ! !
Solo solo = new Solo(getInstrumentation(), getActivity());! solo.sendKey(Solo.MENU);! solo.clickOnText("More");! solo.clickOnText("Preferences");! solo.clickOnText("Edit File Extensions");! assertTrue(solo.searchText("rtf"));! ! solo.clickOnText("txt");! solo.clearEditText(2);! solo.enterText(2, "robotium");! solo.clickOnButton("Save");! solo.goBack();! solo.clickOnText("Edit File Extensions");! ! assertTrue(solo.searchText("application/robotium")! ! ! solo.finishOpenedActivities();! );!
JVM public class RoboGuiceActivityTest { ! @Test public void shouldHaveISet()
throws Exception { RoboGuiceActivity activity = new RoboGuiceActivity(); assertThat(activity.getI(), equalTo(1)); } }
JVM public class RoboGuiceActivityTest { ! @Test public void shouldHaveISet()
throws Exception { RoboGuiceActivity activity = new RoboGuiceActivity(); assertThat(activity.getI(), equalTo(1)); } }
None
We have Mockito! lets mock something in our
Activity ...
Activity source code
Robolectric to the rescue Allows you to run ! you
android code ! on JVM
Robolectric @RunWith(RobolectricRoboTestRunner.class) public class RoboGuiceActivityTest { ! @Test public void
shouldHaveISet() throws Exception { RoboGuiceActivity activity = new RoboGuiceActivity(); activity.onCreate(null); assertThat(activity.getI(), equalTo(1)); } }
Robolectric + Mockito
Testing • DVM or JVM! • Automation or Unit Tests!
• Robotium or Robolectric! • Or both
Conclusion
More libraries?
More libraries
Solution?
Android Bootstrap • Fragments,Fragment Pager! • android-maven-plugin, Dagger! • ActionBarSherlock
! • ViewPagerIndicator! • http-request, GSON ! • Robotium http://www.androidbootstrap.com/
Build Systems • Gradle • Maven ! https://github.com/LArchaon/ android_mvn_template/
Q&A