Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Android Infrastructure Overview
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Alexey Buzdin
April 24, 2013
Programming
690
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Android Infrastructure Overview
Alexey Buzdin
April 24, 2013
More Decks by Alexey Buzdin
See All by Alexey Buzdin
Make you Gadget Talk: Google Assistant
larchaon
0
110
Writing A Plugin for Android Studio
larchaon
1
120
Marvel of Annotation Processing in Java Mobius 2017
larchaon
0
170
How to Become a Successful Programmer
larchaon
0
120
Kotlin JS: Is it a Thing?
larchaon
0
210
Marvel of Annotations in Java/Android
larchaon
0
130
Testing RESTful services: GoT JavaDay Kiev Edition
larchaon
0
130
Automate the Mobile
larchaon
0
230
Google I/O 2016 Retrospective
larchaon
0
88
Other Decks in Programming
See All in Programming
Composerを使ったサプライチェーン攻撃の様子を眺めてみる #phpstudy
o0h
PRO
2
240
LLM本来の能力を解き放つサンドボックス技術とAI民主化への適用
yukukotani
3
3.6k
LLMによるContent Moderationの本番運用の裏側と品質担保への挑戦
suikabar
2
510
Observability in Practice:Grafana 與 Edge Device SRE 的那些事
blueswen
0
160
Javaの型とAI時代に型が大事な理由 / java types and type in AI era
kishida
2
120
Old Dog, New Tricks: The Java 25 Reinvention - JNation
bazlur_rahman
0
150
並列実装の現場、2ヶ月間実務でAIを使い倒したAIもPCも私も限界が近い
ming_ayami
0
120
「エンジニアインターン、どうやって取った?」準備のリアルを語るLT会 Progate BAR
akiomatic
0
130
New "Type" system on PicoRuby
pocke
1
810
Vue × Nuxt × Oxc どこまで使える?実運用の現在地
andpad
0
160
気づいたらRubyで100作品 ー クリエイティブコーディングが生活の一部になるまで / 100 Ruby Sketches Later: How Creative Coding Became Part of My Life
chobishiba
3
560
OSもどきOS
arkw
0
480
Featured
See All Featured
Music & Morning Musume
bryan
47
7.2k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
320
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
600
Building Applications with DynamoDB
mza
96
7.1k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
231
23k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Building an army of robots
kneath
306
46k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
170
YesSQL, Process and Tooling at Scale
rocio
174
15k
Tell your own story through comics
letsgokoyo
1
950
How to build a perfect <img>
jonoalderson
1
5.6k
For a Future-Friendly Web
brad_frost
183
10k
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