LINE の LIFF 開発超入門 : LIFF SDK を使った Web アプリの開発

# 本記事の概要

この記事では LINE で提供されている Line Front-end Framework (LIFF) を使ったページの開発方法をチュートリアル形式で記載しています。カバーする内容は LIFF の基本機能をはじめ、Bot との連携例や CLI ツールを使った登録から展開など、LIFF を使うにあたって必要な知識となります。

尚、本記事で利用するコードは [line-liff-starter](https://github.com/line/line-liff-starter) より一部拝借してします。
また最終系は [こちらのレポジトリ](https://github.com/kenakamu/LINE-LIFF-Sample/) にあります。

# LIFF アプリとは
LIFF SDK を利用して開発した Web ページの事であり、登録時に取得できる専用のアドレスに LINE からアクセスすることで動作するアプリケーションとなります。つまり、LIFF アプリの開発は LIFF SDK を埋め込んだ Web ページを開発することです。


# 必要なスキルと環境

- LINE Bot の基本的な知識
- [Visual Studio Code](https://code.visualstudio.com/) の基本的な操作方法
- [Azure サブスクリプション](https://azure.microsoft.com/ja-jp/free/)
- [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest) 
- [git](https://git-scm.com/download)
- [LIFF CLI](https://qiita.com/kenakamu/items/5a9cbdc32c4575e53c59)

※ この記事では Microsoft Azure を利用しますが、LIFF を利用するサイトのホストは任意です。

# 事前準備

## チャネルの作成

[こちらのページ](https://developers.line.me/ja/docs/liff/getting-started/) を参考にチャネルを作成します。チャネル作成後、チャネルアクセストークンを発行してコピーしておきます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/214116/d63d4afe-08e3-e383-bd53-111dee845ea3.png" width=600/>

また「Your user ID」も後ほど利用するためコピーしておきます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/214116/fd5fb84a-e0e8-556d-d1bd-f048f8dfaa51.png" width=600/>

## Azure 環境の準備

Azure ポータルを使い慣れている場合はポータルからの操作でもいいですが、今回は Azure CLI を使います。また Heroku など他のサービスを使っている場合はそちらでも結構です。

1\. まだインストールしていない場合は、[Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest) をインストール。もしくは [Azure ポータル](https://portal.azure.com) ログイン後、画面右上の Cloud Shell よりコンソールを起動。

<img src="https://qiita-image-store.s3.amazonaws.com/0/214116/7287ecb7-702d-e17d-351c-2304ccf2bc20.png" width=600/>

2\. Cloud Shall の場合は、手順 4 に進む。コンソールの場合は、まず以下のコマンドでログインを実行。

```
az login
```

3\. 画面の指示に順ってログインを完了。

4\. ログイン完了後、複数の Azure サブスクリプションがある場合は、以下のコマンドで使うサブスクリプションをセット。

```
az account list
az account set -s 'subscription id'
az account show
```
5\. まず以下のコマンドでリソースグループを lineliffsample として、地域を東日本で作成。

```
az group create -n lineliffsample -l japaneast
```

6\. 次に LIFF アプリケーションのデプロイ先となる WebApps を作成。作成時には、まずサービスプランを作成し、WebApp を作成します。名前はグローバルで一意になるものを指定。

```
az appservice plan create -n lineliffappplan -g lineliffsample --sku F1
az webapp create -n <ユニークな WebApp の名前> -g lineliffsample -p lineliffappplan
```

7\. git でデプロイできるように指定。返り値が git のリモートレポジトリとなるため保存しておく。

```
az webapp deployment user set --user-name <ユーザー名> --password <パスワード>
az webapp deployment source config-local-git -n <ユニークな WebApp の名前> -g lineliffsample
```

## LIFF CLI と既存のサイトを使った LIFF の登録およびテスト

LIFF は LIFF SDK を使った　Web ページで最大効果を発揮しますが、既存のページを指定してすぐに使うことも可能です。ここではまず LIFF 登録の概念を把握するため、既存のページ (https://linecorp.com/ja/) を登録してみます。

1\. Liff npm パッケージをまだ入れていない場合、npm でインストール。

```
npm install -g liff
```

2\. liff init で初期化。上記で取得したチャネルのアクセストークンを渡す。

```
liff init <チャネルアクセストークン>
```

3\. LIFF アプリケーションの登録。ここではサイズとして tall を指定。サイズは full, tall, compact がある。

```
liff add https://linecorp.com/ja/ tall
```

4\. 戻り値から Liff ID および Accessible URL を確認。

<img src="https://qiita-image-store.s3.amazonaws.com/0/214116/a9469abf-dcba-5d16-cb43-52982a003b35.png" width=500/>

5\. 以下 liff send コマンドでリンクを送付するか、LIFF アドレスを手動で LINE へ送付。LINE アプリよりリンクをクリックしてテスト。

```
liff send <LIFF ID> <User ID>
```

<img src="https://qiita-image-store.s3.amazonaws.com/0/214116/dc22e480-0369-1981-ffb8-63b323c02a74.png" width=300 />

# LIFF アプリの開発

では LIFF SDK を使ったアプリを開発していきます。

## プロジェクトの作成と LIFF SDK の読み込み

1\. 任意のディレクトに MyFirstLiff フォルダを作成し、Visual Studio Code で開く。

```shell
mkdir MyFirstLiff
cd MyFirstLiff
code .
```
2\. Visual Studio Code で新しく index.html ファイルを追加。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/865c2a24-cbe8-ba88-7dfc-2e37a081984c.png)

3\. index.html の中身に以下のコードをペースト

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>My First LIFF</title>
</head>
<body>
    <div id="liffdata">
        <h2>LIFF Data</h2>
        <table border="1">
            <tr>
                <th>language</th>
                <td id="languagefield"></td>
            </tr>
            <tr>
                <th>context.viewType</th>
                <td id="viewtypefield"></td>
            </tr>
            <tr>
                <th>context.userId</th>
                <td id="useridfield"></td>
            </tr>
            <tr>
                <th>context.utouId</th>
                <td id="utouidfield"></td>
            </tr>
            <tr>
                <th>context.roomId</th>
                <td id="roomidfield"></td>
            </tr>
            <tr>
                <th>context.groupId</th>
                <td id="groupidfield"></td>
            </tr>
        </table>
    </div>
    
    <!-- LIFF SDK の読み込み -->
    <script src="https://d.line-scdn.net/liff/1.0/sdk.js"></script>
    <script src="liff.js"></script>
</body>
</html>
```

4\. 同じディレクトリに liff.js を追加し、以下コードをペースト。

```javascript
window.onload = function (e) {
    // init で初期化。基本情報を取得。
    // https://developers.line.me/ja/reference/liff/#initialize-liff-app
    liff.init(function (data) {
        initializeApp(data);
    });
};

function initializeApp(data) {
    document.getElementById('languagefield').textContent = data.language;
    document.getElementById('viewtypefield').textContent = data.context.viewType;
    document.getElementById('useridfield').textContent = data.context.userId;
    document.getElementById('utouidfield').textContent = data.context.utouId;
    document.getElementById('roomidfield').textContent = data.context.roomId;
    document.getElementById('groupidfield').textContent = data.context.groupId;
}
```

5\. 全ての保存。

### LIFF アプリケーションの展開

この段階で一旦 LIFF アプリの公開と登録を行います。

1\. まずレポジトリの初期化。Visual Studio Code より統合コンソールを開き、以下コマンドを実行。

```
git init
```

2\. 次に発行先を設定。アドレスは WebApp 作成時に取得したものを使用。

```
git remote add origin <上記手順で取得したリモート git アドレス> 
```

3\. ファイルの追加とコミット。

```
git add .
git commit -m "初回コミット"
```

4\. Push でデプロイの実行。

```
git push -u origin master
``` 

5\. LIFF CLI でアプリの登録。

```
liff add <Web App のアドレス> tall
```

6\. 戻り値を liff send か手動で LINE に送付して SDK の動作を確認。ログインしているユーザーの ID や言語が取得できる。

<img src="https://qiita-image-store.s3.amazonaws.com/0/214116/75a77a89-fc54-2a99-6dfc-d1d6e670925f.png" width=300/>

## SDK を使ったユーザープロファイルの取得

1\. index.html のコードを以下に変更。

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>My First LIFF</title>
</head>
<body>   
    <div id="profileinfo">
        <h2>Profile</h2>
        <div id="profilepicturediv">
        </div>
        <table border="1">
            <tr>
                <th>userId</th>
                <td id="useridprofilefield"></td>
            </tr>
            <tr>
                <th>displayName</th>
                <td id="displaynamefield"></td>
            </tr>
            <tr>
                <th>statusMessage</th>
                <td id="statusmessagefield"></td>
            </tr>
        </table>
    </div>

    <div id="liffdata">
        <h2>LIFF Data</h2>
        <table border="1">
            <tr>
                <th>language</th>
                <td id="languagefield"></td>
            </tr>
            <tr>
                <th>context.viewType</th>
                <td id="viewtypefield"></td>
            </tr>
            <tr>
                <th>context.userId</th>
                <td id="useridfield"></td>
            </tr>
            <tr>
                <th>context.utouId</th>
                <td id="utouidfield"></td>
            </tr>
            <tr>
                <th>context.roomId</th>
                <td id="roomidfield"></td>
            </tr>
            <tr>
                <th>context.groupId</th>
                <td id="groupidfield"></td>
            </tr>
        </table>
    </div>
    
    <!-- LIFF SDK の読み込み -->
    <script src="https://d.line-scdn.net/liff/1.0/sdk.js"></script>
    <script src="liff.js"></script>
</body>
</html>
```

2\. liff.js を以下のコードと差し替え。

```javascript
window.onload = function (e) {
    // init で初期化。基本情報を取得。
    // https://developers.line.me/ja/reference/liff/#initialize-liff-app
    liff.init(function (data) {
        getProfile();
        initializeApp(data);
    });
};

// プロファイルの取得と表示
function getProfile(){
    // https://developers.line.me/ja/reference/liff/#liffgetprofile()
    liff.getProfile().then(function (profile) {
        document.getElementById('useridprofilefield').textContent = profile.userId;
        document.getElementById('displaynamefield').textContent = profile.displayName;

        var profilePictureDiv = document.getElementById('profilepicturediv');
        if (profilePictureDiv.firstElementChild) {
            profilePictureDiv.removeChild(profilePictureDiv.firstElementChild);
        }
        var img = document.createElement('img');
        img.src = profile.pictureUrl;
        img.alt = "Profile Picture";
        img.width = 200;
        profilePictureDiv.appendChild(img);

        document.getElementById('statusmessagefield').textContent = profile.statusMessage;
    }).catch(function (error) {
        window.alert("Error getting profile: " + error);
    });
}

function initializeApp(data) {
    document.getElementById('languagefield').textContent = data.language;
    document.getElementById('viewtypefield').textContent = data.context.viewType;
    document.getElementById('useridfield').textContent = data.context.userId;
    document.getElementById('utouidfield').textContent = data.context.utouId;
    document.getElementById('roomidfield').textContent = data.context.roomId;
    document.getElementById('groupidfield').textContent = data.context.groupId;
}
```

3\. git で変更のコミットしてプッシュ。

```
git commit -am "add profile"
git push origin master
```

4\. LIFF アプリケーションのアドレスは変わっていないため、先ほどテストで送ったアドレスをクリックして動作を確認。

<img src="https://qiita-image-store.s3.amazonaws.com/0/214116/e0c6842e-e492-3119-9921-23a6afb300d9.png" width="300"/>

## LIFF よりメッセージの送信

LIFF 上のボタンクリックイベントなどから、チャットウィンドウにメッセージを送ることも出来ます。これで Bot と LIFF のシームレスな連携が可能となります。ここではテキストとスタンプを例として実装しますが、他のタイプもサポートされます。

詳細は [liff.sendMessages()](https://developers.line.me/ja/reference/liff/#liffsendmessages()) 参照。
1\. index.html を以下のコードに差し替え。

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>My First LIFF</title>
</head>
<body>   
    <button id="sendmessagebutton">メッセージ送信</button>
    <div id="profileinfo">
        <h2>Profile</h2>
        <div id="profilepicturediv">
        </div>
        <table border="1">
            <tr>
                <th>userId</th>
                <td id="useridprofilefield"></td>
            </tr>
            <tr>
                <th>displayName</th>
                <td id="displaynamefield"></td>
            </tr>
            <tr>
                <th>statusMessage</th>
                <td id="statusmessagefield"></td>
            </tr>
        </table>
    </div>

    <div id="liffdata">
        <h2>LIFF Data</h2>
        <table border="1">
            <tr>
                <th>language</th>
                <td id="languagefield"></td>
            </tr>
            <tr>
                <th>context.viewType</th>
                <td id="viewtypefield"></td>
            </tr>
            <tr>
                <th>context.userId</th>
                <td id="useridfield"></td>
            </tr>
            <tr>
                <th>context.utouId</th>
                <td id="utouidfield"></td>
            </tr>
            <tr>
                <th>context.roomId</th>
                <td id="roomidfield"></td>
            </tr>
            <tr>
                <th>context.groupId</th>
                <td id="groupidfield"></td>
            </tr>
        </table>
    </div>
    
    <!-- LIFF SDK の読み込み -->
    <script src="https://d.line-scdn.net/liff/1.0/sdk.js"></script>
    <script src="liff.js"></script>
</body>
</html>
```

2\. liff.js を以下のコードに差し替え。

```javascript
window.onload = function (e) {
    // init で初期化。基本情報を取得。
    // https://developers.line.me/ja/reference/liff/#initialize-liff-app
    liff.init(function (data) {
        getProfile();
        initializeApp(data);
    });

    // メッセージの送信
    document.getElementById('sendmessagebutton').addEventListener('click', function () {
        // https://developers.line.me/ja/reference/liff/#liffsendmessages()
        liff.sendMessages([{
            type: 'text',
            text: "テキストメッセージの送信"
        }, {
            type: 'sticker',
            packageId: '2',
            stickerId: '144'
        }]).then(function () {
            window.alert("送信完了");
        }).catch(function (error) {
            window.alert("Error sending message: " + error);
        });
    });
};

// プロファイルの取得と表示
function getProfile(){
    // https://developers.line.me/ja/reference/liff/#liffgetprofile()
    liff.getProfile().then(function (profile) {
        document.getElementById('useridprofilefield').textContent = profile.userId;
        document.getElementById('displaynamefield').textContent = profile.displayName;

        var profilePictureDiv = document.getElementById('profilepicturediv');
        if (profilePictureDiv.firstElementChild) {
            profilePictureDiv.removeChild(profilePictureDiv.firstElementChild);
        }
        var img = document.createElement('img');
        img.src = profile.pictureUrl;
        img.alt = "Profile Picture";
        img.width = 200;
        profilePictureDiv.appendChild(img);

        document.getElementById('statusmessagefield').textContent = profile.statusMessage;
    }).catch(function (error) {
        window.alert("Error getting profile: " + error);
    });
}

function initializeApp(data) {
    document.getElementById('languagefield').textContent = data.language;
    document.getElementById('viewtypefield').textContent = data.context.viewType;
    document.getElementById('useridfield').textContent = data.context.userId;
    document.getElementById('utouidfield').textContent = data.context.utouId;
    document.getElementById('roomidfield').textContent = data.context.roomId;
    document.getElementById('groupidfield').textContent = data.context.groupId;
}
```

3\. git で変更のコミットしてプッシュ。

```
git commit -am "add send message"
git push origin master
```

4\. LIFF アプリケーションのアドレスは変わっていないため、先ほどテストで送ったアドレスをクリックして動作を確認。

<img src="https://qiita-image-store.s3.amazonaws.com/0/214116/39f5d489-9d11-47d5-2659-60eab4aae102.png" width="300"/>

<img src="https://qiita-image-store.s3.amazonaws.com/0/214116/01f3b06f-c013-3755-3653-5205547c1ad4.png" width="300"/>

<img src="https://qiita-image-store.s3.amazonaws.com/0/214116/66f8228b-69ce-a59c-585c-0f94d216f931.png" width="300"/>


## LIFF アプリより別ウィンドウを開く

LIFF アプリ内で指定した URL を、LINEアプリ 内ブラウザまたは外部ブラウザで開きます。

1\. index.html を以下のコードに差し替え。

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>My First LIFF</title>
</head>
<body>   
    <button id="openwindowbutton">ウィンドウを LINE 内で開く</button>
    <button id="openwindowexternalbutton">ウィンドウを外部ブラウザで開く</button>
    <button id="sendmessagebutton">メッセージ送信</button>
    <div id="profileinfo">
        <h2>Profile</h2>
        <div id="profilepicturediv">
        </div>
        <table border="1">
            <tr>
                <th>userId</th>
                <td id="useridprofilefield"></td>
            </tr>
            <tr>
                <th>displayName</th>
                <td id="displaynamefield"></td>
            </tr>
            <tr>
                <th>statusMessage</th>
                <td id="statusmessagefield"></td>
            </tr>
        </table>
    </div>

    <div id="liffdata">
        <h2>LIFF Data</h2>
        <table border="1">
            <tr>
                <th>language</th>
                <td id="languagefield"></td>
            </tr>
            <tr>
                <th>context.viewType</th>
                <td id="viewtypefield"></td>
            </tr>
            <tr>
                <th>context.userId</th>
                <td id="useridfield"></td>
            </tr>
            <tr>
                <th>context.utouId</th>
                <td id="utouidfield"></td>
            </tr>
            <tr>
                <th>context.roomId</th>
                <td id="roomidfield"></td>
            </tr>
            <tr>
                <th>context.groupId</th>
                <td id="groupidfield"></td>
            </tr>
        </table>
    </div>
    
    <!-- LIFF SDK の読み込み -->
    <script src="https://d.line-scdn.net/liff/1.0/sdk.js"></script>
    <script src="liff.js"></script>
</body>
</html>
```

2\. liff.js を以下のコードに差し替え。

```javascript
window.onload = function (e) {
    // init で初期化。基本情報を取得。
    // https://developers.line.me/ja/reference/liff/#initialize-liff-app
    liff.init(function (data) {
        getProfile();
        initializeApp(data);
    });

    // ウィンドウを開く
    // https://developers.line.me/ja/reference/liff/#liffopenwindow()
    document.getElementById('openwindowbutton').addEventListener('click', function () {
        liff.openWindow({
            url: 'https://line.me'
        });
    });

    document.getElementById('openwindowexternalbutton').addEventListener('click', function () {
        liff.openWindow({
            url: 'https://line.me',
            external: true
        });
    });

    // メッセージの送信
    document.getElementById('sendmessagebutton').addEventListener('click', function () {
        // https://developers.line.me/ja/reference/liff/#liffsendmessages()
        liff.sendMessages([{
            type: 'text',
            text: "テキストメッセージの送信"
        }, {
            type: 'sticker',
            packageId: '2',
            stickerId: '144'
        }]).then(function () {
            window.alert("送信完了");
        }).catch(function (error) {
            window.alert("Error sending message: " + error);
        });
    });
};

// プロファイルの取得と表示
function getProfile(){
    // https://developers.line.me/ja/reference/liff/#liffgetprofile()
    liff.getProfile().then(function (profile) {
        document.getElementById('useridprofilefield').textContent = profile.userId;
        document.getElementById('displaynamefield').textContent = profile.displayName;

        var profilePictureDiv = document.getElementById('profilepicturediv');
        if (profilePictureDiv.firstElementChild) {
            profilePictureDiv.removeChild(profilePictureDiv.firstElementChild);
        }
        var img = document.createElement('img');
        img.src = profile.pictureUrl;
        img.alt = "Profile Picture";
        img.width = 200;
        profilePictureDiv.appendChild(img);

        document.getElementById('statusmessagefield').textContent = profile.statusMessage;
    }).catch(function (error) {
        window.alert("Error getting profile: " + error);
    });
}

function initializeApp(data) {
    document.getElementById('languagefield').textContent = data.language;
    document.getElementById('viewtypefield').textContent = data.context.viewType;
    document.getElementById('useridfield').textContent = data.context.userId;
    document.getElementById('utouidfield').textContent = data.context.utouId;
    document.getElementById('roomidfield').textContent = data.context.roomId;
    document.getElementById('groupidfield').textContent = data.context.groupId;
}
```

3\. git で変更のコミットしてプッシュ。

```
git commit -am "add openwindow"
git push origin master
```

4\. LIFF アプリケーションのアドレスは変わっていないため、先ほどテストで送ったアドレスをクリックして動作を確認。

## LIFF アプリを閉じる

LIFF　アプリは右上の「X」をタップするか、tall/compact の場合は領域以外をタップすれば閉じますが、明示的に閉じるイベントもサポートされます。

1\. index.html を以下コードに差し替え。

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>My First LIFF</title>
</head>
<body>           
    <button id="closewindowbutton">LIFF アプリを閉じる</button>
    <button id="openwindowbutton">ウィンドウを LINE 内で開く</button>
    <button id="openwindowexternalbutton">ウィンドウを外部ブラウザで開く</button>
    <button id="sendmessagebutton">メッセージ送信</button>
    <div id="profileinfo">
        <h2>Profile</h2>
        <div id="profilepicturediv">
        </div>
        <table border="1">
            <tr>
                <th>userId</th>
                <td id="useridprofilefield"></td>
            </tr>
            <tr>
                <th>displayName</th>
                <td id="displaynamefield"></td>
            </tr>
            <tr>
                <th>statusMessage</th>
                <td id="statusmessagefield"></td>
            </tr>
        </table>
    </div>

    <div id="liffdata">
        <h2>LIFF Data</h2>
        <table border="1">
            <tr>
                <th>language</th>
                <td id="languagefield"></td>
            </tr>
            <tr>
                <th>context.viewType</th>
                <td id="viewtypefield"></td>
            </tr>
            <tr>
                <th>context.userId</th>
                <td id="useridfield"></td>
            </tr>
            <tr>
                <th>context.utouId</th>
                <td id="utouidfield"></td>
            </tr>
            <tr>
                <th>context.roomId</th>
                <td id="roomidfield"></td>
            </tr>
            <tr>
                <th>context.groupId</th>
                <td id="groupidfield"></td>
            </tr>
        </table>
    </div>
    
    <!-- LIFF SDK の読み込み -->
    <script src="https://d.line-scdn.net/liff/1.0/sdk.js"></script>
    <script src="liff.js"></script>
</body>
</html>
```

2\. liff.js を以下コードに差し替え。

```javascript
window.onload = function (e) {
    // init で初期化。基本情報を取得。
    // https://developers.line.me/ja/reference/liff/#initialize-liff-app
    liff.init(function (data) {
        getProfile();
        initializeApp(data);
    });

    // LIFF アプリを閉じる
    // https://developers.line.me/ja/reference/liff/#liffclosewindow()
    document.getElementById('closewindowbutton').addEventListener('click', function () {
        liff.closeWindow();
    });

    // ウィンドウを開く
    // https://developers.line.me/ja/reference/liff/#liffopenwindow()
    document.getElementById('openwindowbutton').addEventListener('click', function () {
        liff.openWindow({
            url: 'https://line.me'
        });
    });

    document.getElementById('openwindowexternalbutton').addEventListener('click', function () {
        liff.openWindow({
            url: 'https://line.me',
            external: true
        });
    });

    // メッセージの送信
    document.getElementById('sendmessagebutton').addEventListener('click', function () {
        // https://developers.line.me/ja/reference/liff/#liffsendmessages()
        liff.sendMessages([{
            type: 'text',
            text: "テキストメッセージの送信"
        }, {
            type: 'sticker',
            packageId: '2',
            stickerId: '144'
        }]).then(function () {
            window.alert("送信完了");
        }).catch(function (error) {
            window.alert("Error sending message: " + error);
        });
    });
};

// プロファイルの取得と表示
function getProfile(){
    // https://developers.line.me/ja/reference/liff/#liffgetprofile()
    liff.getProfile().then(function (profile) {
        document.getElementById('useridprofilefield').textContent = profile.userId;
        document.getElementById('displaynamefield').textContent = profile.displayName;

        var profilePictureDiv = document.getElementById('profilepicturediv');
        if (profilePictureDiv.firstElementChild) {
            profilePictureDiv.removeChild(profilePictureDiv.firstElementChild);
        }
        var img = document.createElement('img');
        img.src = profile.pictureUrl;
        img.alt = "Profile Picture";
        img.width = 200;
        profilePictureDiv.appendChild(img);

        document.getElementById('statusmessagefield').textContent = profile.statusMessage;
    }).catch(function (error) {
        window.alert("Error getting profile: " + error);
    });
}

function initializeApp(data) {
    document.getElementById('languagefield').textContent = data.language;
    document.getElementById('viewtypefield').textContent = data.context.viewType;
    document.getElementById('useridfield').textContent = data.context.userId;
    document.getElementById('utouidfield').textContent = data.context.utouId;
    document.getElementById('roomidfield').textContent = data.context.roomId;
    document.getElementById('groupidfield').textContent = data.context.groupId;
}
```

3\. git で変更のコミットしてプッシュ。

```
git commit -am "add closewindow"
git push origin master
```

4\. LIFF アプリケーションのアドレスは変わっていないため、先ほどテストで送ったアドレスをクリックして動作を確認。

## LIFF アプリの更新と削除

LIFF CLI を使えば登録済の URL やサイズを変更できるだけでなく、不要となった LIFF アプリを削除することも可能です。現状 10 個までしかアプリを登録できないため、賢く管理する必要があります。

更新

```
liff update <liffId> <url> <type:full|tall|compact>
```

削除

```
liff delete <liffId>
liff deleteAll
```

# まとめ

LIFF アプリは Web 画面と Bot をシームレスに統合できる便利な機能です。是非色々試してください。