Social Integration In Android App: Twitter

Fabric is an amalgamation of multiple tools and SDKs that help developers create awesome apps in no time. Using their plugin for Android Studio, we can integrate any or all of their SDKs in our apps, Twitter is included.

In this tutorial, we will see how to implement Twitter API integration in our Android app. Let’s start with App Module‘s build.gradle file:

Add these statements at the top of the file:

buildscript {
    repositories {
        maven { url 'https://maven.fabric.io/public' }
    }

    dependencies {
        classpath 'io.fabric.tools:gradle:1.+'
    }
}
apply plugin: 'com.android.application'
apply plugin: 'io.fabric'

repositories {
    maven { url 'https://maven.fabric.io/public' }
}

And in Dependencies section, add this:

compile('com.twitter.sdk.android:twitter:2.3.1@aar') {
    transitive = true;
}

 

In your activity’s xml file, add the TwitterLoginButton like this:

<com.twitter.sdk.android.core.identity.TwitterLoginButton 
    android:id="@+id/btnTwitter" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_gravity="center" />

 

Finally, add this code in your Activity file:

	// Note: Your consumer key and secret should be obfuscated in your source code before shipping.
    private static final String TWITTER_KEY = "YOUR_TWITTER_API_KEY";
    private static final String TWITTER_SECRET = "YOUR_TWITTER_API_SECRET";
	private TwitterSession session = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_twitter);
        ButterKnife.bind(this);
        setTitle("Twitter");
		
	TwitterAuthConfig authConfig = new TwitterAuthConfig(TWITTER_KEY, TWITTER_SECRET);
        Fabric.with(this, new Twitter(authConfig), new TweetComposer());

        btnTwitter.setCallback(new Callback<TwitterSession>() {
            @Override
            public void success(Result<TwitterSession> result) {
                // The TwitterSession is also available through:
                // Twitter.getInstance().core.getSessionManager().getActiveSession()
                session = result.data;
                // TODO: Remove toast and use the TwitterSession's userID
                // with your app's user model
                String msg = "@" + session.getUserName()
                        + " \n logged in! (#" + session.getUserId() + ")";
                tvTwitterUser.setText(msg);
//                Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();


            }
            @Override
            public void failure(TwitterException exception) {
                Log.d("TwitterKit", "Login with Twitter failure", exception);
            }
        });
    }

    @OnClick({R.id.btnTweet})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btnTweet:
                if (etTweet.getText().toString()!=null && etTweet.getText().toString().length()>0) {
                    TweetComposer.Builder builder = new TweetComposer.Builder(this)
                            .text(etTweet.getText().toString());
                    builder.show();
                }
                else {
                    UIUtils.showToast(this, "Please enter your tweet.");
                }
                break;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        // Make sure that the loginButton hears the result from any
        // Activity that it triggered.
        btnTwitter.onActivityResult(requestCode, resultCode, data);
    }

You can check the full source here.

Happy Coding!

Social Integration In Android App: Google+

Any app on its own, serves its defined purpose by default, but when you integrate with other apps or social networks, then it enriches your app even more. Using social networks like Google+, Twitter or Facebook you can know more about your users and serve them accordingly. These integrations enhance the user experience of your apps and ensure that your users stay with you.

This will be a series of articles enabling your apps with multiple social networks or login mechanisms and we will start with integrating Google+ in our Android app.

First and foremost, we will have to create a Console Project to be able to use Google+ in our app. You can create a Google Console Project using the Developer Console or the Firebase Developer Console if you plan to use Firebase products in your app. Whichever way you choose to create your project, you’ll have to login to Google Developer Console website and enable Google+ API for your project. You’ll also need to create Credentials (keys) for your app. Once that is done, you’ll need to download the Configuration file from here. It is a JSON file named “google-services.json” and it needs to be placed in the “app” directory of your Android project.

To add Google+ in our apps, we have to add its Gradle dependencies first. Open your Project‘s build.gradle file and add this statement in Dependencies section:

classpath 'com.google.gms:google-services:3.0.0'

 

Now, open your App Module‘s build.gradle file and these statements:
In Dependencies section:

compile 'com.google.android.gms:play-services-auth:10.0.1'

At the end of the file:

apply plugin: 'com.google.gms.google-services'

 

Once these changes are made, you can sync up your project to download the dependencies which we can use in our project.

Now, add a Google+  Sign In button in your activity’s xml file:

<com.google.android.gms.common.SignInButton 
    android:id="@+id/btnGooglePlus" 
    android:layout_width="200dp" 
    android:layout_height="50dp" 
    android:layout_marginTop="10dp"/>

 

Finally, add this code in your Activity file:

    private static final int RC_SIGN_IN = 9001;
    private GoogleApiClient googleApiClient;
    private boolean intentInProgress;
    private boolean signedInUser;
    private ConnectionResult connectionResult;
    private ProgressDialog mProgressDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_google_plus);
        ButterKnife.bind(this);

        setTitle("Google Plus");

        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestEmail()
                .requestProfile()
                .build();

        googleApiClient = new GoogleApiClient.Builder(this)
                .enableAutoManage(this, this)
                .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .build();


        btnGooglePlus.setSize(SignInButton.SIZE_STANDARD);
        btnGooglePlus.setScopes(gso.getScopeArray());

        btnGooglePlus.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(googleApiClient);
                startActivityForResult(signInIntent, RC_SIGN_IN);
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(googleApiClient);
        if (opr.isDone()) {
            // If the user's cached credentials are valid, the OptionalPendingResult will be "done"
            // and the GoogleSignInResult will be available instantly.
            Log.d("GooglePlusActivity", "Got cached sign-in");
            GoogleSignInResult result = opr.get();
            handleSignInResult(result);
        } else {
            // If the user has not previously signed in on this device or the sign-in has expired,
            // this asynchronous branch will attempt to sign in the user silently.  Cross-device
            // single sign-on will occur in this branch.
            showProgressDialog();
            opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
                @Override
                public void onResult(GoogleSignInResult googleSignInResult) {
                    hideProgressDialog();
                    handleSignInResult(googleSignInResult);
                }
            });
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        googleApiClient.disconnect();
    }

    private void resolveSignInError() {
        if (connectionResult.hasResolution()) {
            try {
                intentInProgress = true;
                connectionResult.startResolutionForResult(this, RC_SIGN_IN);
            }
            catch (IntentSender.SendIntentException sie) {
                intentInProgress = false;
                googleApiClient.connect();
            }
        }
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        signedInUser = false;
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Log.d("GooglePlusActivity", "onConnectionFailed:" + connectionResult);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
        if (requestCode == RC_SIGN_IN) {
            GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
            handleSignInResult(result);
        }
    }

    private void handleSignInResult(GoogleSignInResult result) {
        Log.d("GooglePlusActivity", "handleSignInResult:" + result.isSuccess());
        if (result.isSuccess()) {
            // Signed in successfully, show authenticated UI.
            GoogleSignInAccount acct = result.getSignInAccount();
            String personName = acct.getDisplayName();
            String personEmail = acct.getEmail();
            String personId = acct.getId();
            Uri personPhoto = acct.getPhotoUrl();

            String userInfo = personName + "\n" + personEmail
                    + "\n" + personId;

            tvGoogleUser.setText(userInfo);

            Picasso.with(GooglePlusActivity.this).load(personPhoto).into(ivGoogleProfile);

        } else {
            // Signed out, show unauthenticated UI.

        }
    }

    private void signOut() {
        Auth.GoogleSignInApi.signOut(googleApiClient).setResultCallback(
                new ResultCallback<Status>() {
                    @Override
                    public void onResult(Status status) {
                        // [START_EXCLUDE]
                        // [END_EXCLUDE]
                        tvGoogleUser.setText("");
                        ivGoogleProfile.setImageResource(R.drawable.ic_person_black_24dp);
                    }
                });
    }

    private void showProgressDialog() {
        if (mProgressDialog == null) {
            mProgressDialog = new ProgressDialog(this);
            mProgressDialog.setMessage(getString(R.string.loading));
            mProgressDialog.setIndeterminate(true);
        }

        mProgressDialog.show();
    }

    private void hideProgressDialog() {
        if (mProgressDialog != null && mProgressDialog.isShowing()) {
            mProgressDialog.hide();
        }
    }

And make sure that your activity implements these interfaces View.OnClickListener, GoogleApiClient.ConnectionCallbacks & GoogleApiClient.OnConnectionFailedListener.

Using this, we can enable Google+ login in our app and get users’ information in our app. You can check the full source code here.

Happy Coding!

SnackBar

Android’s Design Support library has a cool widget that enhances visual feel of your apps, called SnackBar. It is not a replacement for Toast widget, but there are some similarities that you might see. Basically, a SnackBar is a view that can show a message to the user in a non-disturbing way. Plus, it can also take user’s inputs, should the app require one. Lets see, how to add one in our app.

Add this compile statement in your App Module‘s build.gradle file & build:

compile 'com.android.support:design:25.1.0'

Gradle will then download this library and SnackBar will be available for you to use.

Then in your activity or fragment file, add the SnackBar like this:

final Snackbar snackbar; 

Now, where you need to show your SnackBar, add the below snippets according to your required SnackBar. Remember, this “v” is the view from which you are calling this SnackBar. I’m calling it in a Button click, v is the Button view for me.

Normal SnackBar: 

snackbar = Snackbar.make(v, "This is Normal", Snackbar.LENGTH_SHORT);
snackbar.show(); 

 

Normal SnackBar With Action Button: 

snackbar = Snackbar.make(v, "But Normals need Action", Snackbar.LENGTH_INDEFINITE);
snackbar.setAction("OK", new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Toast.makeText(MainActivity.this, "Understood", Toast.LENGTH_LONG).show();
        snackbar.dismiss();
    }
});
snackbar.show();

 

Customized SnackBar With Action Button:

snackbar = Snackbar.make(v, "Customized Snacking...", Snackbar.LENGTH_LONG);
snackbar.setAction("OK", new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Toast.makeText(MainActivity.this, "Nice", Toast.LENGTH_LONG).show();
        snackbar.dismiss();
    }
});
View view = snackbar.getView();
view.setBackgroundColor(ContextCompat.getColor(MainActivity.this, R.color.colorPrimary));
TextView tv = (TextView) view.findViewById(android.support.design.R.id.snackbar_text);
if (tv != null) {
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
        tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
    }
    tv.setGravity(Gravity.CENTER_HORIZONTAL);
    tv.setTextColor(Color.WHITE);
}
snackbar.setActionTextColor(ContextCompat.getColor(MainActivity.this, R.color.colorAccent));
snackbar.show();

 

Check the video of the different SnackBars:

Checkout the full source code here.

Happy Coding!
Buy Me a Coffee at ko-fi.com

Adding Google Services In Android Project

Google Services library has multiple APIs that any developer might need, for example, “play-services-auth” is used to add Google+ features in your app like login, posting on Google+, etc. So, the Google Services library is an important weapon in a developer’s arsenal. To use this library, its repository must be installed in the Android SDK.

Install Google Services Repository:

  1. Open Android Studio.
  2. Navigate to Tools menu and select Android -> SDK Manager.
  3. The Default Settings window will open and Android SDK will be selected. On the right, the details of your currently installed Android SDK will be listed. Navigate to SDK Tools, this will show all the tools and extra libraries for Android. Scroll down to bottom of that list and expand Support Repository.
  4. From the expanded list, select Google Repository and hit Apply. Android Studio will start downloading and installing this repository in the SDK.

Once this is completed, you can close the Settings window and start integrating the library in your project. To do this follow the below steps:

Open Project‘s build.gradle file, add this line in dependencies section:

classpath 'com.google.gms:google-services:3.0.0'

This section should look like this once you are done:

buildscript {
    repositories {
        jcenter()
     }
    dependencies {
         classpath 'com.android.tools.build:gradle:2.3.0-beta2'
         classpath 'com.google.gms:google-services:3.0.0'
    }
}

 

Then open your App Module‘s build.gradle file and add this line in your dependencies:

compile 'com.google.android.gms:play-services-auth:10.0.1'

Now, scroll down to the last line of this file and add this line at the end of this file:

apply plugin: 'com.google.gms.google-services'

 

It’s very important to add this “Apply Plugin” statement at the end of this file. If you add it at the top, then you might start to get “Conflict” issues while building the project. Android Studio & Gradle while building the project, scan the file (build.gradle) and add the libraries and resolve their dependencies on the fly. So, if this line is read at the beginning, then Gradle will download this library first and apply it to your project. But if at the bottom, you are using another third party library that requires another version of Google Services library, it will create a conflict. By adding this line at the bottom, you ensure that all the dependencies will be resolved when Gradle reads the “Apply Plugin” statement and will apply the required version of this library needed in your project.

All The Available Google Play Services API: (with their Gradle names)

  1. Google+ (play-services-plus)
  2. Google Account Login (play-services-auth)
  3. Google Actions, Base Client Library (play-services-base)
  4. Google Address API (play-services-identity)
  5. Google Analytics (play-services-analytics)
  6. Google Awareness (play-services-awareness)
  7. Google Cast (play-services-cast)
  8. Google Cloud Messaging (play-services-gcm)
  9. Google Drive (play-services-drive)
  10. Google Fit (play-services-fitness)
  11. Google Location and Activity Recognition (play-services-location)
  12. Google Maps (play-services-maps)
  13. Google Mobile Ads (play-services-ads)
  14. Google Places (play-services-places)
  15. Mobile Vision (play-services-vision)
  16. Google Nearby (play-services-nearby)
  17. Google Panorama Viewer (play-services-panorama)
  18. Google Play Game Services (play-services-games)
  19. SafetyNet (play-services-safetynet)
  20. Android Pay (play-services-wallet)
  21. Android Wear (play-services-wearable)

To add any of the above libraries in your project, simply create a Compile statement like this:

compile 'com.google.android.gms:<YOUR_REQUIRED_LIBRARYS_GRADLE_NAME>:<CURRENT_VERSION>'

Get the current version of Google Services API from this official link.

Happy Coding!
Buy Me a Coffee at ko-fi.com

Animations

Animations in an Android app adds the wow factor to the app. It engages the user with visual treats that enhance the overall experience of your app. Android framework provides multiple ways to animate views, objects and overall screens. Please check the demo:

Let’s see one example from the demo, Alpha Animation. Create a resource file named alpha in your “res\anim” directory with the following code:

<?xml version="1.0" encoding="utf-8"?>
<alpha
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:fromAlpha="0.0"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:toAlpha="1.0">
</alpha>

Add this code where you want to animate the view in your app:

Animation animAlpha = AnimationUtils.loadAnimation(MainActivity.this, R.anim.alpha);
[YOUR_VIEW_OBJECT].startAnimation(animAlpha);

Replace the “YOUR_VIEW_OBJECT” with the view’s name which you want to animate.

Checkout the rest of the animations in this GitHub repository. In the demo project, you’ll find animations for alpha, blinking, fading, zooming, scaling, rotation, flipping & more.

Happy Coding!

Android Notifications

Notifications are a great way to remind user of his/her immediate or future attention required by the app. It enables the developers to show useful and sometimes crucial information in concise way to the users.
Lets see how we can take advantage of the NotificationCompat API:
In your app gradle file, make your target version point to 20 because from Android OS Lollipop and later, the notification icons should follow the material design (must be entirely white), in case, your notification icon doesn’t follow the requirements.
In your activity (MainActivity.java in my case) file, add this declaration:

private PendingIntent pendingIntent;
private NotificationManager notificationManager;
private NotificationCompat.Builder notificationBuilder;

In the onCreate method of the activity, add these lines:

Intent i = new Intent(MainActivity.this, CatchNotificationActivity.class);
pendingIntent = PendingIntent.getActivity(MainActivity.this, 0, i, 0);
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

Now, whenever you want to show the notification, add this code to any events in your activity or method calls:

notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(MainActivity.this)
        .setContentIntent(pendingIntent)
        .setContentTitle("Notifications Demo")
        .setContentText("Notified you, don't tell me I didn't.")
        .setSmallIcon(R.mipmap.ic_launcher)
        .setSubText("Told you, I've notified already. ;)")
        .setAutoCancel(true)
        .setTicker("Notifying...");

Uri uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
notificationBuilder.setSound(uri);
notificationBuilder.setVibrate(new long[]{300, 1000});

notificationManager.notify(1, notificationBuilder.build());

In CatchNotification.java activity file, I’ve just added the code to remove the notification once it has been consumed:

String ns = Context.NOTIFICATION_SERVICE;
NotificationManager nMgr = (NotificationManager) getApplicationContext().getSystemService(ns);
nMgr.cancel(1);

The example code is available in this GitHub repository. In the sample project, you’ll also find code to show the notification using the BigPictureStyle and BigTextStyle APIs.

Happy Coding!

Mashmallow Permission

Starting with the Android Marshmallow OS, the permissions mechanism has been updated. Now, the apps are directly installed in Android M or later OS devices without asking for permissions. In the app, when a user accesses a feature that requires a nod from the user, the app has to ask for the permission and only if the user allows that permission, can the feature work in the app. Otherwise, the app has to disable that feature for that user.
This has put us, the developers, to do more work in the app, checking for each permission that the app needs. But at the same time, it has enabled the user to view and understand what an app does with a particular feature and given him/her a right to disable access if he/she wishes to. User’s privacy and his/her rights are utmost to us, so even if it means extra coding, we should be willing to do it. Also, its a great user experience (UX), if our app enables and educates the user on each and every feature we develop for them.
Let’s check out, how to implement the permission requests and handle the situations. I’m going to show how we can ask for Location updates from user’s device. But you can use the code for any permission you like.
Let’s add dependencies in app gradle file:

    compile 'com.android.support:design:23.3.0'
    compile 'com.google.android.gms:play-services:8.4.0'

Google Play services is the one for location and Design support library is for SnackBar I’ve used in the app.

Imports in the MainActivity.java class file:

import android.Manifest;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;

MainActivity class file:

public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {

    private static final int REQUEST_ACCESS_FINE_LOCATION = 1;
    private Button btnLocation;
    private TextView tvLocation;
    private GoogleApiClient mGoogleApiClient;
    private Location mLastLocation;

    private void findViews() {
        btnLocation = (Button)findViewById( R.id.btnLocation );
        tvLocation = (TextView)findViewById( R.id.tvLocation );

        btnLocation.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mGoogleApiClient != null) {
                    if (mGoogleApiClient.isConnected()) {
                        getLocation();
                    } else {
                        Snackbar.make(tvLocation, "Google Play Services not ready!", Snackbar.LENGTH_LONG).show();
                    }
                } else {
                    Snackbar.make(tvLocation, "Google Play Services not available!", Snackbar.LENGTH_LONG).show();
                }
            }
        });
    }

    private void getLocation() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(MainActivity.this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    REQUEST_ACCESS_FINE_LOCATION);

            return;
        }

        mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        if (mLastLocation != null) {
            String msg = "Latitude: " + String.valueOf(mLastLocation.getLatitude()) + "\n"
                    + "Longitude: " + String.valueOf(mLastLocation.getLongitude());
            tvLocation.setText(msg);
        }else{
            Snackbar.make(tvLocation, "Location unavailable!", Snackbar.LENGTH_LONG).show();
        }
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // instantiate Google API client
        if (mGoogleApiClient == null) {
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
        }

        findViews();
    }

    @Override
    protected void onStart() {
        mGoogleApiClient.connect();
        super.onStart();
    }

    @Override
    protected void onStop() {
        mGoogleApiClient.disconnect();
        super.onStop();
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        getLocation();
    }

    @Override
    public void onConnectionSuspended(int i) {
        Snackbar.make(tvLocation, "Google Play Services not ready!", Snackbar.LENGTH_LONG).show();
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Snackbar.make(tvLocation, "Google Play Services connection failed!", Snackbar.LENGTH_LONG).show();
    }

    @Override
    public void onRequestPermissionsResult(
            int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        switch (requestCode) {
            case REQUEST_ACCESS_FINE_LOCATION: {
                // grantResults array will be empty if the user denies permission...
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Snackbar.make(tvLocation, "Permission granted!", Snackbar.LENGTH_LONG).show();
                    getLocation();

                } else {
                    Snackbar.make(tvLocation, "Permission denied!", Snackbar.LENGTH_LONG).show();
                    // you can also build a case with the user if the permission is important for the app.
                    AlertDialog.Builder builder = new AlertDialog.Builder(
                            MainActivity.this);
                    builder.setTitle("Marshmallow Permissions");
                    builder.setMessage("Location is important for the app to function " +
                            "and give you better results! Please grant location permission.");
                    builder.setPositiveButton("OK",
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog,
                                                    int which) {
                                    getLocation();
                                }
                            });
                    builder.show();
                }
                return;
            }

            // other permissions can be checked in Case statements
        }
    }
}

We can maintain the count of requests for a feature and show appropriate messages to the user based on the count of requests and earlier denials. App source is available on this GitHub repository.

Happy Coding!

Speech To Text

Android has a very awesome API that enables speech to be converted to text. It is available by default. All we need is an Internet connection as the API sends your speech to Google servers to convert to text and get the results back to us. There is an Offline mode but for that we need to make sure that we download the language packs for our speech to converted to words.

As a developer, it excites me to try this feature and add it to my apps if my clients ever need it. To enable speech recognition in your activity, all we need to do is the following code:

Speech recognition code:

private final int SPEECH_CODE = 1;

The code in this method triggered on event or ran on its own:

private void startConvertingSpeechToText() {
        Intent i = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        i.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
        i.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
                RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
        i.putExtra(RecognizerIntent.EXTRA_PROMPT,
                "Please start speaking...");
        try {
            startActivityForResult(i, SPEECH_CODE);
        } catch (ActivityNotFoundException a) {
            Snackbar.make(fabSpeak, "Speech recognition is not supported on your device. Sorry!",
                    Snackbar.LENGTH_LONG).show();
        }
    }

Handle onActivityResult method with the speech data:

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case SPEECH_CODE: {
                if (resultCode == RESULT_OK && null != data) {
                    ArrayList<String> result = data
                            .getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
                    String text = result.get(0);
                    tvConvertedText.setText(text);
                }
                break;
            }
        }
    }

That’s it! You can start getting text commands from your users in your apps using speech now. This is really good UX mechanism to save keystrokes, but only for short commands. I’ve found out that sometimes, it fails due to different accents, speed of speaking and how near or far the device you are holding when speaking. Do your own experiments!

The example project is available on GitHub.

Happy Coding!

Bye, Bye Parse!

Facebook is pulling the plug on Parse on January 28, 2017 and they’ve given all the Parse users to backup their data before that date. Now, we have to find other alternatives to Parse that give us the same features, scalability, convenience, and most of all, cost-free to develop for Indie developers or freelancers like me.

I researched for many BaaS (Backend As A Service) providers with the above filters and found the below mentioned to be useful. Please check them out:

Firebase: Google owned Firebase, provides a real-time No-SQL cloud database, social logins and hosting for mobile and web apps. (Free Plan: Unlimited users, 100 active connections/second, 1 GB storage, 10 GB data transfer, 1 GB hosting, 100 GB hosting transfer)

AWS Mobile Hub: Amazon platform provides you with configuration options to add user authentications, data storage, backend logic, push notifications, analytics for your mobile apps. (Check out AWS Free Usage Tier)

Back4App: It uses the Parse open source code base to provide the infrastructure. It means we can migrate our Parse apps to Back4App without any problems. Using visual tools, we can build & host APIs for mobile, web & IoT apps. (Free Plan: 1 GB data transfer/month & 100 K API calls/month)

Back&: Backand is a powerful BaaS provider for AngularJS that provides social login, real-time communication, Ionic integration. (Free Plan: 30 requests/second, 150 real-time connections, 20 GB file storage/month, 2 GB database storage/month, 150 GB data transfer/month)

BackEndLess: Backendless is a framework of integrated, general purpose, mobile cloud services with native and REST APIs. (Free Plan: 50 API calls/second, 20 GB file storage/month, 1 M pub-sub messages/month, 1 M push notifications/month)

Buddy: A lightweight, fast and flexible platform for collecting and processing IoT data. Also offers a mobile-focused set of APIs such as Users, Check-ins, Push Notifications and Metrics. (Free Plan: Unlimited API Calls, 20 requests/second,  10 GB storage, 5 million notifications/month)

Apstrata: It is a complete BaaS provider for mobile & web applications. It provides orchestration (JavaScript server-side scripting), No-SQL persistence,  Messaging (push notifications, email), User authentications & Social integration. (Free Plan: No limit usage for up to 500 Users or unique devices)

AppWooDoo: Appwoodoo provides a real-time database and push notifications backend server for mobile. It is open-source. (Free Plan: 15 K API calls/month, 1 K push notifications/month. Limits are shared between all your apps, up to 50 apps)

Rapid API: It provides drag-and-drop visual blocks of code to create APIs and backend features that you may require, like data storage, social logins, email-text-push notification messages, etc. (Free Plan: 1 DB, 10 Endpoints, 1 K API calls, 1 K emails, 1 K push notifications, 1 K text messages)

ShepHertz App42: It provides a framework to create apps and games for multiple platforms such as TV, IoT, Mobile, Web, Wearables, Social & Games. Developers can use modules for push notifications, No-SQL storage, Cloud code,  User management, Analytics, Gaming, and many more. (Free Plan: (For Indie Developers) 1 M API calls, 1 M push notifications,  1 GB bandwidth, 1 GB storage)

AppMobi: It is a Mobile Security as a Service (MSaaS) provider with configurable encryption, authentication, encrypted data storage, secure push messages & secure analytics. (Free Plan: No limit usage for up to 500 unique devices)

There are some platforms that provide free BaaS solutions only for development or proof-of-concept. Using these platforms, you can create your app but if you want to launch your app you need to upgrade your account to a paid one. These platforms are Syncano, Reindex, RestDB & FatFractal.

Android Links

Android is an OS and a framework based on Linux kernel for the mobile devices, comes from the house of Google! It is the most popular mobile platform in the Indian sub-continent. Here are the some of the important links in the Android eco-system that will help developers learn more about Android & building Android apps:

Official Google Links:

Courses / Video Tutorials:

Tutorials / Blogs / Communities:

News / Tools / Libraries: