Sonntag, 6. November 2016

Google Login with Oracle Jet - Part 3 - Combine with Oracle Jet hybrid application

Introduction


This is part 3 of a series of blogs, that explain on how to use Google Sign In with Oracle Jet. For more information, please start with part 1.
  1. Google Login with Oracle Jet - Part 1 - Create Google Project
  2. Google Login with Oracle Jet - Part 2 - Combine with Oracle Jet webapplication
  3. Google Login with Oracle Jet - Part 3 - Combine with Oracle Jet hybrid application
Let's continue with the fun part. After creating a Google project and an OAuth client ID in part 1. We did create a basic Oracle Jet webapplication and added a Sign In and Sign Out functionality to it. In part 3 of this blog series, we want to do the same as we did in part 2 with the difference that we implement a hybrid application for our smartphone, instead of implementing a webapplication, as we did in part 2.


Create Oracle Jet hybrid application

We did this several times before and we will do it again. We will create really fast an Oracle Jet page, which is based on the navdrawer template. Just enter the following commands to first create it an than build it.

$ yo oraclejet:hybrid hybridclient --appid=de.lumabit.googlelogin --appname=googlelogin --template=navdrawer:hybrid --platform=android

$ grunt build --platform=android

Add Google+ cordova plugin

I did checkout the cordova page to find a plugin, which is suitable for using a Google+ login. I did decide to use the following plugin and didn't have any problems so far with my android virtual device and my nexus 5. I didn't test with any other android device or with the iphone yet.

https://www.npmjs.com/package/cordova-plugin-googleplus


It is not needed to follow the Cordova documentation. Everything needed to make it work with OracleJet is included in this blog.

The good thing about Oracle Jet is, that you don't have to explicitly download the cordova plugin, if you want to use it. All you have to do is open the following file with your NetBeans IDE

hybrid/config.xml


and add the following lines code to the config.xml

<plugin name="cordova-plugin-googleplus" spec="https://github.com/EddyVerbruggen/cordova-plugin-googleplus">
    <variable name="REVERSED_CLIENT_ID" value="<Reverse_GoogleLogin_Web_ClientID>" />
</plugin>



Reverse_GoogleLogin_Web_ClientID has been created in part 1 of this series of blogs and should be used in reversed form here.
This means it should look similar to this: com.googleusercontent.apps.<LONG_UNIQUE_ID>

ATTENTION: It is very important that you use the OAuth2 webapplication id here and not the OAuth2 Android id, which will be created later.

If you don't remember your GoogleLogin_Web_ClientID it can be found here:
https://console.cloud.google.com/apis/credentials



Create the Javascript functionality

We do need some Javascript functions like GoogleSignIn, GoogleSignOut or IsUserLoggedIn to make this work.
Please open the profile.js file and make the following adjustments  to it.

1. First of all we have to extend the define, because the ojs/button also has to be loaded. So please add 'ojs/ojbutton' to your define.

My define looks like this now. Yours can look different, but the important part is, that you add this 'ojs/ojbutton'

define(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojbutton'],
        function (oj, ko, $) {



2. Create the knockout observable parameters, that will be used to define wether the user is logged in or not and the imageUrl of the user
// Define if the user is logged in
self.isUserLoggedIn = ko.observable(false);
// Image Url
self.imagePath = ko.observable("");




3. We write a function, which will be triggered, when the user is clicking the sign in button. 
  • This is a promise, which is entering the first function, if everything worked fine and the second function, if there was an error.
  • In case of a success I decided to set isUserLoggedIn to true and set the imagePath of the user profile. The returned obj also contains other profile information. 
    • obj.email
    • obj.userId
    • obj.displayName
    • obj.familyName
    • obj.givenName
    • obj.imageUrl
    • obj.idToken
    • obj.serverAuthCode
  • In the second function, which means, that the login failed, we set the isUserLoggedIn to false again. We also give an alert to the user, telling what went wrong.
  • GoogleLogin_Web_ClientID has been created in part 1 of this series of blogs

function ProfileViewModel() {
...
self.googleSignIn = function (data, event) {
                    window.plugins.googleplus.login(
                            {
                               'scopes': 'profile email', 
                               'webClientId': '<GoogleLogin_Web_ClientID>', 
                               'offline': true 
                            },
                            function (obj) {
                               self.isUserLoggedIn(true);
                               self.imagePath(obj.imageUrl);
                               alert(JSON.stringify(obj));
                            },
                            function (msg) {
                                self.isUserLoggedIn(false);
                                self.imagePath("");
                                alert('error: ' + msg);
                            }
                    );
                }
...
}



4. We write a function, which will be triggered, when the user is clicking the sign out button. 
  • In case of a sign out success we do set isUserLoggedIn to false

function ProfileViewModel() {
...
self.googleSignOut = function (data, event) {
                    window.plugins.googleplus.logout(
                            function (msg) {
                                self.isUserLoggedIn(false);
                                self.imagePath("");
                            }
                    );
                }
...
}




5. We write a silentLogin function, which will be triggered, when the user enters the profile module. To make this possible we place the function call inside self.handlActivated(). Silent login sets isUserLoggedIn to true if the application already has the necessary rights to access the user profile.
  • This is a promise, which is entering the first function, if everything worked fine and the second function, if there was an error.
  • In case of a success I decided to set isUserLoggedIn to true and set the imagePath of the user profile
  • In the second function, which means, that the login failed, we set the isUserLoggedIn to false again.
  • GoogleLogin_Web_ClientID has been created in part 1 of this series of blogs

function ProfileViewModel() {
...
self.handleActivated = function (info) {
                    window.plugins.googleplus.trySilentLogin(
                            {
                               'scopes': 'profile email', 
                               'webClientId': '<GoogleLogin_Web_ClientID>', 
                               'offline': true 
                            },
                            function (obj) {
                                self.isUserLoggedIn(true);
                                self.imagePath(obj.imageUrl);
                                self.userObject = obj;
                            },
                            function (msg) {
                                self.isUserLoggedIn(false);
                                self.imagePath("");
                            }
                    );
                };
...
}


Trigger the Javascript functions from HTML

Open the profile.html file and make the following adjustments.

1. Add Sign In button and make it only visible, if the user is not logged in

<div data-bind="ifnot: isUserLoggedIn">
        <button id="google-signin-button"
                data-bind="click: googleSignIn, ojComponent: {
          component:'ojButton', label: 'Sign In',
          icons: {start:'oj-fwk-icon oj-fwk-icon-signin'},
          chroming: 'full'
        }">
        </button>
</div>






2. Add a Sign out and Disconnect button and make it only visible, if the user is logged in. Also add an image of the logged in user.

<div data-bind="if: isUserLoggedIn">
<button id="google-signin-button"
data-bind="click: googleSignOut, ojComponent: {
 component:'ojButton', label: 'Sign Out',
 icons: {start:'oj-fwk-icon oj-fwk-icon-signin'},
 chroming: 'full'
}">
</button>
<img data-bind="attr:{src: imagePath}" />
</div>







Deploy to Android (Virtual) Device

One last step that has to be done is, that we have to deploy our hybrid application to an Android device. The deployment is not the difficult part, but what has to be done, to give the deployed application access to the Google API is, that we have to create another OAuth2 id at the Google Platform. Besides the OAuth2 id for webapplications, we also need one for Android our applications. So what we do is, the following.

1. Open a cmd prompt and enter the following
$ keytool -exportcert -keystore C:/Users/<USERNAME>/.android/debug.keystore -list -v

<USERNAME> is your Windows username
If this is not working, than please check if the file debug.keystore does exist at that location

The password will be android


Now you should see all the entries in the keystore. You should also be able to see a SHA1 key. Please copy that key.





2. Go to the following URL

And create a new OAuth2 client ID for Android applications



3. Enter the needed information for the key

Name: Choose whatever you want
Signing-certificate fingerprint: Please take the SHA1 fingerprint that you copied two steps ago
Package-Name: Choose the package name, that you also picked in your hybric/config.xml file as the id of the widget. In my case it is de.lumabit.googlelogin



This is it. Now you are ready to deploy to your android virtual device.

Conclusion

This series of three blogs showed me, that Oracle Jet is working very well together with other vendors like Google or Cordova. It was possible to make this work without any crazy hacks. All that had to be done, was follow the standard tutorials. This is something I like. :-)

Keine Kommentare:

Kommentar veröffentlichen