Tuesday, 26 December 2017

Ionic 3 Google Plus Authentication

This is step by step tutorial Ionic 3 and Angular 4 app authentication with Ionic 3 native Google plus plugin. Before started with the app, there's a setup of Google Plus via Google Developer Console.

1. Google API Setup

The first thing to setup from Google is generating configuration files for iOS and Android. For iOS, open your browser then point to this address then log in with your google account.
 Create the new iOS app from there by filling the form. Enter app name and iOS bundle ID, our example is "MyGooglePlusAuth" for app name and "com.mygoogleplusauth" for iOS bundle ID. Please, remember that iOS bundle ID will use in Ionic 3 config later and that would be easy if we use the same bundle ID for Android.
Leave other option to default then click "Choose and Configure Service" button.
Click "ENABLE GOOGLE SIGN IN" button. After that, click "Generate configuration file" button. Click the button "Download GoogleService-info.plist", we will use this files later on the Ionic 3 project.
Next, we have to generate Google service configuration file for Android too. Go to this address then choose app name that previously created. File Android package name same as iOS bundle ID "com.mygoogleplusauth".
 Click "Choose and configure service" button. Before enabling this service, we have to create new SHA-1 signing certificate which uses for release and debug. Open terminal or command line, then type this command to create certificate fingerprint for debugging.
keytool -exportcert -list -v \
> -alias androiddebugkey -keystore ~/.android/debug.keystore
or from the command line (windows).
keytool -exportcert -list -v \
-alias androiddebugkey -keystore %USERPROFILE%\.android\debug.keystore
Enter the password, by default for "debug.keystore is "android".
Alias name: androiddebugkey
Creation date: Nov 8, 2015
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Android Debug, O=Android, C=US
Issuer: CN=Android Debug, O=Android, C=US
Serial number: 5e9752f4
Valid from: Sun Nov 08 22:25:34 WIB 2015 until: Tue Oct 31 22:25:34 WIB 2045
Certificate fingerprints:
     MD5:  0A:2D:96:6B:B8:84:F7:37:2E:7E:83:09:43:BB:B7:D4
     SHA1: 2B:52:02:F0:82:94:34:68:FC:B6:DD:81:1D:3A:66:D7:57:3B:B9:11
     SHA256: B1:40:EB:9D:03:50:A2:0F:F2:D4:1B:6D:AA:F6:F9:6A:57:52:B0:70:5A:3C:87:9E:15:F0:BE:7C:90:00:DA:51
     Signature algorithm name: SHA256withRSA
     Version: 3

Extensions:

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: C0 3A D3 06 65 23 89 A1   5D 80 CC 55 88 D8 BD 23  .:..e#..]..U...#
0010: 80 6E 67 01                                        .ng.
]
]
Copy Certificate fingerprints SHA1 value then paste in "Android Signing Certificate SHA-1" of Google Developer to enable Google Sign-In service.
Next, just click the "CLOSE" button and not necessary to download generated configuration files for Android only. If you plan to use your app in production/published, change the certificate fingerprint with this command.
keytool -exportcert -list -v \
-alias <your-key-name> -keystore <path-to-production-keystore>
Keystore using same as your Keystore of build release for publishing. Then edit manually in Google developer console. Choose credentials from side menu then find "OAuth 2.0 client IDs" for Android. You can replace the SHA1 certificate fingerprint with production/release key.

2. Create Ionic 3 App

As usually in almost all of our tutorial, we create an app from scratch. Back to the terminal or command line then go to your apps folder. Type this command to create new Ionic 3 app.
ionic start mygoogleplusauth blank --v2
Go to the newly created app folder.
cd mygoogleplusauth
Now, open and edit config.xml in the root of app folder. Replace app id on the <widget> tag to match Android package or iOS bundle ID that previously created on the Google Developer page.
<widget id="com.mygoogleplusauth" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
Run the app, to make sure everything still on the path.
ionic serve -l
If you see the Ionic 3 blank app page below then we ready to continue.
Ionic 3 Google Plus Authentication Tutorial - Ionic Blank App
For now, stop the app by push control+c at the same time.


3. Setup Ionic 3 Native Google Plus Plugin

To install Ionic 3 native Google Plus plugin you can refer to the official Ionic Framework documentation. Back to the terminal or command line. Type this command to install Cordova plugin and ionic module of Google Plus plugin. You can find "REVERSED_CLIENT_ID" on generated "GoogleService-info.plist" file.
ionic plugin add cordova-plugin-googleplus --variable REVERSED_CLIENT_ID=myreversedclientid
npm install --save @ionic-native/google-plus
If you see warning like below then we should update the "@ionic-native/core" module.
npm WARN @ionic-native/google-plus@3.6.1 requires a peer of @ionic-native/core@^3.6.1 but none was installed.
Update the @ionic-native/core module by type this commands.
npm uninstall --save @ionic-native/core
npm install --save @ionic-native/core@^3.6.1


4. Add Google Login Button on The Page

To implement Google authentication, we put Google login button to trigger Google Plus authentication. Open and edit "src/pages/home/home.ts" then replace all codes with this.
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { GooglePlus } from '@ionic-native/google-plus';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html',
  providers: [GooglePlus]
})
export class HomePage {

  displayName: any;
  email: any;
  familyName: any;
  givenName: any;
  userId: any;
  imageUrl: any;

  isLoggedIn:boolean = false;

  constructor(public navCtrl: NavController, private googlePlus: GooglePlus) {

  }

  login() {
    this.googlePlus.login({})
      .then(res => {
        console.log(res);
        this.displayName = res.displayName;
        this.email = res.email;
        this.familyName = res.familyName;
        this.givenName = res.givenName;
        this.userId = res.userId;
        this.imageUrl = res.imageUrl;

        this.isLoggedIn = true;
      })
      .catch(err => console.error(err));
  }

  logout() {
    this.googlePlus.logout()
      .then(res => {
        console.log(res);
        this.displayName = "";
        this.email = "";
        this.familyName = "";
        this.givenName = "";
        this.userId = "";
        this.imageUrl = "";

        this.isLoggedIn = false;
      })
      .catch(err => console.error(err));
  }
}
Next, open and edit "src/pages/home/home.ts" then replace all codes with this.
<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic Blank
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <div *ngIf="isLoggedIn; else loginTemplate">
    <h1>Welcome, {{displayName}}!</h1>
    <p>Email: {{email}}<br>
      Family Name: {{familyName}}<br>
      Given Name: {{givenName}}<br>
      User ID: {{userId}}</p>
    <p><ion-avatar item-left>
        <img src="{{imageUrl}}">
       </ion-avatar></p>
    <p><button ion-button (click)="logout()">Logout From Google</button></p>
  </div>

  <ng-template #loginTemplate>
    <h1>Please Login to see your Google Account Information</h1>
    <p><button ion-button (click)="login()">Login With Google</button></p>
  </ng-template>
</ion-content>
5. Run Ionic 3 App on Android and iOS Device
For android is really easy. Before run make sure we have to add Android platform.
ionic platform add android
Then run the app on Android device, make sure you have connected your device to your computer.
ionic run android
Ionic 3 Google Plus Authentication Tutorial - Ionic App with Google Login
After clicking the button "Login With Google", it will show a dialog to choose your existing google credentials on the device. Choose one of it then it will back to the app with Google user detail.

 For iOS type this command.
ionic build ios
After the finished build, open the file with extension ".xcodeproj" on "/platforms/ios" folder using XCode.

Click/highlight project name on the left pane, then choose Capabilities. Turn on Keychain Sharing, for that you have to use your Apple developer account.

Now, we can run the app to an iOS device from XCode, make sure there's a Google account on the device.

Sunday, 17 December 2017

Spinner DropDown List Example using PHP MySQL and Android Studio

           In this tutorial I will teach how to build a dropdwon list / menu using PHP, MySQL, and JSON
Needed:
  • PHP Editor like Notepad++ (downloaded here if you dont have it)
  • Webserver like XAMPP (downloaded here if you dont have it) or see this tutorial how to install XAMPP
  • Android Studio (downloaded here if you dont have it)
Step 1: Create Database
Go to your localhost:  http://localhost/ or  http://localhost/phpmyadmin/
and create new database named: customers
alfter that create a new table and call it  customer and  insert some data.
                   
Step 2: Create PHP
After that go to your XAMPP or WAMP or your webserver install directory
for XAMP users go to your XAMPP installation folder C:\xampp\htdocs and under the htdocs folder create a new folder and call it custmers and Create a new file call it spinner_test.php and write following code.
                      <?php
  $DB_USER='YOUR USER'; 
$DB_PASS='YOUR PASSWORD'; 
$DB_HOST='localhost';
$DB_NAME='YOUR DATABASE NAME';
                        $mysqli = new mysqli($DB_HOST, $DB_USER, $DB_PASS, $DB_NAME);
                       /* check connection */
                         if (mysqli_connect_errno())
                           {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
                          }
                          $mysqli->query("SET NAMES 'utf8'");
                          $sql="SELECT iname FROM Spinnertest";
                          $result=$mysqli->query($sql);
                          while($e=mysqli_fetch_assoc($result))
                           {
$output[]=$e; 
                           }
print(json_encode($output)); 
$mysqli->close();
                           ?>
Step 3: Gradle Files

   include android {....} brfore buildToolsVersion 
useLibrary 'org.apache.http.legacy'
   incclude dependencies{....}
 compile 'com.loopj.android:android-async-http:1.4.5'
 compile 'com.android.support:design:23.0.0'
Step 4: AndroidManifest.xml
   Include user permission in your AndroidManifest File
<uses-permission android:name="android.permission.INTERNET" />
Step 5:  Spinner_layout.xml
   <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    
                    android:orientation="vertical"    
                    android:layout_width="match_parent"    
                    android:layout_height="match_parent>
    <TextView        
       android:id="@+id/txt"        
       android:layout_width="match_parent"        
       android:layout_height="wrap_content"      
       android:padding="10dp"        
       android:textSize="30dp"
       android:textColor="#000000" />
</LinearLayout>
Step 6:  Activity_Main.xml
                            <?xml version="1.0" encoding="utf-8"?>
              <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    
               xmlns:tools="http://schemas.android.com/tools"    
               android:layout_width="match_parent"    
               android:layout_height="match_parent"    
               android:orientation="vertical"    
               android:padding="10dp"    
               tools:context=".MainActivity"    
               android:weightSum="1">
              <TextView
               android:layout_width="match_parent"  
               android:layout_height="wrap_content"   
               android:text="Click Spinner"    
               android:gravity="center" 
               android:textSize="25dp" />
             <Spinner 
              android:id="@+id/spinner"   
              android:layout_width="match_parent"   
              android:layout_height="wrap_content"   
              android:layout_weight="0.07">
             </Spinner>
Step 7:  MainActivity.java
                          package com.spinnerexample;
             import android.app.ProgressDialog;
             import android.os.AsyncTask;
             import android.support.v7.app.ActionBarActivity;
             import android.os.Bundle;
             import android.support.v7.app.AppCompatActivity;
             import android.view.View;
             import android.widget.AdapterView;
             import android.widget.ArrayAdapter;
             import android.widget.Spinner;
             import android.widget.Toast;
             import org.apache.http.HttpEntity;
             import org.apache.http.HttpResponse;
             import org.apache.http.client.HttpClient;
             import org.apache.http.client.methods.HttpPost;
             import org.apache.http.impl.client.DefaultHttpClient;
             import org.json.JSONArray;
             import org.json.JSONException;
             import org.json.JSONObject;
             import java.io.BufferedReader;
             import java.io.IOException;
             import java.io.InputStream;
             import java.io.InputStreamReader;
             import java.util.ArrayList;
             public class MainActivity extends AppCompatActivity{
             ArrayList<String> listItems=new ArrayList<>();
             ArrayAdapter<String> adapter;
            Spinner sp;
            protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            sp=(Spinner)findViewById(R.id.spinner);
       adapter=new ArrayAdapter<String>(this,R.layout.spinner_layout,R.id.txt,listItems);
       sp.setAdapter(adapter);
       sp.setOnItemSelectedListener(
       new AdapterView.OnItemSelectedListener() {
       public void onItemSelected(
       AdapterView<?> parent, View view, int position, long id) {
       Toast.makeText(getApplicationContext(),listItems.get(position),
       Toast.LENGTH_LONG).show();
                    }
                    public void onNothingSelected(AdapterView<?> parent) {
                    }
                });
           }
            public void onStart(){
        super.onStart();
        BackTask bt=new BackTask();
        bt.execute();
    }
        private class BackTask extends AsyncTask<Void,Void,Void> {
        ProgressDialog loading;
        ArrayList<String> list;
        protected void onPreExecute(){
            super.onPreExecute();
       loading = ProgressDialog.show(MainActivity.this, "Please Wait",null, true, true);
            list=new ArrayList<>();
        }
        protected Void doInBackground(Void...params){
            InputStream is=null;
            String result="";
            try{
            HttpClient httpclient=new DefaultHttpClient();
            HttpPost httppost= new HttpPost("http://krishscs.esy.es/Spinner_test.php");
            HttpResponse response=httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
        // Get our response as a String.                is = entity.getContent();
            }catch(IOException e){
                e.printStackTrace();
            }
//convert response to string            try{
        BufferedReader reader = new BufferedReader(new InputStreamReader(is,"utf-8"));
                String line = null;
                while ((line = reader.readLine()) != null) {
                    result+=line;
                }
                is.close();
                //result=sb.toString();            }catch(Exception e){
                e.printStackTrace();
            }
// parse json data            try{
                JSONArray jArray =new JSONArray(result);
                for(int i=0;i<jArray.length();i++){
                    JSONObject jsonObject=jArray.getJSONObject(i);
 // add interviewee name to arraylist  list.add(jsonObject.getString("iname"));
                }
            }
            catch(JSONException e){
                e.printStackTrace();
            }
            return null;
        } protected void onPostExecute(Void result){
            listItems.addAll(list);
            adapter.notifyDataSetChanged();
            loading.dismiss();
  Toast.makeText(getApplicationContext(),"Loading Completed",Toast.LENGTH_LONG).show();
        }
    }
}