Android dev toolbox AVGeeks, 2015
Android dev toolboxAVGeeks, 2015
Shem Magnezi@shemag8 | shem8.wordpress.com
Part 1 Libraries
Why use external libraries?
▣Let others speed up your development▣Code that is heavily
used▣Small hidden bugs /
case you didn’t think of▣Help others
Why not?
▣Legal issues▣Old/ buggy code▣Your core functions
1.Basics
Support Library & Design Support Libraryset of code libraries that provide backward-compatible versions of Android framework APIs as well as features
that are only available through the library APIs.
● Fragment
● NotificationCompat
● LocalBroadcastManager
● ViewPager
● PagerTitleStrip
● PagerTabStrip
● DrawerLayout
SlidingPaneLayout
● Navigation View
● Floating labels
● FAB
● Snackbar
● CoordinatorLayout
● Collapsing Toolbars
● ...
Google Play Servicestake advantage of the latest, Google-powered features such as Maps, Google+, and more, with automatic
platform updates distributed as an APK through the Google Play store.
● Google+
● Google Account Login
● Google App Invites
● Google Analytics
● Google Cloud Messaging
● Google Fit
● Google Location
● Google Maps
ParcelerAndroid Parcelables made easy through code generation.
@Parcel
public class Example {
String name;
int age;
public Example(){ /*Required empty bean constructor*/ }
public Example(int age, String name) {
this.age = age;
this.name = name;
}
public String getName() { return name; }
public int getAge() { return age; }
}
Bundle bundle = new Bundle();
bundle.putParcelable("example", Parcels.wrap(example));
Example example = Parcels.unwrap(this.getIntent().getParcelableExtra("example"));
http://square.github.io/picasso/
IcepickAndroid library that eliminates the boilerplate of saving and restoring instance state.
class ExampleActivity extends Activity {
@State String username; // This will be automatically saved and restored
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Icepick.restoreInstanceState(this, savedInstanceState);
}
@Override public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Icepick.saveInstanceState(this, outState);
}
}
https://github.com/frankiesardo/icepick
Joda timeJoda-Time is the widely used replacement for the Java date and time classes.
public boolean isAfterPayDay(DateTime datetime) {
if (datetime.getMonthOfYear() == 2) { // February is month 2!!
return datetime.getDayOfMonth() > 26;
}
return datetime.getDayOfMonth() > 28;
}
public Days daysToNewYear(LocalDate fromDate) {
LocalDate newYear = fromDate.plusYears(1).withDayOfYear(1);
return Days.daysBetween(fromDate, newYear);
}
public boolean isRentalOverdue(DateTime datetimeRented) {
Period rentalPeriod = new Period().withDays(2).withHours(12);
return datetimeRented.plus(rentalPeriod).isBeforeNow();
}
public String getBirthMonthText(LocalDate dateOfBirth) {
return dateOfBirth.monthOfYear().getAsText(Locale.ENGLISH);
}
https://github.com/JodaOrg/joda-time
GuavaGoogle core libraries for Java 6+
@Override public String toString() {
return Objects.toStringHelper(this)
.add("name", name)
.add("nickname", nickname)
.add("favMovie", favMovie)
.toString();
}
public String preferredName() {
return Objects.firstNonNull(nickname, name);
}
String seriesId =
CharMatcher.DIGIT.or(CharMatcher.is('-'))
.retainFrom(input);
https://github.com/google/guava
2.Network
GsonConvert Java Objects into their JSON representation
Albums albums = new Albums();
albums.title = "Free Music Archive - Albums";
albums.message = "";
albums.total = "11259";
albums.total_pages = 2252;
albums.page = 1;
albums.limit = "5";
GsonBuilder builder = new GsonBuilder();
Gson gson = builder.create();
System.out.println(gson.toJson(albums));
System.out.println(gson.fromJson(gson.toJson(albums)));
https://github.com/google/gson
JacksonMulti-purpose Java library for processing JSON data format. Jackson aims to be the best possible combination
of fast, correct, lightweight, and ergonomic for developers.
JsonFactory jsonFactory = new JsonFactory(); // or, for data binding,
org.codehaus.jackson.mapper.MappingJsonFactory
JsonGenerator jg = jsonFactory.createJsonGenerator(file, JsonEncoding.UTF8); // or Stream, Reader
TokenBuffer buffer = new TokenBuffer();
// serialize object as JSON tokens (but don't serialize as JSON text!)
objectMapper.writeValue(buffer, myBean);
// read back as tree
JsonNode root = objectMapper.readTree(buffer.asParser());
// modify some more, write out
String jsonText = objectMapper.writeValueAsString(root);
https://github.com/FasterXML/jackson
VolleyVolley is an HTTP library that makes networking for Android apps easier and most importantly, faster.
RequestQueue queue = Volley.newRequestQueue(this);
String url ="http://www.google.com";
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
// Display the first 500 characters of the response string.
mTextView.setText("Response is: "+ response.substring(0,500));
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
mTextView.setText("That didn't work!");
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
http://developer.android.com/training/volley/index.html
OkHttpAn HTTP & SPDY client for Android and Java applications
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
http://square.github.io/okhttp/
FlatBuffersMemory Efficient Serialization Library
ByteBuffer bb = ByteBuffer.wrap(data);
Monster monster = Monster.getRootAsMonster(bb);
short hp = monster.hp();
Vec3 pos = monster.pos();
https://github.com/google/flatbuffers
RetrofitA type-safe HTTP client for Android and Java
public interface GitHubService {
@GET("/users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.build();
GitHubService service = retrofit.create(GitHubService.class);
Call<List<Repo>> repos = service.listRepos("octocat");
http://square.github.io/retrofit/
3.Basics
ORMLiteActiveAndroid allows you to save and retrieve SQLite database records without ever writing a single SQL
statement.
@DatabaseTable(tableName = "accounts")
public class Account {
@DatabaseField(id = true)
private String name;
@DatabaseField(canBeNull = false)
private String password;
}
// create an instance of Account
String name = "Jim Smith";
Account account = new Account(name, "_secret");
// persist the account object to the database
accountDao.create(account);
// retrieve the account
Account account2 = accountDao.queryForId(name);
http://ormlite.com/
ActiveAndroidActiveAndroid allows you to save and retrieve SQLite database records without ever writing a single SQL
statement.
@Table(name = "Categories")
public class Category extends Model {
@Column(name = "Name")
public String name;
}
@Table(name = "Items")
public class Item extends Model {
@Column(name = "Name")
public String name;
@Column(name = "Category")
public Category category;
}
Category restaurants = new Category();
restaurants.name = "Restaurants";
restaurants.save();
new Select()
.from(Item.class)
.where("Category = ?", category.getId())
.orderBy("Name ASC")
.execute();
http://www.activeandroid.com/
GreenDAOgreenDAO is an open source project to help Android developers working with data stored in SQLite.
List joes = userDao.queryBuilder()
.where(Properties.FirstName.eq("Joe"))
.orderAsc(Properties.LastName)
.list();
QueryBuilder<User> queryBuilder = userDao.queryBuilder();
queryBuilder.join(Properties.addressId, Address.class)
.where(AddressDao.Properties.Street.eq("Sesame Street"));
List<User> users = queryBuilder.list();
List orders = customer.getOrders();
daoSession.delete(newOrder);
orders.remove(newOrder);
http://greendao-orm.com/
SquidbSquiDB is a SQLite database layer for Android.
// This is a table schema
@TableModelSpec(className = "Person", tableName = "people")
public class PersonSpec {
public String firstName;
public String lastName;
@ColumnSpec(name = "creationDate")
public long birthday;
}
// This is how you'd work with the generated model
Person newPerson = new Person()
.setFirstName("Sam")
.setLastName("Bosley")
.setBirthday(System.currentTimeMillis());
db.persist(newPerson);
long ageCutoff = System.currentTimeMillis() - (DateUtil.YEAR_IN_MILLIS * 18);
Query peopleWhoCanVote = Query.select().where(Person.BIRTHDAY.lt(ageCutoff));
// This becomes select * from people where people.birthday < ? where ? is the age cutoff arg
SquidCursor<Person> voters = db.query(Person.class, peopleWhoCanVote);
https://github.com/yahoo/squidb
RealmRealm is a mobile database that runs directly inside phones, tablets or wearables
// Define you model class by extending the RealmObject
public class Dog extends RealmObject {
@Required private String name;
private int age;
}
public class Person extends RealmObject {
@Required private String name;
private String imageUrl;
private RealmList<Dog> dogs;
}
// Use them like regular java objects
Dog dog = new Dog();
dog.setName("Rex");
Realm realm = Realm.getInstance(context);
realm.beginTransaction();
realm.copyToRealm(dog);
realm.commitTransaction();
// Get a Realm instance for this thread
Realm realm = Realm.getInstance(context);
Dog dog = realm.where(Dog.class).equalTo("name", "Rex").findFirst();
https://github.com/realm/realm-java
4.Images
Universal image loaderUIL aims to provide a powerful, flexible and highly customizable instrument for image loading, caching and
displaying.
ImageLoader imageLoader = ImageLoader.getInstance(); // Get singleton instance
// Load image, decode it to Bitmap and display Bitmap in ImageView (or any other view
// which implements ImageAware interface)
imageLoader.displayImage(imageUri, imageView);
// Load image, decode it to Bitmap and return Bitmap to callback
imageLoader.loadImage(imageUri, new SimpleImageLoadingListener() {
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
// Do whatever you want with Bitmap
}
});
// Load image, decode it to Bitmap and return Bitmap synchronously
Bitmap bmp = imageLoader.loadImageSync(imageUri);
https://github.com/nostra13/Android-Universal-Image-Loader
PicassoA powerful image downloading and caching library for Android
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
Picasso.with(context)
.load(url)
.resize(50, 50)
.centerCrop()
.into(imageView);
Picasso.with(context)
.load(url)
.placeholder(R.drawable.user_placeholder)
.error(R.drawable.user_placeholder_error)
.into(imageView);
http://square.github.io/picasso/
GlideAn image loading and caching library for Android focused on smooth scrolling
// For a simple view:
@Override
public void onCreate(Bundle savedInstanceState) {
ImageView imageView = (ImageView) findViewById(R.id.my_image_view);
Glide.with(this).load("http://goo.gl/gEgYUd").into(imageView);
}
// For a simple image list:
@Override
public View getView(int position, View recycled, ViewGroup container) {
...
String url = myUrls.get(position);
Glide.with(myFragment)
.load(url)
.centerCrop()
.placeholder(R.drawable.loading_spinner)
.crossFade()
.into(myImageView);
return myImageView;
}
https://github.com/bumptech/glide
5.Utils
EventBussimplifies the communication between components
public class MessageEvent { /* Additional fields if needed */ }
eventBus.register(this);
public void onEvent(AnyEventType event) {/* Do something */};
eventBus.post(event);
http://square.github.io/otto/
OttoOtto is an event bus designed to decouple different parts of your application while still allowing them to
communicate efficiently.
Bus bus = new Bus();
bus.post(new AnswerAvailableEvent(42));
bus.register(this);
@Subscribe
public void answerAvailable(AnswerAvailableEvent event) {
// TODO: React to the event somehow!
}
http://square.github.io/otto/
Dagger 2A fast dependency injector for Android and Java
class Thermosiphon implements Pump {
private final Heater heater;
@Inject
Thermosiphon(Heater heater) {
this.heater = heater;
}
}
class CoffeeMaker {
@Inject Heater heater;
@Inject Pump pump;
}
@Provides Heater provideHeater() {
return new ElectricHeater();
}
CoffeeShop coffeeShop = DaggerCoffeeShop.builder()
.dripCoffeeModule(new DripCoffeeModule())
.build();
http://google.github.io/dagger/
RoboguiceGoogle Guice on Android
@ContentView(R.layout.main)
class RoboWay extends RoboActivity {
@InjectView(R.id.name)
TextView name;
@InjectView(R.id.thumbnail)
ImageView thumbnail;
@InjectResource(R.drawable.icon)
Drawable icon;
@InjectResource(R.string.app_name) String myName;
@Inject
LocationManager loc;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
name.setText( "Hello, " + myName );
}
}
https://github.com/roboguice/roboguice
Butter KnifeField and method binding for Android views
class ExampleActivity extends Activity {
@Bind(R.id.title) TextView title;
@Bind(R.id.subtitle) TextView subtitle;
@Bind(R.id.footer) TextView footer;
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_activity);
ButterKnife.bind(this);
}
@BindString(R.string.title) String title;
@BindDrawable(R.drawable.graphic) Drawable graphic;
@BindColor(R.color.red) int red; // int or ColorStateList field
@BindDimen(R.dimen.spacer) Float spacer; // int (for pixel size) or float (for exact value)
@OnClick(R.id.submit)
public void submit(View view) {
// TODO submit data to server...
}
}
http://jakewharton.github.io/butterknife/
AndroidAnnotationsan Open Source framework that speeds up Android development. It takes care of the plumbing, and lets you
concentrate on what's really important.
@EActivity(R.layout.translate) // Sets content view to R.layout.translate
public class TranslateActivity extends Activity {
@ViewById EditText textInput; // Injects R.id.textInput
@ViewById(R.id.myTextView) TextView result; // Injects R.id.myTextView
@AnimationRes Animation fadeIn; // Injects android.R.anim.fade_in
@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);
}
}
https://github.com/excilys/androidannotations
NineOldAndroidsAndroid library for using the Honeycomb (Android 3.0) animation API on all versions of the platform back to 1.0!
ObjectAnimator.ofFloat(myObject, "translationY", -myObject.getHeight()).start();
ValueAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor",0xFFFF8080, 0xFF8080FF);
colorAnim.setEvaluator(new ArgbEvaluator());
colorAnim.setRepeatCount(ValueAnimator.INFINITE);
colorAnim.setRepeatMode(ValueAnimator.REVERSE);
colorAnim.start();
AnimatorSet set = new AnimatorSet();
set.playTogether(
ObjectAnimator.ofFloat(myView, "rotationX", 0, 360),
ObjectAnimator.ofFloat(myView, "rotationY", 0, 180),
ObjectAnimator.ofFloat(myView, "rotation", 0, -90),
ObjectAnimator.ofFloat(myView, "translationX", 0, 90),
ObjectAnimator.ofFloat(myView, "translationY", 0, 90),
ObjectAnimator.ofFloat(myView, "scaleX", 1, 1.5f),
ObjectAnimator.ofFloat(myView, "scaleY", 1, 0.5f),
ObjectAnimator.ofFloat(myView, "alpha", 1, 0.25f, 1)
);
set.setDuration(5 * 1000).start();
animate(myButton).setDuration(2000).rotationYBy(720).x(100).y(100);
http://nineoldandroids.com/
Priority Jobqueue A Job Queue specifically written for Android to easily schedule jobs (tasks) that run in the background, improving
UX and application stability.
jobManager.addJobInBackground(new PostTweetJob(status));
public class PostTweetJob extends Job {
public static final int PRIORITY = 1;
public PostTweetJob(String text) {
// This job requires network connectivity,
// and should be persisted in case the application exits before job is completed.
super(new Params(PRIORITY).requireNetwork().persist());
}
@Override
public void onAdded() {
}
@Override
public void onRun() throws Throwable {
webservice.postTweet(text);
}
@Override
protected RetryConstraint shouldReRunOnThrowable(Throwable throwable, int runCount, int
maxRunCount) {
return RetryConstraint.createExponentialBackoff(runCount, 1000);
}
@Override
protected void onCancel() {
}
}
https://github.com/yigit/android-priority-jobqueue
TapeTape is a collection of queue-related classes for Android and Java by Square, Inc.
public class ImageQueueServiceListener implements ObjectQueue.Listener<ImageUploadTask> {
@Override public void onAdd(ObjectQueue<ImageUploadTask> queue, ImageUploadTask task) {
context.startService(new Intent(context, ImageQueueService.class));
}
@Override public void onRemove(ObjectQueue<ImageUploadTask> queue) {}
}
public class ImageQueueService extends Service implements ImageUploadTask.Callback {
private TaskQueue<ImageUploadTask> queue;
@Override public int onStartCommand(Intent intent, int flags, int startId) {
executeNext();
return START_STICKY;
}
public void executeNext() {
ImageUploadTask task = queue.peek();
if (task != null) {
task.execute(this);
return;
}
stopSelf(); // We're done for now.
}
@Override public void imageUploadComplete() {
queue.remove();
executeNext();
}
}
http://square.github.io/tape/
RetrolambdaBackport of Java 8's lambda expressions to Java 7, 6 and 5
button.setOnClickListener(v -> log("Clicked"));
https://github.com/orfjackal/retrolambda
BoltsBolts is a collection of low-level libraries designed to make developing mobile apps easier.
findAsync(query).continueWithTask(new Continuation<List<ParseObject>, Task<Void>>() {
public Task<Void> then(Task<List<ParseObject>> results) throws Exception {
// Collect one task for each delete into an array.
ArrayList<Task<Void>> tasks = new ArrayList<Task<Void>>();
for (ParseObject result : results) {
// Start this delete immediately and add its task to the list.
tasks.add(deleteAsync(result));
}
// Return a new task that will be marked as completed when all of the deletes are finished.
return Task.whenAll(tasks);
}
}).onSuccess(new Continuation<Void, Void>() {
public Void then(Task<Void> ignored) throws Exception {
return null; // Every comment was deleted.
}
});
Uri targetUrl = AppLinks.getTargetUrlFromInboundIntent(getIntent());
if (targetUrl != null) {
AppLinkNavigation.navigateInBackground(getContext(), targetUrl);
} else {
// Not an applink, your existing code goes here.
}
https://github.com/BoltsFramework/Bolts-Android
RxJava (and RxAndroid)RxJava is a Java VM implementation of Reactive Extensions: a library for composing asynchronous and event-
based programs by using observable sequences.
public static void hello(String... names) {
Observable.from(names).subscribe(new Action1<String>() {
@Override
public void call(String s) {
System.out.println("Hello " + s + "!");
}
});
}
hello("Ben", "George");
Hello Ben!
Hello George!
Observable.just("one", "two", "three", "four", "five")
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(/* an Observer */);
https://github.com/ReactiveX/{RxJava,RxAndroid}
6.UI
Ultimate RecyclerViewA RecyclerView with refreshing,loading more,animation and many other features.
https://github.com/cymcsg/UltimateRecyclerView
Sticky headers recyclerviewSticky Headers decorator for Android's RecyclerView
https://github.com/timehop/sticky-headers-recyclerview
PagerSlidingTabStripAn interactive indicator to navigate between the different pages of a ViewPager
https://github.com/jpardogo/PagerSlidingTabStrip
Android BootstrapBootstrap style widgets for Android, with Glyph Icons
https://github.com/Bearded-Hen/Android-Bootstrap
Photo viewImplementation of ImageView for Android that supports zooming, by various touch gestures.
https://github.com/chrisbanes/PhotoView
DialogPlusAdvanced dialog solution for android
https://github.com/orhanobut/dialogplus
https://github.com/PhilJay/MPAndroidChart
MPAndroidChartA powerful Android chart view / graph view library, supporting line- bar- pie- radar- bubble- and candlestick
charts as well as scaling, dragging and animations.
WilliamChartAndroid library to create charts.
https://github.com/diogobernardino/WilliamChart
ObservableScrollViewAndroid library to observe scroll events on scrollable views. It's easy to interact with the Toolbar introduced in
Android 5.0 Lollipop and may be helpful to implement look and feel of Material Design apps.
http://ksoichiro.github.io/Android-ObservableScrollView/
Thanks!Any questions?
You can find this presentation at:shem8.wordpress.com
Presentation template by SlidesCarnival | Photographs by Unsplash