Mobile (Webview)

Pertama, pilih file HTML index-debug-standard.html dan ganti namanya menjadi index-mobile.html (Ini opsional atau Anda dapat membiarkannya saja seperti itu).

Kemudian, buka file HTML dan salin kode di bawah ini ke index situs web Anda atau masukkan file HTML. Tempel kode di dalam tag <head> Anda.

<html>
<head>
  <meta charset="UTF-8">
  <title>Enterprise Web Chat</title>
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1,user-scalable=no" />
  <link rel='stylesheet prefetch' href='https://fonts.googleapis.com/css?family=Open+Sans'>
  <link rel="stylesheet" href="css/indigo.css">
  <link rel="stylesheet" href="css/widget.css">
  <link rel="stylesheet" href="css/lightslider.css">
  <link rel="stylesheet" href="css/intlTelInput.css">
	<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1,user-scalable=no" />
	<style type="text/css">
		html {
			background: url(images/bg-login.svg) no-repeat;
			height: 100%;
			background-size: cover;
		}
	</style>
  <!-- <script src="https://maps.googleapis.com/maps/api/js?key=<KEY>&libraries=places"></script> -->
  <script src="https://www.google.com/recaptcha/api.js"></script>
  <!-- <script src="http://code.responsivevoice.org/responsivevoice.js"></script> -->
  <script src='js/jquery-2.1.3.min.js'></script>
  <script src='js/iframeResizer.contentWindow.js'></script>
  <script src='js/iframeResizer.js'></script>
  <script src='js/lightslider.js'></script>  
  <script src='js/lazyload.min.js'></script>  
  <script src="js/cryptojs/pbkdf2.js"></script>
  <script src="js/cryptojs/aes.js"></script>
  <script src="js/cipher/aes-util.js"></script>
  <script src="js/stp.js"></script>
  <script src="js/sjs.js"></script>
  <script src="js/chat.js"></script>
  <script src="js/fuse.js"></script>
  <script src="js/speech.js"></script>
  <script src="js/intlTelInput.js"></script>
  <script>
  $(document).ready(function() {
	    Chat.init({
	        header: 'Welcome to Our Chat',
	        login_sub_header: 'Please tell us about yourself',
	        connect_message: 'Do you have questions ? <br>Come chat with us, we are here to help you',
	        chat_sub_header: 'Our agent will serve you shortly',
			url: 'https://<host>:<port>',
			client_id: '<client_id>',
			client_secret: '<client_secret>',	
	        type_placeholder: 'Type message...',
			avatar: '<bot_image>',
			icon_avatar: '<icon_image>',
			agent_avatar: '<agent_image>',
	        enable_attachment: true,
	        enable_voice: true,
	        enable_speech: true,
	        enable_queue: true,
	        enable_history: true,
	        compatibility_mode: false,
	        queue_text: "⏰NOMOR URUT: ",
	        enable_campaign: false,
	        campaign_avatar: '<campaign_image>',
			campaign_title: '<campaign_title>',
	        campaign_text: 'Hello 👋, What do you think about our service ?',
	        campaign_timer: 5000,
	        campaign_menu: [{
	            "label": "<Campaign Label>",
	            "value": "<Campaign Payload>",
	            "icon": "<campaign_icon>"
	        }, {
	            "label": "<Campaign Label>",
	            "value": "<Campaign Payload>",
	            "icon": "<campaign_icon>"
	        }, {
	            "label": "<Campaign Label>",
	            "value": "<Campaign Payload>",
	            "icon": "<campaign_icon>"
	        }],
	        max_upload_message: "File size limit exceeded. Maximum filesize is [max_filesize]",
	        selection_topic_placeholder: "Please select a topic",
	        selection_topic_member: ["Product", "Service"],
	        selection_topic_non_member: ["Hai", "Hello"],
			member_mode: false,
	        selection_topic_placeholder: "Please select a topic",
	        enable_service_hour: false,
	        service_hour: [{
	                "days": "sunday",
	                "startHour": "00:00",
	                "endHour": "23:59",
	                "holiday": true
	            },
	            {
	                "days": "monday",
	                "startHour": "00:00",
	                "endHour": "23:59",
	                "holiday": true
	            },
	            {
	                "days": "tuesday",
	                "startHour": "00:00",
	                "endHour": "15:52",
	                "holiday": true
	            },
	            {
	                "days": "wednesday",
	                "startHour": "00:00",
	                "endHour": "23:59",
	                "holiday": true
	            },
	            {
	                "days": "thursday",
	                "startHour": "00:00",
	                "endHour": "23:59",
	                "holiday": true
	            },
	            {
	                "days": "friday",
	                "startHour": "00:00",
	                "endHour": "23:59",
	                "holiday": true
	            },
	            {
	                "days": "saturday",
	                "startHour": "00:00",
	                "endHour": "23:59",
	                "holiday": true
	            }
	        ],
	        channel_id_email: "25b7fe4f7bd81aa0533be4963972ac74", /* channel id email */
	        subject_email: "Of service hour ticket",
	        send_email_success_message: "Email sent successfully !<br/><br/>Thanks, we have received your question or your complaint",
	        process_send_email_message: "Sending Email...",
	        process_send_email_error_message: "Email sent failed !",
			is_waiting_text_icon: true
	    });
	});
  </script>
</head>
<body>  
</body>
</html>

Hapus semua file HTML tetapi pertahankan index-mobile.html sebagai gantinya.

Salin seluruh direktori live chat yang tersisa ke path yang Anda tentukan dari server hosting web Anda.

Asumsikan yang ingin Anda pilih adalah tema indigo, lalu buka index-mobile.html dan ubah kode menggunakan warna yang Anda inginkan.

<link rel="stylesheet" href="css/indigo.css">
  <link rel="stylesheet" href="css/widget.css">
  <link rel="stylesheet" href="css/lightslider.css">
  <link rel="stylesheet" href="css/intlTelInput.css">

Jangan lupa untuk menyesuaikan resource path yang ada di index-mobile.html yang digunakan untuk memuat file seperti js, CSS, atau gambar, sesuai dengan tempat resource disimpan di server Anda.

<html>
<head>
  <meta charset="UTF-8">
  <title>Enterprise Web Chat</title>
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1,user-scalable=no" />
  <link rel='stylesheet prefetch' href='https://fonts.googleapis.com/css?family=Open+Sans'>
  <link rel="stylesheet" href="css/indigo.css">
  <link rel="stylesheet" href="css/widget.css">
  <link rel="stylesheet" href="css/lightslider.css">
  <link rel="stylesheet" href="css/intlTelInput.css">
	<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1,user-scalable=no" />
	<style type="text/css">
		html {
			background: url(images/bg-login.svg) no-repeat;
			height: 100%;
			background-size: cover;
		}
	</style>
  <!-- <script src="https://maps.googleapis.com/maps/api/js?key=<KEY>&libraries=places"></script> -->
  <script src="https://www.google.com/recaptcha/api.js"></script>
  <!-- <script src="http://code.responsivevoice.org/responsivevoice.js"></script> -->
  <script src='js/jquery-2.1.3.min.js'></script>
  <script src='js/iframeResizer.contentWindow.js'></script>
  <script src='js/iframeResizer.js'></script>
  <script src='js/lightslider.js'></script>  
  <script src='js/lazyload.min.js'></script>  
  <script src="js/cryptojs/pbkdf2.js"></script>
  <script src="js/cryptojs/aes.js"></script>
  <script src="js/cipher/aes-util.js"></script>
  <script src="js/stp.js"></script>
  <script src="js/sjs.js"></script>
  <script src="js/chat.js"></script>
  <script src="js/fuse.js"></script>
  <script src="js/speech.js"></script>
  <script src="js/intlTelInput.js"></script>
  <script>
  $(document).ready(function() {
	    Chat.init({
	        header: 'Welcome to Our Chat',
	        login_sub_header: 'Please tell us about yourself',
	        connect_message: 'Do you have questions ? <br>Come chat with us, we are here to help you',
	        chat_sub_header: 'Our agent will serve you shortly',
			url: 'https://<host>:<port>',
			client_id: '<client_id>',
			client_secret: '<client_secret>',	
	        type_placeholder: 'Type message...',
			avatar: '<bot_image>',
			icon_avatar: '<icon_image>',
			agent_avatar: '<agent_image>',
	        enable_attachment: true,
	        enable_voice: true,
	        enable_speech: true,
	        enable_queue: true,
	        enable_history: true,
	        compatibility_mode: false,
	        queue_text: "⏰NOMOR URUT: ",
	        enable_campaign: false,
	        campaign_avatar: '<campaign_image>',
			campaign_title: '<campaign_title>',
	        campaign_text: 'Hello 👋, What do you think about our service ?',
	        campaign_timer: 5000,
	        campaign_menu: [{
	            "label": "<Campaign Label>",
	            "value": "<Campaign Payload>",
	            "icon": "<campaign_icon>"
	        }, {
	            "label": "<Campaign Label>",
	            "value": "<Campaign Payload>",
	            "icon": "<campaign_icon>"
	        }, {
	            "label": "<Campaign Label>",
	            "value": "<Campaign Payload>",
	            "icon": "<campaign_icon>"
	        }],
	        max_upload_message: "File size limit exceeded. Maximum filesize is [max_filesize]",
	        selection_topic_placeholder: "Please select a topic",
	        selection_topic_member: ["Product", "Service"],
	        selection_topic_non_member: ["Hai", "Hello"],
			member_mode: false,
	        selection_topic_placeholder: "Please select a topic",
	        enable_service_hour: false,
	        service_hour: [{
	                "days": "sunday",
	                "startHour": "00:00",
	                "endHour": "23:59",
	                "holiday": true
	            },
	            {
	                "days": "monday",
	                "startHour": "00:00",
	                "endHour": "23:59",
	                "holiday": true
	            },
	            {
	                "days": "tuesday",
	                "startHour": "00:00",
	                "endHour": "15:52",
	                "holiday": true
	            },
	            {
	                "days": "wednesday",
	                "startHour": "00:00",
	                "endHour": "23:59",
	                "holiday": true
	            },
	            {
	                "days": "thursday",
	                "startHour": "00:00",
	                "endHour": "23:59",
	                "holiday": true
	            },
	            {
	                "days": "friday",
	                "startHour": "00:00",
	                "endHour": "23:59",
	                "holiday": true
	            },
	            {
	                "days": "saturday",
	                "startHour": "00:00",
	                "endHour": "23:59",
	                "holiday": true
	            }
	        ],
	        channel_id_email: "25b7fe4f7bd81aa0533be4963972ac74", /* channel id email */
	        subject_email: "Of service hour ticket",
	        send_email_success_message: "Email sent successfully !<br/><br/>Thanks, we have received your question or your complaint",
	        process_send_email_message: "Sending Email...",
	        process_send_email_error_message: "Email sent failed !",
			is_waiting_text_icon: true
	    });
	});
  </script>
</head>
<body>  
</body>
</html>

Selanjutnya, sesuaikan url, client_id dan properti client_secret sesuai dengan konfigurasi channel back-end Anda. Silakan merujuk kembali ke bagian How to Connect Client to Live Chat Channel untuk informasi lebih lanjut.

Di bagian sebelumnya ditujukkan untuk meletakkan source code pada situs web yang sudah tersedia, sedangkan di bagian ini kita harus membuat host live chat secara mandiri.

Di bawah ini merupakan sample code untuk mengonfigurasi tampilan web Anda yang menampilkan index-mobile.html yang sudah dihosting.

Configure Web View

Anda perlu mengaktifkan Javascript dan DomStorage untuk LocalStorage.

webview.getSettings().setJavaScriptEnabled(true);
webview.getSettings().setDatabaseEnabled(true);
webview.getSettings().setDomStorageEnabled(true);

Sekarang Anda dapat memuat URL.

webview.loadUrl("https://hostname/webchat/index-debug-standard.html");

Untuk menyesuaikannya setelah load halaman selesai, Anda dapat menjalankan kode ini.

webview.setWebViewClient(new WebViewClient() {
     @Override
     public void onPageFinished(WebView view, String url) {
          progressBar.setVisibility(View.GONE);
          super.onPageFinished(view, url);
     }
});

Enable Voice to Text (Speech Recognition)

Untuk mengaktifkan fitur ini, pertama-tama Anda perlu mengaktifkan RECORD_AUDIO pada android manifest.

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

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

Kemudian, silahkan menginisialisasi Properties untuk mengaktifkan Record Audio Permission.

private static final int RECORD_AUDIO_REQUEST_CODE = 123;
private PermissionRequest permissionRequest;

permissionRequest property digunakan untuk mengakomodasi permintaan dari tampilan web yang akan diberikan akses nanti.

Saat ikon 'microphone' diklik, browser akan meminta izin ke perangkat, aplikasi Anda harus menangkap permintaan tersebut. dapat dilakukan dengan:

private void loadLiveChat() {
		...
		...

    webview.setWebChromeClient(new WebChromeClient() {
        @Override
        public void onPermissionRequest(PermissionRequest request) {
            if (request != null) {
                permissionRequest = request;
                askPermission();
            }
        }
    });
}

private void askPermission() {
    if (ContextCompat.checkSelfPermission(getApplicationContext(), 
						Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
        
				ActivityCompat.requestPermissions(
						MainActivity.this, 
						new String[]{Manifest.permission.RECORD_AUDIO}, 
						RECORD_AUDIO_REQUEST_CODE
				);
    } else {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            permissionRequest.grant(permissionRequest.getResources());
        }
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if(requestCode == RECORD_AUDIO_REQUEST_CODE){
        if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                permissionRequest.grant(permissionRequest.getResources());
            }
            Toast.makeText(getApplicationContext(), "Permission Granted", Toast.LENGTH_SHORT).show();
        }
    }
}

Enable Attachment

Anda perlu mengaktifkan izin untuk READ_EXTERNAL_STORAGE pada android manifest.

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

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

kemudian, inisialisasi Properties untuk mengakses file.

private static final int INPUT_FILE_REQUEST_CODE = 1;
private ValueCallback<Uri[]> mFilePathCallback;

Konfigurasi web view untuk mengakses akses file.

private void loadLiveChat() {
		...
    webview.getSettings().setLoadWithOverviewMode(true);
    webview.getSettings().setAllowFileAccess(true);
		...
		...
}

Saat ikon 'attachment' diklik, browser akan meminta untuk membuka penyimpanan perangkat. Dapat dilakukan dengan:

private void loadLiveChat() {
    ...
		...

    webview.setWebChromeClient(new WebChromeClient() {
        ...
				...
				@Override
        public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { 
            if (mFilePathCallback != null) {
                mFilePathCallback.onReceiveValue(null);
            }
            mFilePathCallback = filePathCallback;

            Intent chooserIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE);
            return true;
        }
    });
}

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        if (requestCode != INPUT_FILE_REQUEST_CODE || mFilePathCallback == null) {
            super.onActivityResult(requestCode, resultCode, data);
            return;
        }
        Uri[] results = null;
        if (resultCode == Activity.RESULT_OK) {
            if (data != null) {
                String dataString = data.getDataString();
                results = new Uri[]{Uri.parse(dataString)};
            }
        }
        mFilePathCallback.onReceiveValue(results);
        mFilePathCallback = null;
    }
}

Di bawah ini adalah contoh final code jika Anda sudah mengikuti langkah-langkah di atas.

package com.imi.dolphin.bella;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.webkit.PermissionRequest;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

public class MainActivity extends AppCompatActivity {

    /**
     * Properties to access file
     */
    private static final int INPUT_FILE_REQUEST_CODE = 1;
    private ValueCallback<Uri[]> mFilePathCallback;

    /**
     * Properties to enable Record Audio Permission
     * <p>
     * the permissionRequest property is used to accommodate requests from the web view that will be granted access later
     */
    private static final int RECORD_AUDIO_REQUEST_CODE = 123;
    private PermissionRequest permissionRequest;

    /**
     * Initial Component Web View and Progress Bar
     */
    private WebView webview;
    private ProgressBar progressBar;

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

        init();
        loadLiveChat();
    }

    /**
     * Configure Web View
     */
    @SuppressLint("SetJavaScriptEnabled")
    private void loadLiveChat() {
        webview.loadUrl("<Server URL>");

        // Configure WebView To set Enable Javascript True And To Activate DomStorage True For LocalStorage
        webview.getSettings().setJavaScriptEnabled(true);
        webview.getSettings().setDatabaseEnabled(true);
        webview.getSettings().setDomStorageEnabled(true);

        // Configure WebView to access file access
        webview.getSettings().setLoadWithOverviewMode(true);
        webview.getSettings().setAllowFileAccess(true);

        webview.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                progressBar.setVisibility(View.GONE);
                super.onPageFinished(view, url);
            }
        });
        webview.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onPermissionRequest(PermissionRequest request) {
                if (request != null) {
                    permissionRequest = request;
                    askPermission();
                }
            }

            @Override
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
                // Double check that we don't have any existing callbacks
                if (mFilePathCallback != null) {
                    mFilePathCallback.onReceiveValue(null);
                }
                mFilePathCallback = filePathCallback;

                Intent chooserIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE);
                return true;
            }
        });
    }

    /**
     * Binding Item
     */
    private void init() {
        webview = findViewById(R.id.web_view);
        progressBar = findViewById(R.id.progress_bar);
        progressBar.setVisibility(View.VISIBLE);
    }

    /**
     * ask permission for Record Audio
     */
    private void askPermission() {
        if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.RECORD_AUDIO}, RECORD_AUDIO_REQUEST_CODE);
        } else {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                permissionRequest.grant(permissionRequest.getResources());
            }
        }
    }

    /**
     * Catch permission from user
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == RECORD_AUDIO_REQUEST_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    permissionRequest.grant(permissionRequest.getResources());
                }
                Toast.makeText(getApplicationContext(), "Permission Granted", Toast.LENGTH_SHORT).show();
            }
        }
    }

    /**
     * Catch File data from user
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            if (requestCode != INPUT_FILE_REQUEST_CODE || mFilePathCallback == null) {
                super.onActivityResult(requestCode, resultCode, data);
                return;
            }
            Uri[] results = null;
            if (resultCode == Activity.RESULT_OK) {
                if (data != null) {
                    String dataString = data.getDataString();
                    results = new Uri[]{Uri.parse(dataString)};
                }
            }
            mFilePathCallback.onReceiveValue(results);
            mFilePathCallback = null;
        }
    }
}

Jika Anda ingin mencoba code kami, klik ini untuk memulai.

Last updated