Stuff you should know about Android

Basics
Challenges
Techniques

Basics

Basic elements

  • Activity
  • Intent
  • Context
  • Layout
  • Manifest

There is more...

  • Service
  • Multimedia
  • User info & location
  • User input
  • Content sharing
  • Performance
  • Google Cloud Messaging
  • Hardware components
  • User Interface
  • Testing
  • Distribution

...and bleeding edge stuff

  • Android Studio (still) beta
  • Android L
  • Wearables
  • Google TV
  • Google Glass
  • Android Auto

Activity Lifecycle

Intent intent = new Intent(this, MyActivity.class);
startActivity(intent);

Starting Activity with an Intent

from Context of another activity

Android Context

Context of the Activity

Context of the Application

public class MyActivity extends Activity {
    public void showMyToast() {
        Toast.makeText(this, "I am toast!", Toast.LENGTH_SHORT).show();
    }
}
// Assuming, we have created BaseApplication class extending Application class
Resources resources = BaseApplication.getInstance().getResources();
String myString = resources.getString(R.string.my_string);

We should use it in operations related to Activity and UI

<!-- part of AndroidManifest.xml file -->
<application android:name="com.app.BaseApplication">

We should use it while accessing elements related to whole application and global elements

View

LinearLayout

RelativeLayout

TextView, Button, EditText, CheckBox, RadioButton, ImageView, GridView, ListView, ProgressBar and many more...

We can also create our own custom views!

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >
    <TextView android:id="@+id/text"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Hello, I am a TextView" />
    <Button android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello, I am a Button" />
</LinearLayout>
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_layout);
}

Exemplary

Layout

Layout initialization

in Activity

res/layout/main_layout.xml

Android Manifest

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="string"
          android:versionCode="integer"
          android:versionName="string"
          android:installLocation=["auto" | "internalOnly" | "preferExternal"] >

 <uses-permission />
    <permission />
    <uses-sdk />
    <supports-screens />  
    <compatible-screens />

    <application>
        <activity></activity>       
        <service></service>
        <receiver></receiver>
        <provider></provider>
    </application>

</manifest>

Describes application

package, version, SDK, activities, services, receivers, providers, etc.

AndroidManifest.xml syntax with the most important features

Challenges

Challenges

  • Efficient communication with RESTful APIs
  • Managing complicated application flow
  • Asynchronous operations
  • Handling events
  • Injecting views
  • Loading images
  • Long running operations
  • Queuing operations
  • Choosing build system
  • Ustable version of Android Studio
  • Testing
  • and more...

Techniques

Using RESTful API

public interface GitHubService {
  @GET("/users/{user}/repos")
  List<Repo> listRepos(@Path("user") String user);
}
RestAdapter restAdapter = new RestAdapter.Builder()
    .setEndpoint("https://api.github.com")
    .build();

GitHubService service = restAdapter.create(GitHubService.class);

List<Repo> repos = service.listRepos("octocat");

Handling complicated application flow

Dealing with many scenarios and many conditions

  • Creating so called NavigationDispatcher
  • Defining flow steps in JSON file
  • Flow steps objects are created with Java reflection
  • GSON library is used for transforming JSON data into objects
  • Single step consists of: originatingContextactionfactories.

Profits?

  • we have defined application flow in a single file
  • we can generate application flow diagram! (e.g. with JavaScript)

Approach

Asynchronous operations

Problem

  • We send request
  • We don't know, when will we receive the response

Approach #1

AsyncTask and Callback

Approach #2

How about events?

tight coupling

loose coupling

Bus bus = new Bus();
bus.post(new AnswerAvailableEvent(42));

@Subscribe 
public void answerAvailable(AnswerAvailableEvent event) {
    // TODO: React to the event somehow!
}

Interesting applications of EventBus

Micro-location using WiFi Access Points

  1. map MAC addresses of APs into locations
  2. monitor WiFi state with BroadcastReceiver
  3. send event to bus, when signal strength of WiFi APs was changed
  4. react on event
  5. select known APs from list of available APs
  6. choose AP with the strongest signal
  7. determine and display approximate location

Check out open-source library:  

https://github.com/pwittchen/NetworkEvents (still under development)

Injecting views

class ExampleActivity extends Activity {
  @InjectView(R.id.title) TextView title;
  @InjectView(R.id.subtitle) TextView subtitle;
  @InjectView(R.id.footer) TextView footer;

  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.simple_activity);
    ButterKnife.inject(this);
    // TODO Use "injected" views...
  }
}
public void inject(ExampleActivity activity) {
  activity.subtitle = (android.widget.TextView) activity.findViewById(2130968578);
  activity.footer = (android.widget.TextView) activity.findViewById(2130968579);
  activity.title = (android.widget.TextView) activity.findViewById(2130968577);
}

This code:

will generate this code (instead of using slow reflection):

Dependency Injection

  • is popular
  • used by well known apps (e.g. Facebook Messanger)
  • easy to use
  • has many features
  • is slow, because uses reflection
  • is less popular
  • does not have all features of RoboGuice
  • is fast, due to compile-time code generation

In mobile applications development Dagger would be a better choice as DI framework, because in this case, speed matters.

Downloading and caching images


Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);

Long running operations

Service

IntentService

<manifest ... >
  <application ... >
      <service 
         android:name=".HelloService" />
  </application>
</manifest>
public class HelloIntentService extends IntentService {
  public HelloIntentService() {
      super("HelloIntentService");
  }

  @Override
  protected void onHandleIntent(Intent intent) {
    // start executing operation here
  }
}
public class HelloService extends Service {
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // start executing operations here
        return super.onStartCommand(intent,flags,startId);
    }
}

HelloService.java

HelloIntentService.java

AndroidManifest.xml

Queuing operations

public class MyJob extends Job {
    public static final int PRIORITY = 1;
    private String message;
    public MyJob(String message) {
        super(new Params(PRIORITY).requireNetwork().persist());
        this.message = message;
    }
    @Override
    public void onAdded() {}
    @Override
    public void onRun() throws Throwable {}
    @Override
    protected boolean shouldReRunOnThrowable(Throwable throwable) {}
    @Override
    protected void onCancel() {}
}

jobManager.addJobInBackground(new MyJob("message for a job"));

Defining job

Adding job to queue

available in Android L (API 20)

Android L is not officially released yet

and will be released later this year

JobInfo uploadTask = new JobInfo.Builder(mJobId, mServiceComponent)
        .setRequiredNetworkCapabilities(JobInfo.NetworkType.UNMETERED)
        .build();

JobScheduler jobScheduler = 
(JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE)
jobScheduler.schedule(uploadTask);

Thank you for attention!

Any questions?

piotr@wittchen.biz.pl

pwittchen@future-processing.com

Made with Slides.com