[안드로이드] 안드로이드와 javascript 정보교환하기 - token 저장하고 불러오기 (push 푸시 구현시 필요)
이번 포스팅은 실무에서 구글 파이어베이스 등으로 푸쉬를 구현할때 반드시 알아 두어야할 사항이므로 꼭 숙지하도록 하자.
하이브리드앱상으로 WebView 를 올리고 안드로이다와 WebView 내의 javascript 코드 형태로 상호 정보 교환이 이루어지도록 하고자 한다.
보통의 경우 푸쉬작업을 위하여 Token 을 생성하는데, 이 고유한 토큰을 따로 저장하고, WebView 상의 javascript 코드 형태로 바로 전달하는 매커니즘이 핵심이다.
우선은 아래의 MainActivity 소스부터 확인하도록 하자.
[ MainActivity.java ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.messaging.FirebaseMessaging;
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView1 = (WebView) findViewById(R.id.webView1);
// 현재 토큰값 얻기
FirebaseMessaging.getInstance().getToken().addOnCompleteListener(new OnCompleteListener<String>() {
@Override
public void onComplete(@NonNull Task<String> task) {
if (!task.isSuccessful()) {
Log.w(TAG, "Fetching FCM registration token failed", task.getException());
return;
}
// Get new FCM registration token
fcmToken = task.getResult();
// Log and toast
String msg = "FCM token : " + fcmToken;
Log.d(TAG, msg);
// Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
}
});
// javascript 브릿지 연동
AndroidBridge ab = new AndroidBridge(webView1, MainActivity.this);
webView1.addJavascriptInterface(ab, "Android");
}
}
|
cs |
AndroidBridge 가 웹뷰와 Javascript 사이의 정보교환을 담당하는 놈인데 이를 아래의 소스로 구현해 두도록 한다.
[ AndroidBridge.java ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
package won.alwaysweb.fcmtest1;
import android.content.SharedPreferences;
import android.os.Handler;
import android.util.Log;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;
import static android.content.Context.MODE_PRIVATE;
public class AndroidBridge {
private String TAG = "AndroidBridge";
private WebView wv;
private MainActivity mContext;
final public Handler handler = new Handler();
public AndroidBridge(WebView _wv, MainActivity _mContext) {
wv = _wv;
mContext = _mContext;
}
@JavascriptInterface
public void alert_js(final String message) {
Log.d(TAG, "alert_js function" + message);
handler.post(new Runnable() {
@Override
public void run() {
wv.loadUrl("javascript:alert('"+ message +"')");
}
});
}
//----------------- 실제 웹뷰에서 javascript 사용법 ----------------
// <a href="javascript:window.Android.alert_js('내용입니다.');">alert내용</a>
//----------------------------------------------------------------
@JavascriptInterface
public void get_token() {
// 저장된 token 읽어오기 SharedPreferences pref = mContext.getSharedPreferences("pref", MODE_PRIVATE);
String token = pref.getString("token","");
Log.d(TAG, "get_token function : " + token);
handler.post(new Runnable() {
@Override
public void run() {
wv.loadUrl("javascript:get_token('"+ token +"')");
}
});
}
//----------------- 실제 웹뷰에서 javascript 사용법 ----------------
// <a href="javascript:window.Android.get_token();">토큰내용읽어오기</a>
//<script>
//function get_token(str) {
// alert(str);
//}
//</script>
//----------------------------------------------------------------
}
|
cs |
[ MyFirebaseMessagingService.java ] - 푸쉬내용을 구현한 파이어베이스 소스부분
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
package won.alwaysweb.fcmtest1;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import java.io.IOException;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMessagingService";
public MyFirebaseMessagingService() {
}
// 앱을 새로 설치할때 - 새로운 등록 id 토큰 db에 저장
@Override
public void onNewToken(@NonNull String token) {
super.onNewToken(token);
Log.e(TAG,"onNewToken 호출됨 token : " + token);
//----------- 만들어진 토큰을 저장한다 ------------
SharedPreferences pref = getSharedPreferences("pref", MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.putString("token", token);
editor.apply(); // 비동기적 저장
//editor.commit(); // 동기적 저장
}
}
|
cs |
위의 소스에서 핵심은 37라인의 앱이 설치되면서 동작하는 onNewToken 에서 42라인처럼 token 이름으로 비동기형식으로 pref 값이 안드로이드 상에 저장된다.
그러면, AndroidBridge.java 소스의 39라인 소스를 보면 실제 javascript 소스상으로 get_token() 형태로 웹에서 바로 그 저장된 Token 값을 읽어올 수 있다.
이때 반드시 네트워크 상으로 정보교환이 이루어짐으로써, 라인46 처럼 쓰레드 처리를 해야한다. (비동기처리)
이제 아래의 일반 웹소스 형태로 읽어온 Token 값을 찍어본다.
[ index.html ]
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<script>
function get_token(str) {
if (str != null && str != "") {
alert(str);
}
}
if (typeof Android == "undefined") {
var Android = {};
} else {
window.Android.get_token();
}
</script>
|
cs |
위의 html 소스를 보면 안드로이드 앱상으로 WebView 형태로 index.html 를 로딩하면,
위에서 설명한 AndroidBridge 소스부분에 명명한 것처럼 window.Android 하면 해당 get_token() 메소스를 사용할 수가 있다.