Android Developer

เขียนแอพ Android การใช้งาน Line SDK กับ Line Login

ตัวอย่างนี้เป็นแนวทางสำหรับคนที่ต้องการเขียน API ของ Line SDK ส่วนของ Line Login ร่วมกับแอพพลิเคชันระบบปฏิบัติการ Android 

Line ได้เปิด Social API ให้กับนักพัฒนาแอพพลิเคชันและเกม ออกมา 2 ตัวคือ Line Login และ Message API ครับซึ่งตัวอย่างนี้เราจะใช้ Line Login ก่อน ซึ่งการทำงานก็ไม่มีอะไรมากครับ คือการ Authentication เข้าแอพพิลเคชัน หรือ เกมเหมือนการใช้ Facebook Login นั่นแหละ แต่เป็นการใช้ Line แทนนั่นเองครับ

ตัวอย่างจาก Line developer Portal

การสมัคร Line Developer

ไปที่ Line Developer (https://developers.line.me) ทำการสมัครเป็นนักพัฒนาครับ

ใช้ Line ID หรือ Email ของเราในการสมัครเป็นนักพัฒนา เปิดเมลเพื่อ Activated ยืนยันตัวตนครับ ระบบจะพาเรากลับไปยัง Developer Portal ใหม่

ใครใคร่สมัครเป็น ส่วนบุคคลเลือกแบบนี้
ใครใคร่สมัครเป็น ส่วนบุคคลเลือกแบบนี้

ให้เราเปิดใช้งาน Social API ของ Line Login

ไปเลือกที่ LINE Login ครับ

เลือกเป็น WEB และ NATIVE_APP ไปเลยเผื่อจะต่อยอดส่วนของ เว็บไซต์ด้วย หลังจากนั้นไปที่เมนู Download SDK เลือก LineSDK_android_4.0.0.zip ครับ ดาวน์โหลดมาแตกไฟล์ zip ให้เรียบร้อย

เราจะได้ Channel ID มาด้วย

คราวนี้เราก็มาออกแบบแอพพิลเคชันของเราบ้างดีกว่า เปิด Android Studio ขึ้นมาครับ สร้าง Basic Activity ใหม่ เลือกโหมดของ Solution เป็น Projects ครับไปยัง Folder ชื่อ libs นำไฟล์ .arr ของ Line SDK ไปวางในนั้นซะ

เปิดโหมด Project หา libs แล้วนำไฟล์ .aar ไปวาง

ตามตัวอย่าง

ทำการเปิด buil.Gradle ส่วนของ Project ขึ้นมาตั้งค่าตามนี้

allprojects {
    repositories {
        jcenter()
        flatDir {
            dirs 'libs'
        }
    }
}

ให้มีการ Flat ไปยัง Directory ที่ชื่อว่า “libs” หลังจากนั้นเปิด Gradle ของส่วน Module ขึ้นมา แก้ไขดังนี้ใน dependencies

compile(name:'line-sdk-4.0.0', ext:'aar')

ไฟล์จะเป็นแบบนี้

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.daydev.lineapidev"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.2.0'
    compile 'com.android.support:design:25.2.0'
    compile(name:'line-sdk-4.0.0', ext:'aar')
    testCompile 'junit:junit:4.12'
}

ไปที่ AndroidManiFest.xml เปิด Permission ของ Internet ครับ

<uses-permission android:name="android.permission.INTERNET" />

ต่อมาเรามาออกแบบหน้าจอ XML ของ content_activity.xml ดังนี้

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/content_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.daydev.lineapidev.MainActivity"
    tools:showIn="@layout/activity_main">

    <Button
        android:id="@+id/login_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Login with LINE"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:background="@color/colorPrimary"
        android:textColor="@android:color/background_light" />

    <Button
        android:id="@+id/browser_login_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Browser Login"
        android:layout_marginTop="45dp"
        android:layout_below="@+id/login_button"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:background="@color/colorPrimary"
        android:textColor="@android:color/background_light" />
</RelativeLayout>

ในการทำงานเราจะมีการแบ่ง Class ของ Activity เพิ่มมาคือส่วนของ Post Login และการเก็บค่า Channel ID ซึ่งเก็บใน strings.xml ก็ได้แต่ตัวอย่างเก็บไว้ใน Class ชื่อ Constants

ทำการสร้าง Java Class มาใหม่ใน Package ของเรา

ตั้งชื่อว่า Constants

ใน Class Constants.java เก็บ Channel ID ของเราครับ

package com.daydev.lineapidev;

/**
 * Created by banyapon on 3/5/2017 AD.
 */

public class Constants {

    // Set this value to your Channel ID
    public static final String CHANNEL_ID = "1XXXXXXXX4";
}

ไปที่ https://developers.line.me/ba/tech/ ส่วนของ Technical Configuration ทำการใส่ package name และ Hashkey ของ แอพพลิเคชันเราลงไป

Hash Key ให้ใส่ใน Android Package Signature วิธีการก็หาเอาใน Google ครับส่วนของ OS X ก็ข้างล่าง

เพิ่ม Activity ใหม่ขึ้นมาครับชื่อว่า PostLoginActivity

ออกแบบหน้าจอ content_post_login.xml ดังนี้

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/content_post_login"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.daydev.lineapidev.PostLoginActivity"
    tools:showIn="@layout/activity_post_login">
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <LinearLayout
                android:id="@+id/nameLayout"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/displayNameField"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_centerHorizontal="true"
                    android:text="TextView"
                    android:textAlignment="center"
                    android:textSize="24sp"
                    android:textStyle="normal|bold"
                    tools:text="Name" />

            </LinearLayout>

            <LinearLayout
                android:id="@+id/imageLayout"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/nameLayout"
                android:orientation="vertical">

                <ImageView
                    android:id="@+id/profileImageView"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_centerHorizontal="true"
                    app:srcCompat="@android:color/background_light" />
            </LinearLayout>

            <LinearLayout
                android:id="@+id/userDataLayout"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/imageLayout"
                android:orientation="vertical">

                <LinearLayout
                    android:id="@+id/userDataLayout"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_below="@+id/imageLayout"
                    android:orientation="vertical">


                    <TextView
                        android:id="@+id/textView9"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="User ID:"
                        android:textSize="18sp"
                        android:textStyle="normal|bold" />

                    <TextView
                        android:id="@+id/userIDField"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="TextView" />

                    <TextView
                        android:id="@+id/textView11"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Status Message:"
                        android:textAlignment="textStart"
                        android:textSize="18sp"
                        android:textStyle="normal|bold" />

                    <TextView
                        android:id="@+id/statusMessageField"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="TextView" />

                    <TextView
                        android:id="@+id/textView13"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="Access Token:"
                        android:textSize="18sp"
                        android:textStyle="normal|bold" />

                    <TextView
                        android:id="@+id/accessTokenField"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="TextView" />

                </LinearLayout>

            </LinearLayout>

            <LinearLayout
                android:id="@+id/buttonlayout"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/userDataLayout"
                android:orientation="vertical">

                <Button
                    android:id="@+id/profileButton"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:text="Get Profile" />

                <Button
                    android:id="@+id/refreshButton"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:text="Refresh Token" />

                <Button
                    android:id="@+id/verifyButton"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:text="Verify Token" />

                <Button
                    android:id="@+id/logoutButton"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:text="Logout" />
            </LinearLayout>

        </RelativeLayout>

    </ScrollView>
</RelativeLayout>

สร้าง Resource ใหม่ขึ้นมาชื่อว่า profile_dialog.xml

โดยมีโครงสร้าง xml ดังนี้

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/loadingPanel"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center">

        <ProgressBar
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:indeterminate="true" />
    </LinearLayout>


    <LinearLayout
        android:id="@+id/profileContent"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:visibility="invisible">


        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/holo_green_light"
            android:text="@string/profile_screen_label"
            android:textAlignment="center"
            android:textColor="@android:color/white"
            android:textSize="18sp"
            android:textStyle="normal|bold" />

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:id="@+id/textView5"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/profile_display_name_label"
                android:textSize="14sp"
                android:textStyle="normal|bold" />

            <TextView
                android:id="@+id/profileName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:id="@+id/textView6"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/profile_mid_label"
                android:textSize="14sp"
                android:textStyle="normal|bold" />

            <TextView
                android:id="@+id/profileMid"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:id="@+id/textView7"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/profile_status_message_label"
                android:textSize="14sp"
                android:textStyle="normal|bold" />

            <TextView
                android:id="@+id/profileMessage"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:id="@+id/textView8"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/profile_image_label"
                android:textSize="14sp"
                android:textStyle="normal|bold" />

            <TextView
                android:id="@+id/profileImageUrl"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="" />
        </LinearLayout>

    </LinearLayout>


</LinearLayout>

 

กำหนดค่า Strings.xml กันหน่อย ตามตัวอย่างเลย

<resources>
    <string name="app_name">เปิดสาขา DA ที่ DPU</string>
    <string name="action_settings">Settings</string>
    <string name="title_activity_post_login">PostLoginActivity</string>
    <string name="profile_screen_label">User Profile</string>
    <string name="profile_display_name_label">Display Name:</string>
    <string name="profile_mid_label">MID:</string>
    <string name="profile_status_message_label">Status Message:</string>
    <string name="profile_image_label">Profile Image URL:</string>
    <string name="no_profile_image_set">Profile Image Not Set</string>
</resources>

ต่อมาให้สร้าง Action ของ MainActivity.java ส่วนของปุ่มในการ Login ทั้งสองดังนี้

final Button a2aButton = (Button) findViewById(R.id.login_button);
        a2aButton.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {

                try {
                    // App to App Login
                    Intent LoginIntent = LineLoginApi.getLoginIntent(v.getContext(), Constants.CHANNEL_ID);
                    startActivityForResult(LoginIntent, REQUEST_CODE);

                } catch (Exception e) {
                    Log.e("ERROR", e.toString());
                }
            }
        });

        final Button browserLoginButton = (Button) findViewById(R.id.browser_login_button);
        browserLoginButton.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {

                try {
                    // Browser Login
                    Intent LoginIntent = LineLoginApi.getLoginIntentWithoutLineAppAuth(v.getContext(), Constants.CHANNEL_ID);
                    startActivityForResult(LoginIntent, REQUEST_CODE);

                } catch (Exception e) {
                    Log.e("ERROR", e.toString());
                }
            }

        });

โดยมีเมธอดใหม่เพิ่มเข้าไปคือ

public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode != REQUEST_CODE) {
            Log.e("ERROR", "Unsupported Request");
            return;
        }

        LineLoginResult result = LineLoginApi.getLoginResultFromIntent(data);

        switch (result.getResponseCode()) {

            case SUCCESS:

                Intent transitionIntent = new Intent(this, PostLoginActivity.class);
                transitionIntent.putExtra("line_profile", result.getLineProfile());
                transitionIntent.putExtra("line_credential", result.getLineCredential());
                startActivity(transitionIntent);
                break;

            case CANCEL:
                Log.e("ERROR", "LINE Login Canceled by user!!");
                break;

            default:
                Log.e("ERROR", "Login FAILED!");
                Log.e("ERROR", result.getErrorData().toString());
        }
    }

ภาพรวมไฟล์ MainActivity.java เป็นดังนี้

package com.daydev.lineapidev;

import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;

import com.linecorp.linesdk.auth.LineLoginApi;
import com.linecorp.linesdk.auth.LineLoginResult;

public class MainActivity extends AppCompatActivity {
    private static final int REQUEST_CODE = 1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        final Button a2aButton = (Button) findViewById(R.id.login_button);
        a2aButton.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {

                try {
                    // App to App Login
                    Intent LoginIntent = LineLoginApi.getLoginIntent(v.getContext(), Constants.CHANNEL_ID);
                    startActivityForResult(LoginIntent, REQUEST_CODE);

                } catch (Exception e) {
                    Log.e("ERROR", e.toString());
                }
            }
        });

        final Button browserLoginButton = (Button) findViewById(R.id.browser_login_button);
        browserLoginButton.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {

                try {
                    // Browser Login
                    Intent LoginIntent = LineLoginApi.getLoginIntentWithoutLineAppAuth(v.getContext(), Constants.CHANNEL_ID);
                    startActivityForResult(LoginIntent, REQUEST_CODE);

                } catch (Exception e) {
                    Log.e("ERROR", e.toString());
                }
            }

        });
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode != REQUEST_CODE) {
            Log.e("ERROR", "Unsupported Request");
            return;
        }

        LineLoginResult result = LineLoginApi.getLoginResultFromIntent(data);

        switch (result.getResponseCode()) {

            case SUCCESS:

                Intent transitionIntent = new Intent(this, PostLoginActivity.class);
                transitionIntent.putExtra("line_profile", result.getLineProfile());
                transitionIntent.putExtra("line_credential", result.getLineCredential());
                startActivity(transitionIntent);
                break;

            case CANCEL:
                Log.e("ERROR", "LINE Login Canceled by user!!");
                break;

            default:
                Log.e("ERROR", "Login FAILED!");
                Log.e("ERROR", result.getErrorData().toString());
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

 

ส่วนของ PostLoginActivity.java คือคำสั่งต่อไปนี้

package com.daydev.lineapidev;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.linecorp.linesdk.LineAccessToken;
import com.linecorp.linesdk.LineApiResponse;
import com.linecorp.linesdk.LineCredential;
import com.linecorp.linesdk.LineProfile;
import com.linecorp.linesdk.api.LineApiClient;
import com.linecorp.linesdk.api.LineApiClientBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

public class PostLoginActivity extends AppCompatActivity {

    private LineApiClient lineApiClient;

    // Method for preventing orientation changes during ASyncTasks
    private void lockScreenOrientation(){
        int currentOrientation = getResources().getConfiguration().orientation;
        if (currentOrientation == Configuration.ORIENTATION_PORTRAIT){
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        } else {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }
    }

    // This method is used to reenable orientation changes after an ASyncTask is finished.
    private void unlockScreenOrientation(){
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
    }

    public static class ProfileDialogFragment extends DialogFragment {

        private LineProfile profileInfo;

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {

            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
            LayoutInflater inflater = getActivity().getLayoutInflater();
            View view = inflater.inflate(R.layout.profile_dialog, null);


            TextView textview = (TextView) view.findViewById(R.id.profileName);
            textview.setText(profileInfo.getDisplayName());
            textview = (TextView) view.findViewById(R.id.profileMessage);
            textview.setText(profileInfo.getStatusMessage());
            textview = (TextView) view.findViewById(R.id.profileMid);
            textview.setText(profileInfo.getUserId());
            Uri pictureUrl = profileInfo.getPictureUrl();
            textview = (TextView) view.findViewById(R.id.profileImageUrl);

            // If the user's profile picture is not set, the picture url will be null.
            if (pictureUrl != null) {
                textview.setText(profileInfo.getPictureUrl().toString());
            } else {
                textview.setText(view.getContext().getResources().getString(R.string.no_profile_image_set));
            }

            view.findViewById(R.id.loadingPanel).setVisibility(View.GONE);
            view.findViewById(R.id.profileContent).setVisibility(View.VISIBLE);

            builder.setView(view);
            builder.setPositiveButton("OK", null);
            return builder.create();
        }

        public LineProfile getProfileInfo() {
            return profileInfo;
        }

        public void setProfileInfo(LineProfile profileInfo) {
            this.profileInfo = profileInfo;
        }
    }


    public class ImageLoaderTask extends AsyncTask<String, String, Bitmap> {

        final static String TAG = "ImageLoaderTask";

        protected void onPreExecute(){
            lockScreenOrientation();
        }

        protected Bitmap doInBackground(String... strings) {
            Bitmap bitmap = null;
            try {
                URL url = new URL(strings[0]);
                bitmap = BitmapFactory.decodeStream((InputStream) url.getContent());
            } catch (IOException e) {
                Log.e(TAG, e.getMessage());
            }
            return bitmap;
        }

        protected void onPostExecute(Bitmap bitmap) {
            ImageView profileImageView = (ImageView) findViewById(R.id.profileImageView);
            profileImageView.setImageBitmap(bitmap);
            unlockScreenOrientation();
        }
    }


    public class RefreshTokenTask extends AsyncTask<Void, Void, LineApiResponse<LineAccessToken>> {

        final static String TAG = "RefreshTokenTask";

        protected void onPreExecute(){
            lockScreenOrientation();
        }

        protected LineApiResponse<LineAccessToken> doInBackground(Void... params) {

            return lineApiClient.refreshAccessToken();
        }

        protected void onPostExecute(LineApiResponse<LineAccessToken> response) {

            if (response.isSuccess()) {
                String updatedAccessToken = lineApiClient.getCurrentAccessToken().getResponseData().getAccessToken();

                // Update the view
                TextView accessTokenField = (TextView) findViewById(R.id.accessTokenField);
                accessTokenField.setText(updatedAccessToken);
                Toast.makeText(getApplicationContext(), "Access Token has been refreshed.", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(getApplicationContext(), "Could not refresh the access token.", Toast.LENGTH_SHORT).show();
                Log.e(TAG, response.getErrorData().toString());
            }

            unlockScreenOrientation();
        }
    }

    public class VerifyTokenTask extends AsyncTask<Void, Void, LineApiResponse<LineCredential>> {

        final static String TAG = "VerifyTokenTask";

        protected void onPreExecute(){
            lockScreenOrientation();
        }

        protected LineApiResponse<LineCredential> doInBackground(Void... params) {

            return lineApiClient.verifyToken();
        }

        protected void onPostExecute(LineApiResponse<LineCredential> response) {

            if (response.isSuccess()) {
                StringBuilder toastStringBuilder = new StringBuilder("Access Token is VALID and contains the permissions ");

                for (String temp : response.getResponseData().getPermission()) {
                    toastStringBuilder.append(temp + ", ");
                }
                Toast.makeText(getApplicationContext(), toastStringBuilder.toString(), Toast.LENGTH_SHORT).show();

            } else {
                Toast.makeText(getApplicationContext(), "Access Token is NOT VALID", Toast.LENGTH_SHORT).show();
            }
            unlockScreenOrientation();
        }
    }

    public class GetProfileTask extends AsyncTask<Void, Void, LineApiResponse<LineProfile>> {

        private ProfileDialogFragment fragment;

        final static String TAG = "GetProfileTask";

        protected void onPreExecute(){
            lockScreenOrientation();
        }

        protected LineApiResponse<LineProfile> doInBackground(Void... params) {
            return lineApiClient.getProfile();
        }

        protected void onPostExecute(LineApiResponse<LineProfile> apiResponse) {

            if(apiResponse.isSuccess()) {
                ProfileDialogFragment newFragment = new ProfileDialogFragment();
                newFragment.setProfileInfo(apiResponse.getResponseData());
                newFragment.show(getFragmentManager(), null);
                unlockScreenOrientation();
            } else {
                Toast.makeText(getApplicationContext(), "Failed to get profile.", Toast.LENGTH_SHORT).show();
                Log.e(TAG, "Failed to get Profile: " + apiResponse.getErrorData().toString());
            }
        }
    }

    public class LogoutTask extends AsyncTask<Void, Void, LineApiResponse> {

        final static String TAG = "LogoutTask";

        protected void onPreExecute(){
            lockScreenOrientation();
        }

        protected LineApiResponse doInBackground(Void... params) {
            return lineApiClient.logout();
        }

        protected void onPostExecute(LineApiResponse apiResponse){

            if(apiResponse.isSuccess()){
                Toast.makeText(getApplicationContext(), "Logout Successful", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(getApplicationContext(), "Logout Failed", Toast.LENGTH_SHORT).show();
                Log.e(TAG, "Logout Failed: " + apiResponse.getErrorData().toString());
            }
            unlockScreenOrientation();
        }
    }

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_post_login);

        LineApiClientBuilder apiClientBuilder = new LineApiClientBuilder(getApplicationContext(), Constants.CHANNEL_ID);
        lineApiClient = apiClientBuilder.build();

        // Profile Button Click Listener
        final Button profileButton = (Button) findViewById(R.id.profileButton);

        profileButton.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
                new GetProfileTask().execute();
            }
        });


        // Refresh Button Click Listener
        final Button refreshButton = (Button) findViewById(R.id.refreshButton);
        refreshButton.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {

                new RefreshTokenTask().execute();
            }

        });

        // Verify Button Click Listener
        final Button verifyButton = (Button) findViewById(R.id.verifyButton);
        verifyButton.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {

                new VerifyTokenTask().execute();
            }

        });

        // Logout Button Click Listener
        final Button logoutButton = (Button) findViewById(R.id.logoutButton);
        logoutButton.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {

                new LogoutTask().execute();
                finish();
            }

        });

        // Get the intent so that we can get information from the previous activity
        Intent intent = getIntent();
        LineProfile intentProfile = intent.getParcelableExtra("line_profile");
        LineCredential intentCredential = intent.getParcelableExtra("line_credential");

        ImageView profileImageView = (ImageView) findViewById(R.id.profileImageView);
        Uri pictureUrl = intentProfile.getPictureUrl();

        if (pictureUrl != null) {
            Log.i("PostLoginActivity", "Picture URL: " + pictureUrl.toString());
            new ImageLoaderTask().execute(pictureUrl.toString());
        }

        TextView profileText;

        profileText = (TextView) findViewById(R.id.displayNameField);
        profileText.setText(intentProfile.getDisplayName());

        profileText = (TextView) findViewById(R.id.userIDField);
        profileText.setText(intentProfile.getUserId());

        profileText = (TextView) findViewById(R.id.statusMessageField);
        profileText.setText(intentProfile.getUserId());

        profileText = (TextView) findViewById(R.id.accessTokenField);
        profileText.setText(intentCredential.getAccessToken().getAccessToken());

    }

}

เพิ่ม Activity state ของ AndroidManiFest.xml ดังนี้

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.daydev.lineapidev">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".PostLoginActivity" android:label="User Information"></activity>
    </application>

</manifest>

ทดสอบโดยการ Run ตัวแอพพลิเคชันของเราแล้วทำการ Login ด้วย Line ดูเราจะพบว่า เราจะขอสิทธิในการ Login และ Permission ของ User ใน Line จากแอพพลิเคชัน Line ของเราได้แล้ว

 

จะเห็นว่าการออกแบบ Line APIต่อไปก็คือการ Identity Thief มากขึ้นแบบที่ แอพขำขันทำกัน คำถามคือถ้าผมบอกว่า ขอให้เชื่อใจผม เค้าจะยอมไหมนะ เพราะกระบวนการนี้ได้มาซึ่ง token ซึ่งผมอาจจะแอบเก็บไว้ทำอะไรก็ได้ทีหลังอยู่ดี

ใครขี้เกียจเขียน Code เองมี git ของ Line ให้นะเค้าทำไว้ https://github.com/line/line-sdk-starter-android-v2

Asst. Prof. Banyapon Poolsawas

อาจารย์ประจำสาขาวิชาการออกแบบเชิงโต้ตอบ และการพัฒนาเกม วิทยาลัยครีเอทีฟดีไซน์ & เอ็นเตอร์เทนเมนต์เทคโนโลยี มหาวิทยาลัยธุรกิจบัณฑิตย์ ผู้ก่อตั้ง บริษัท Daydev Co., Ltd, (เดย์เดฟ จำกัด)

Related Articles

Back to top button

Adblock Detected

เราตรวจพบว่าคุณใช้ Adblock บนบราวเซอร์ของคุณ,กรุณาปิดระบบ Adblock ก่อนเข้าอ่าน Content ของเรานะครับ, ถือว่าช่วยเหลือกัน