Overview of Android Infrastructure

  • Published on
    15-Feb-2017

  • View
    314

  • Download
    0

Embed Size (px)

Transcript

  • Overview of Android Infrastructure

    Alexey Buzdin

  • @AlexeyBuzdin

    alex.buzdin@gmail.com

    LArchaon

  • Everyone needs an app....

  • We need an app too!

  • simple CRUD app

  • Requirement:Support as many android

    devices as you can(including tablets)

  • 4.0 4.14.2

    3.0

    2.3

    2.22.1

    Google data, March 2013

  • Ain't that good for a developer

  • Is there is someone who could help us?

  • nope

  • Ease our pain

  • maybe

  • Layers

    Presentation

    Application logic

    Domain

    Presentation

    Application logic

    Domain

  • Presentation

    Application logic

    Domain

    Presentation

    Application logic

    Domain

  • But Whers the problem?

  • Missing in Android 2.2

    ActionBar Support for tablets Decent ListView support for server communication

  • Solution?

  • Compatability libraries

    Android Support library

    ActionBarSherlock

    etc

  • Support Libraryhttp://developer.android.com/tools/extras/support-library.html

    Fragments

    Async Stuff

    Experimental stuff

    http://developer.android.com/tools/extras/support-library.htmlhttp://developer.android.com/tools/extras/support-library.html

  • Fragments

  • Example

  • ActionBar

  • ActionBarSherlock

    http://actionbarsherlock.com/

    http://actionbarsherlock.com/

  • Refreshing list

  • Pull to Refresh

    https://github.com/chrisbanes/Android-PullToRefresh

    https://github.com/chrisbanes/Android-PullToRefreshhttps://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)

  • 36

    Android RuntimeAndroid 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); }

    }

  • 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 leave as long as Context does

  • Context problempublic class MyActivity extends Activity {

    @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); String appName = getString(R.string.appName); }

    }

  • Passing Contextpublic class MyStringProvider {

    Context context;

    public MyStringProvider(Context context) { this.context = context; }

    public String getString(){ return context.getString(R.string.app_name); }

    }

  • Passing Context

  • Context problempublic 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)

  • RoboGuicepublic 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()); }

    }

  • RoboGuicepublic class MyStringProvider {

    Context context;

    @Inject public MyStringProvider(Context context) { this.context = context; }

    public String getString(){ return context.getString(R.string.app_name); }}

  • Notable fact

  • Optimezed context injectionpublic 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()); }

    }

  • RoboGuicepublic 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; }}

  • Daggerpublic 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());

    }

    }

  • Daggerpublic 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); }}

  • Daggerpublic class DaggerApplication extends Application {

    private static ObjectGraph objectGraph;

    @Override public void onCreate() { super.onCreate();

    objectGraph = ObjectGraph.create(new DaggerModule(this)); }

    public static 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; }

    }

  • SummaryDagger

    More customizable Easy communicates with other libraries Requires more code

    RoboGuice Simpler Out of Box functionality

  • Problem with views

  • Other Injection libraries

    Resource and View Injection RoboGuice ButterKnife AndroidAnnotations

  • RoboGuice Views Injectionpublic 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()); }

    }

  • Butterknifepublic 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.translatepublic 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 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.testpublic class SimpleActivityTestStandard extends ActivityUnitTestCase { 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();

    );

  • JVMpublic class RoboGuiceActivityTest {

    @Test public void shouldHaveISet() throws Exception { RoboGuiceActivity activity = new RoboGuiceActivity(); assertThat(activity.getI(), equalTo(1)); }}

  • JVMpublic class RoboGuiceActivityTest {

    @Test public void shouldHaveISet() throws Exception { RoboGuiceActivity activity = new RoboGuiceActivity(); assertThat(activity.getI(), equalTo(1)); }}

  • 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/

    http://www.androidbootstrap.com/

  • or customs scripts

  • Build Systems Gradle Maven

    https://github.com/LArchaon/android_mvn_template/

    https://github.com/LArchaon/android_mvn_template/https://github.com/LArchaon/android_mvn_template/

  • Questions?

    Slide 1Slide 2Slide 3Slide 4Slide 5Slide 6Slide 7Slide 8Slide 9Slide 10Slide 11Slide 12Slide 13Slide 14Slide 15Slide 16Slide 17Slide 18Slide 19Slide 20Slide 21Slide 22Slide 23Slide 24Slide 25Slide 26Slide 27Slide 28Slide 29Slide 30Slide 31Slide 32Slide 33Slide 34Slide 35Slide 36Slide 37Slide 38Slide 39Slide 40Slide 41Slide 42Slide 43Slide 44Slide 45Slide 46Slide 47Slide 48Slide 49Slide 50Slide 51Slide 52Slide 53Slide 54Slide 55Slide 56Slide 57Slide 58Slide 59Slide 60Slide 61Slide 62Slide 63Slide 64Slide 65Slide 66Slide 67Slide 68Slide 69Slide 70Slide 71Slide 72Slide 73Slide 74Slide 75Slide 76Slide 77Slide 78Slide 79Slide 80Slide 81Slide 82Slide 83Slide 84Slide 85Slide 86Slide 87Slide 88Slide 89Slide 90Slide 91Slide 92Slide 93Slide 94Slide 95