Monday, October 9, 2017

android - Handle mailto link in WebView

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/base_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#fbfffc"
    >
    <TextView
        android:id="@+id/text_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="8dp"
        android:textColor="#0084ff"
        />
    <WebView
        android:id="@+id/web_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        />
</LinearLayout>
MainActivity.java

package com.cfsuman.me.androidcodesnippets;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
import android.widget.Toast;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;


public class MainActivity extends AppCompatActivity {
    private Context mContext;
    private Activity mActivity;

    private WebView mWebView;
    private TextView mTextView;


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

        // Get the application context
        mContext = getApplicationContext();
        mActivity = MainActivity.this;

        // Get the widget reference from xml layout
        mWebView = findViewById(R.id.web_view);
        mTextView = findViewById(R.id.text_view);

        // Toast the current api level
        Toast.makeText(mContext,"API LEVEL: "+Build.VERSION.SDK_INT,Toast.LENGTH_SHORT).show();

        // Set the web view client
        mWebView.setWebViewClient(new WebViewClient(){

            // For api level bellow 24
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url){
                Toast.makeText(mContext, "Old Method",Toast.LENGTH_SHORT).show();

                if(url.startsWith("http")){
                    Toast.makeText(mContext,"Page link",Toast.LENGTH_SHORT).show();
                    // Return false means, web view will handle the link
                    return false;
                }else if(url.startsWith("mailto")){
                    // Handle the mailto link
                    handleMailToLink(url);

                    // Return true means, leave the current web view and handle the url itself
                    return true;
                }

                return false;
            }

            // From api level 24
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request){
                Toast.makeText(mContext, "New Method",Toast.LENGTH_SHORT).show();

                // Get the mailto url
                String url = request.getUrl().toString();

                if(url.startsWith("http")){
                    Toast.makeText(mContext,"Page link",Toast.LENGTH_SHORT).show();
                    // Return false means, web view will handle the link
                    return false;
                }else if(url.startsWith("mailto")){
                    // Handle the mailto link
                    handleMailToLink(url);

                    // Return true means, leave the current web view and handle the url itself
                    return true;
                }

                return false;
            }
        });

        // Load the url into web view
        mWebView.loadUrl("http://www.rapidtables.com/web/html/mailto.htm");
    }


    /*
        Variables in mailto links:
            mailto: recipient, or recipients, separate with comma
            &cc= cc recipient(s)
            &bcc= bcc recipient(s)
            &subject= mail subject
            &body= mail body
    */

    // Custom method to handle web view mailto link
    protected void handleMailToLink(String url){
        // Initialize a new intent which action is send
        Intent intent = new Intent(Intent.ACTION_SENDTO);

        // For only email app handle this intent
        intent.setData(Uri.parse("mailto:"));

        // Empty the text view
        mTextView.setText("");

        // Extract the email address from mailto url
        String to = url.split("[:?]")[1];
        if(!TextUtils.isEmpty(to)){
            String[] toArray = to.split(";");
            // Put the primary email addresses array into intent
            intent.putExtra(Intent.EXTRA_EMAIL,toArray);
            mTextView.append("TO : " + to);
        }

        // Extract the cc
        if(url.contains("cc=")){
            String cc = url.split("cc=")[1];
            if(!TextUtils.isEmpty(cc)){
                //cc = cc.split("&")[0];
                cc = cc.split("&")[0];
                String[] ccArray = cc.split(";");
                // Put the cc email addresses array into intent
                intent.putExtra(Intent.EXTRA_CC,ccArray);
                mTextView.append("\nCC : " + cc );
            }
        }else {
            mTextView.append("\n" + "No CC");
        }

        // Extract the bcc
        if(url.contains("bcc=")){
            String bcc = url.split("bcc=")[1];
            if(!TextUtils.isEmpty(bcc)){
                //cc = cc.split("&")[0];
                bcc = bcc.split("&")[0];
                String[] bccArray = bcc.split(";");
                // Put the bcc email addresses array into intent
                intent.putExtra(Intent.EXTRA_BCC,bccArray);
                mTextView.append("\nBCC : " + bcc );
            }
        }else {
            mTextView.append("\n" + "No BCC");
        }

        // Extract the subject
        if(url.contains("subject=")){
            String subject = url.split("subject=")[1];
            if(!TextUtils.isEmpty(subject)){
                subject = subject.split("&")[0];
                // Encode the subject
                try{
                    subject = URLDecoder.decode(subject,"UTF-8");
                }catch (UnsupportedEncodingException e){
                    e.printStackTrace();
                }
                // Put the mail subject into intent
                intent.putExtra(Intent.EXTRA_SUBJECT,subject);
                mTextView.append("\nSUBJECT : " + subject );
            }
        }else {
            mTextView.append("\n" + "No SUBJECT");
        }

        // Extract the body
        if(url.contains("body=")){
            String body = url.split("body=")[1];
            if(!TextUtils.isEmpty(body)){
                body = body.split("&")[0];
                // Encode the body text
                try{
                    body = URLDecoder.decode(body,"UTF-8");
                }catch (UnsupportedEncodingException e){
                    e.printStackTrace();
                }
                // Put the mail body into intent
                intent.putExtra(Intent.EXTRA_TEXT,body);
                mTextView.append("\nBODY : " + body );
            }
        }else {
            mTextView.append("\n" + "No BODY");
        }

        // Email address not null or empty
        if(!TextUtils.isEmpty(to)){
            if(intent.resolveActivity(getPackageManager())!=null){
                // Finally, open the mail client activity
                startActivity(intent);
            }else {
                Toast.makeText(mContext,"No email client found.",Toast.LENGTH_SHORT).show();
            }
        }

    }
}