アプリからLINEにメッセージを送る手段として、LINE Notifyを使用する方法がありますが、ネット検索してもWEBアプリからの実装コード例は多く見つかりますが、androidアプリからの実装コード例が、ほぼほぼ見つかりませんでした。
この記事では、わずかながらの参考記事を元に試行錯誤を繰り返し、androidアプリとLINEとの連携を実現した内容について解説します。
この記事を読むと以下のことができるようになります。 ・androidアプリから画像付きのメッセージがLINEに届く。 以下はそのイメージ図。
アプリとLINEの連携を行うにはコード実装と人手設定を行う必要があります。設定と実装に分けて解説します。
設定
手順に関しては、以下の記事が参考になります。
実装
実装にあたり、参考にしたのがLINEの公式ドキュメント「LINE Notify API Document 」です。一読すると記事の理解が深まります。以下の表はドキュメントの抜粋になりますが、気になった点をコメントします。
リクエスト方法
Content-Typeは「multipart/form-data」も使用可能とのことですが、ファイル送信する想定が無かったので試していません。
リクエストパラメータ
パラメータ名は「imageFile」「notificationDisabled」も指定可能とのことですが、想定に無かったので試していません。「stickerPackageId」「stickerId」は動作確認できましたが、実装においてLINEスタンプ表示は見送りました。
実装中に悩まされたのが「imageThumbnail」「imageFullsize」です。 共に省略可能とあるので「message + imageThumbnail」指定、「message + imageFullsize」指定を試しましたが正常に動作せず、結局「message + imageThumbnail + imageFullsize」指定でうまく行きました。片方だけの省略はダメなようです。
又、公式では「imageThumbnail」「imageFullsize」で指定可能なファイルがJPEGのみとなっていますが、動作確認ではPNGでも問題ありませんでした。
リクエスト周りの実装コードはこんな感じです。
try {
URL url = new URL ( "https://notify-api.line.me/api/notify" ) ;
connection = ( HttpURLConnection) url. openConnection ( ) ;
connection. setDoOutput ( true ) ;
connection. setRequestMethod ( "POST" ) ;
connection. addRequestProperty ( "Content-Type" , "application/x-www-form-urlencoded" ) ;
connection. addRequestProperty ( "Authorization" , "Bearer " + token) ;
try ( OutputStream os = connection. getOutputStream ( ) ;
OutputStreamWriter out = new OutputStreamWriter ( os) ) {
out. append ( "message=" ) . append ( URLEncoder. encode ( message, "UTF-8" ) ) ;
out. append ( "&" ) ;
out. append ( "imageThumbnail=" ) . append ( URLEncoder. encode ( image, "UTF-8" ) ) ;
out. append ( "&" ) ;
out. append ( "imageFullsize=" ) . append ( URLEncoder. encode ( image, "UTF-8" ) ) ;
out. flush ( ) ;
レスポンス本文(レスポンス本文はJSONのobject型になります)
レスポンスは正常時、以下の内容で取得できます。 {“status”:200,”message”:”ok”}
レスポンス周りの実装コードはこんな感じです。
try ( InputStream is = connection. getInputStream ( ) ;
BufferedReader r = new BufferedReader ( new InputStreamReader ( is) ) ) {
String res = r. lines ( ) . collect ( Collectors. joining ( ) ) ;
if ( ! res. contains ( "\"message\":\"ok\"" ) ) {
Log. e ( "ERROR" , "Response NG" ) ;
return res;
}
}
その他、異常系の処理の実装ですが、異常を想定した確認結果がこちらになります。
1.LINEアプリから「LINE Notify」を友だち登録削除した場合。 ⇒ 処理が正常終了。LINEに通知無し。
2.LINE Notifyページからサービス連携解除した場合。 ⇒ 処理が異常終了。例外検出(java.io.FileNotFoundException)
レスポンス異常となる場合が確認できませんでしたが、レスポンス異常、例外検出の両方に対応した処理(結果を画面出力)としました。
異常系周りの実装コードはこんな感じです。
ExecutorService ex = Executors. newSingleThreadExecutor ( ) ;
Future< String> futureResult = ex. submit ( new Comm ( token, message, image) ) ;
try {
return futureResult. get ( ) ;
} catch ( Exception e) {
return e. getMessage ( ) ;
}
以上を踏まえて、動作確認できた実装コードを丸っと記載しておきます。実装の参考になれば幸いです。
処理側(LineNotify.java)
package < your package name> ;
import android. util. Log;
import java. io. BufferedReader;
import java. io. IOException;
import java. io. InputStream;
import java. io. InputStreamReader;
import java. io. OutputStream;
import java. io. OutputStreamWriter;
import java. net. HttpURLConnection;
import java. net. URL ;
import java. net. URLEncoder;
import java. util. concurrent. Callable;
import java. util. concurrent. ExecutorService;
import java. util. concurrent. Executors;
import java. util. concurrent. Future;
import java. util. stream. Collectors;
class LineNotify {
public String notify ( String token, String message, String image ) {
ExecutorService ex = Executors. newSingleThreadExecutor ( ) ;
Future< String> futureResult = ex. submit ( new Comm ( token, message, image) ) ;
try {
return futureResult. get ( ) ;
} catch ( Exception e) {
return e. getMessage ( ) ;
}
}
class Comm implements Callable < String> {
private final String token;
private final String message;
private final String image;
Comm ( String token, String message, String image) {
this . token = token;
this . message = message;
this . image = image;
}
@Override
public String call ( ) throws IOException {
HttpURLConnection connection = null ;
try {
URL url = new URL ( "https://notify-api.line.me/api/notify" ) ;
connection = ( HttpURLConnection) url. openConnection ( ) ;
connection. setDoOutput ( true ) ;
connection. setRequestMethod ( "POST" ) ;
connection. addRequestProperty ( "Content-Type" , "application/x-www-form-urlencoded" ) ;
connection. addRequestProperty ( "Authorization" , "Bearer " + token) ;
try ( OutputStream os = connection. getOutputStream ( ) ;
OutputStreamWriter out = new OutputStreamWriter ( os) ) {
out. append ( "message=" ) . append ( URLEncoder. encode ( message, "UTF-8" ) ) ;
out. append ( "&imageThumbnail=" ) . append ( URLEncoder. encode ( image, "UTF-8" ) ) ;
out. append ( "&imageFullsize=" ) . append ( URLEncoder. encode ( image, "UTF-8" ) ) ;
out. flush ( ) ;
try ( InputStream is = connection. getInputStream ( ) ;
BufferedReader r = new BufferedReader ( new InputStreamReader ( is) ) ) {
String res = r. lines ( ) . collect ( Collectors. joining ( ) ) ;
if ( ! res. contains ( "\"message\":\"ok\"" ) ) {
Log. e ( "ERROR" , "Response NG" ) ;
return res;
}
}
}
} catch ( Exception e) {
Log. e ( "ERROR" , "Exception detected" ) ;
throw e;
} finally {
if ( connection != null ) {
connection. disconnect ( ) ;
}
}
return "" ;
}
}
}
呼出側(抜粋)
String contents = < your message> ;
String image = < your site> ( 例) "https://<your domain>/sample.png" ;
String token = < your access token> ;
LineNotify classln = new LineNotify ( ) ;
String ret = classln. notify ( token, contents, image) ;
if ( ret. equals ( "" ) ) {
text. setText ( "正常終了しました。" ) ;
} else {
text. setText ( "異常終了しました。\n" + ret) ;
}
以上です。