The Android SDK provides a simple Java API that enables an Android app to interact with a LoopBack server application.
Page Contents

The Android SDK provides a simple Java API that enables your Android app to access a LoopBack server application. It enables you to interact with your models and data sources in a comfortable native manner instead of using clunky interfaces like AsyncHttpClientJSONObject

Download Android SDK



Getting started with the guide app

The easiest way to get started with the LoopBack Android SDK is with the LoopBack Android guide app. The guide app comes ready to compile with Android Studio and each tab in the app will guide you through the SDK features available to mobile apps.

Prerequisites

If you haven’t already created your application backend, see loopback-android-getting-started. The Android guide app will connect to the this backend sample app.

Before you start, make sure you’ve installed the Eclipse Android Development Tools (ADT).

Now make sure you have the necessary SDK tools installed.

  1. In ADT, choose Window > Android SDK Manager.
  2. Install the following if they are not already installed:
    • Tools:
    • Android SDK Platform-tools 18 or newer
    • Android SDK Build-tools 18 or newer * Android 4.3 (API 18)
    • SDK Platform.
  3. To run the LoopBack Android guide application (see below), also install Extras > Google Play Services.

Before you start, make sure you have set up at least one Android virtual device: Choose Window > Android Virtual Device Manager. See AVD Manager for more information.

Running the LoopBack server application

Follow the instructions in  Getting started with LoopBack to create the LoopBack sample backend application. You can also just clone https://github.com/strongloop/loopback-getting-started.

In the directory where you created the application, enter these commands:

$ cd loopback-getting-started
$ node .

Downloading LoopBack Android Getting Started app

To get the LoopBack Android Getting Started application, you will need either the git command-line tool or a GitHub account.

To use git, enter this command:

$ git clone [email protected]:strongloop/loopback-android-getting-started.git

Running the LoopBack Android Getting Started app

Follow these steps to run the LoopBack Android guide app:

  1. Open ADT Eclipse.
  2. Import the Loopback Guide Application to your workspace:
    1. Choose File > Import.
    2. Choose Android > Existing Android Code into Workspace.
    3. Click Next.
    4. Browse to the loopback-android-getting-started/LoopbackGuideApplication directory.
    5. Click Finish.
  3. Import Google Play Services library project into your workspace. The project is located inside the directory where you have installed the Android SDK.
    1. Choose File > Import.
    2. Choose Android > Existing Android Code into Workspace.
    3. Click Next.
    4. Browse to the <android-sdk>/extras/google/google_play_services/libproject/google-play-services_lib directory.
    5. Check Copy projects into workspace
    6. Click Finish.

    See Google Play Services SDK for more details.

  4. Add the imported google-play-services_lib as an Android build dependency of the Guide Application.
    1. In the Package Explorer frame, select LoopbackGuideApplication
    2. Choose File > Project Properties
    3. Select Android
    4. In the Library frame, click on Add… and select google-play-services_lib
  5. Obtain an API key for Google Maps Android API v2 per  Getting Started instructions and enter it into AndroidManifest.xml.

  6. Click the green Run button in the toolbar to run the application. Each tab (fragment) shows a different way to interact with the LoopBack server. Look at source code of fragments to see implementation details.

It takes some time for the app to initialize: Eventually, you’ll see an Android virtual device window. Click the LoopBack app icon in the home screen to view the LoopBack Android guide app.

Troubleshooting

Problem: Build fails with the message Unable to resolve target 'android-18'.

Resolution: You need to install Android 4.3 (API 18) SDK. See Prerequisites  for instructions on how to install SDK components.

If you don’t want to install an older SDK and want to use the most recent one (for example, Android 4.4 API 19), follow these steps:

  1. Close Eclipse ADT.
  2. Edit the file project.properties in the loopback-android-getting-started directory and change the target property to the API version you have installed. For example: target=android-19.
  3. Open Eclipse ADT again. The project should build correctly now.

Creating and working with your own app

If you are creating a new Android application or want to integrate an existing application with LoopBack, then follow the steps in this section.

Eclipse ADT setup

Follow these steps to add LoopBack SDK to your Eclipse project:

  1. Download LoopBack Android SDK for Eclipse.
  2. Extract the content of the downloaded zip file and copy the contents of the libs folder into the libs folder of your Eclipse ADT project.

Android Studio setup

  1. Edit your build.gradle file.
  2. Make sure you have mavenCentral() or jcenter() among the configured repositories (jcenter is a superset of mavenCentral). Projects created by Android Studio Beta (0.8.1 and newer) have this repository configured for you by default: 

    build.gradle in project root

    repositories { 
        jcenter() 
    }
    
  3. Add com.strongloop:loopback-sdk-android:1.5.- to your compile dependencies:

    dependencies { 
        compile 'com.strongloop:loopback-sdk-android:1.5.-
    }
    

Working with the SDK

For the complete API documentation, see LoopBack Android API.

  1. You need an adapter to tell the SDK where to find the server:

    RestAdapter adapter = new RestAdapter(getApplicationContext(), "http://example.com/api");

    This RestAdapter provides the starting point for all client interactions with the running server. It should be suffixed with “/api” in order for the underlying REST method calls to be resolved to your Model.

  2. Once you have access to adapter (for the sake of example, assume the Adapter is available through our Fragment subclass), you can create basic Model and ModelRepository objects. Assuming you’ve  previously created a LoopBack model named “product”:

    ModelRepository productRepository = adapter.createRepository("product");
    Model pen = productRepository.createObject( ImmutableMap.of("name", "Awesome Pen") );
    

    All the normal Model and ModelRepository methods (for example, createdestroyfindById) are now available through productRepository and pen!

  3. You can now start working with your model through the generic Model object. Continue below to learn how to extend the Model Java object to directly match, and thus provide the strongly-typed interface for interaction with, your own Model’s members. Check out the LoopBack Android API docs  or create more Models with the Model generator.

Creating your own LoopBack model

Creating a subclass of Model enables your class to get the benefits of a Java class; for example, compile-time type checking.

Prerequisites

  • Knowledge of Java and Android app development
  • LoopBack Android SDK - You should have set this up when you followed one of the preceding sections.
  • Schema - Your data schema must be defined already.

Define model class and properties

As with any Java class, the first step is to build the interface. If you leave custom behavior for later, then it’s just a few property declarations and you’re ready for the implementation. In this simple example, each widget has a way to be identified and a price.

import java.math.BigDecimal;
import com.strongloop.android.loopback.Model;

/**
 * A widget for sale.
 */
public class Widget extends Model {

  private String name;
  private BigDecimal price;

  public void setName(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }

  public void setPrice(BigDecimal price) {
    this.price = price;
  }

  public BigDecimal getPrice() {
    return price;
  }
}

Define model repository

The ModelRepository is the LoopBack Android SDK’s placeholder for what in Node is a JavaScript prototype representing a specific “type” of Model on the server. In our example, this is the model exposed as “widget” (or similar) on the server:

var Widget = app.model('widget', {
  dataSource: "db",
  properties: {
    name: String,
    price: Number
  }
});

Because of this the class name ('widget', above) needs to match the name that model was given on the server. If you don’t have a model, see the LoopBack documentation for more information.  The model must exist (even if the schema is empty) before it can be interacted with.

Use this to make creating Models easier. Match the name or create your own.

Since ModelRepository provides a basic implementation, you need only override its constructor to provide the appropriate name.

public class WidgetRepository extends ModelRepository<Widget> {
    public WidgetRepository() {
        super("widget", Widget.class);
    }
}

Add a little glue

Just as in using the guide app, you need an RestAdapter instance to connect to the server:

RestAdapter adapter = new RestAdapter("http://myserver:3000/api");

Remember: Replace ”http://myserver:3000/api” with the complete URL to your server, including the the “/api” suffix.

Once you have that adapter, you can create our Repository instance.

WidgetRepository repository = adapter.createRepository(WidgetRepository.class);

Create and modify widgets

Now you have a WidgetRepository instance, you can:

Create a Widget:

Widget pencil = repository.createObject(ImmutableMap.of("name", "Pencil"));
pencil.price = new BigDecimal("1.50");

Save the Widget:

pencil.save(new VoidCallback() {
    @Override
    public void onSuccess() {
        // Pencil now exists on the server!
    }

    @Override
    public void onError(Throwable t) {
        // save failed, handle the error
    }
});

Find another Widget:

repository.findById(2, new ObjectCallback<Widget>() {
    @Override
    public void onSuccess(Widget widget) {
        // found!
    }

    public void onError(Throwable t) {
        // handle the error
    }
});

Remove a Widget:

pencil.destroy(new VoidCallback() {
    @Override
    public void onSuccess() {
        // No more pencil. Long live Pen!
    }

    @Override
    public void onError(Throwable t) {
        // handle the error
    }
});

Users and authentication

The LoopBack Android SDK provides classes that make it easy to connect an Android client app to a server application using LoopBack’s authentication and authorization model: 

See Authentication, authorization, and permissions for instructions how to enable authentication in your LoopBack server.

The Android SDK comes with a predefined implementation of UserRepository that provides loginUser and logout methods. However, you cannot use UserRepository<User> directly, because the Java runtime removes types from generic instances and therefore there is no way to pass the User class to the UserRepository instance created via createRepository. So you must create a specialized subclass:

package com.example.myproject;
// Optional, you can use LoopBack's User class too
public static class User extends com.strongloop.android.loopback.User {
}
public static class UserRepository·
        extends com.strongloop.android.loopback.UserRepository<User> {
    public interface LoginCallback·
        extends com.strongloop.android.loopback.UserRepository.LoginCallback<User> {
    }
    public UserRepository() {
        super("customer", null, User.class);
    }
}

Then use it as follows: 

RestAdapter restAdapter = new RestAdapter("http://myserver:3000/api");
import com.example.myproject;
UserRepository userRepo = restAdapter.createRepository(UserRepository.class);
User user = userRepo.createUser("[email protected]", "password");

Or, to log in the user:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    final  RestAdapter  restAdapter = new RestAdapter(getApplicationContext(), "http://myserver:3000");
    final UserRepository  userRepo = restAdapter.createRepository(UserRepository.class);
    loginBtn = (Button) findViewById(R.id.loginButton);
    loginUsername = (EditText) findViewById(R.id.loginUsername);
    loginPassword = (EditText) findViewById(R.id.loginPassword);
    goToCreateAccountBtn = (TextView) findViewById(R.id.createAccount);
    //Login click listener
    loginBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            username = loginUsername.getText().toString();
            password = loginPassword.getText().toString();
            System.out.println(username - " : " - password);
            userRepo.loginUser(username , password , new UserRepository.LoginCallback() {
                @Override
                public void onSuccess(AccessToken token, User currentUser) {
                    Intent goToMain = new Intent(getApplicationContext(), Main.class);
                    startActivity(goToMain);
                    finish();
                    System.out.println(token.getUserId() - ":" - currentUser.getId());
                }

                @Override
                public void onError(Throwable t) {
                    Log.e("Chatome", "Login E", t);
                }
            });
        }
    });

    //Create account listener
    goToCreateAccountBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent goToSignup = new Intent(getApplicationContext(), Signup.class);
            startActivity(goToSignup);
            finish();
        }
    });
}

The loginUser() method returns an access token. The RestAdapter stores the access token in and uses it for all subsequent requests. Because it stores the value in SharedPreferences, it preserves the value across application restarts.

userRepo.logout(new VoidCallback() {
    @Override
    public void onSuccess() {
        // logged out
    }

    @Override
    public void onError(Throwable t) {
      // logout failed
    }
});

The repo can also be used to change the current user’s password.

userRepo.changePassword(currentPassword, newPassword, new VoidCallback(){
    @Override
    public void onSuccess() {
        // Password changed
    }

    @Override
    public void onError(Throwable t) {
      // Password change failed
    }
});

Accessing data of the current user

There are two methods to get the User object for the currently logged in user:

  • UserRepository.findCurrentUser() -  performs a request to the server to get the data of the current user and caches the response in memory. When no user is logged in, passes null to the callback.
  • UserRepository.getCachedCurrentUser() - returns the value cached by the last call of findCurrentUser() or loginUser().

Call findCurrentUser when your application starts. Then you can use the synchronous method getCachedCurrentUser in all your Activity classes.

Example of using the findCurrentUser() method:

userRepo.findCurrentUser(new ObjectCallback<User>() {
    @Override
    public void onSuccess(User user) {
        if (user != null) {
            // logged in
        } else {
            // anonymous user
        }
    }
});

Example of using the getCachedCurrentUser() method:

User currentUser = userRepo.getCachedCurrentUser();
if (currentUser != null) {
    // logged in
} else {
    // anonymous user
    // or findCurrentUser was not called yet
}

Extending the pre-defined User model

Most applications will need to extend the built-in User model with additional properties and methods.  Consider the example of an e-shop, where the user is modeled as a Customer, with an additional property address.

models.json

"customer": {
  "properties": {
    "address": "string"
  },
  "options": {
    "base": "user"
  }
}

To access your customer model from the Android app, extend the UserRepository and User classes as you extend ModelRepository and Model when creating any other model class.

public class Customer extends User {
    private String address;
    public String getAddress() { return address; }
    public void setAddress(String address) { this.address = address; }
}

public class CustomerRepository extends UserRepository<Customer> {
    public interface LoginCallback extends UserRepository.LoginCallback<Customer> {
    }

     public CustomerRepository() {
        super("customer", null, Customer.class);
     }
}

Now you can login a customer and access the corresponding address:

CustomerRepository customerRepo = restAdapter.createRepository(CustomerRepository);

customerRepo.loginUser("[email protected]", "password",
    new CustomerRepository.LoginCallback() {
        @Override
        public void onSuccess(AccessToken token, Customer customer) {
            // customer was logged in
        }

       @Override
       public void onError(Throwable t) {
           // login failed
       }
   }
);

// later in one of the Activity classes
Customer current = customerRepo.getCachedCurrentUser();
if (current != null) {
    String address = current.getAddress();
    // display the address
} else {
    // you have to login first
}
REVIEW COMMENT from $paramName

Following from blog post needs to be integrated.

At application startup, find the currently logged-in user. When no user is logged in and your application requires an authenticated user, instead present the login screen Activity.

Call the loginUser() method to log in a user; for example:

Use getCachedCurrentUser() in your Activity classes to get the data for the current user.

Tags: android