안드로이드 하이브리드앱(기본 브라우져 사용)시 서버의 Front에서 javascript를 이용하여 연동하는 방법
1. Native앱 ---> Front의 JavaScript로 데이터 전송시
1) [[Native앱]] 웹브라우져에서 url 호출하듯이 자바스크립트를 호출한다.
webview.loadUrl("javascript:mergeAppUserInfo('testid','1.0.0','android','26');");
2) [[Front의 JavaScript]] 서버의 jsp,asp,php등의 파일에서 자바스크립트 설정을 한다.
<script type="text/javascript">
// Native App에서 호출, 접속한 사용자 및 버전 정보 (앱 --> Front)
function mergeAppUserInfo(userid, app_version, os_type, os_version){
alert("AppInfo:"+userid+", "+app_version+","+os_type+", "+os_version);
}
</script>
2. Front의 JavaScript ---> Native앱으로 데이터 전송시
1) [[앱]] 자바스크립트 인터페이스 추가, AndroidBridge 클래스에 "HybridApp" 이름으로 설정
WebView webview;
webview = (WebView)findViewById(R.id.myWebView);
webview.addJavascriptInterface(new AndroidBridge(), "HybridApp");
...
private class AndroidBridge {
@JavascriptInterface
public void sendUserIdVersion(final String userId, final String lastVersion, final String mustYn) {
}
}
2) [[Front의 JavaScript]] 서버의 jsp,asp,php등의 파일에서 자바스크립트로 데이터 전송 요청을 한다.
<script type="text/javascript">
//하이브리드앱 연동, 앱에 데이터를 전송한다.
$(document).ready(function(){
window.HybridApp.sendUserIdVersion("testid", "1.0.0", "Y"); // (Front --> 앱)
});
</script>
[참고] iOS 하이브리드앱(기본 브라우져 사용)에서시 서버의 Front에서 javaScript를 이용하여 연동하는 방법 링크
https://androi.tistory.com/354
3. [[앱]] 샘플 소스
public class MainActivity extends AppCompatActivity {
WebView webview;
final static String TAG = "MYMALL";
private String START_URL = "http://m.naver.com";
@SuppressLint("JavascriptInterface")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mContext = this;
START_URL = "http://m.naver.com";
if(BuildConfig.BUILD_TYPE.equals("debug")){ // TODO
START_URL = "http://m.naver.com";
}
webview = (WebView)findViewById(R.id.myWebView);
WebSettings webSettings = webview.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setSaveFormData(true);
webSettings.setAllowFileAccess(true);
webSettings.setAllowContentAccess(true);
webSettings.setSupportMultipleWindows(true); // 새창띄우기 허용
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
// webSettings.setBuiltInZoomControls(false);
// webSettings.setSupportZoom(true);
String userAgent = webSettings.getUserAgentString();
webSettings.setUserAgentString(userAgent+" androidapp"); // 앱 인지 여부 UserAgent에 추가
goLink();
webview.addJavascriptInterface(new AndroidBridge(), "HybridApp");
webview.setWebChromeClient(new WebChromeClient(){
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
// Log.d(TAG, "onJsAlert(!" + view + ", " + url + ", "
// + message + ", " + result + ")");
// Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
// return true; // I handled it
return super.onJsAlert(view, url, message, result);
}
});
webview.setDownloadListener(new DownloadListener() {
// 웹뷰내 다운로드가 가능한 파일이 있다면 여기서 처리해도 됨, https://g-y-e-o-m.tistory.com/28
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
}
});
webview.setWebViewClient(new WebClient()); // 응용프로그램에서 직접 url 처리
Log.d(TAG, "START MYMALL MainActivity ");
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
protected void onResume() {
super.onResume();
}
private void goLink(){
String target_link = "";
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
if( bundle != null){
if(bundle.getString("link") != null && !bundle.getString("link").equalsIgnoreCase("")) {
target_link = bundle.getString("link");
Log.e("TAS", "link: "+target_link);
START_URL = target_link;
}else{ // 링크값이 없는 경우
}
}
Log.d(TAG,"START_URL: "+START_URL);
webview.loadUrl(START_URL);
}
@Override
public void onBackPressed() {
if(webview.canGoBack()){
if(webview.getUrl().contains(MAIN_PAGE)){ //뒤로버튼 누를때 메인화면이면
// AlertDialog.Builder builder = new AlertDialog.Builder(this); // 여기서 this는 Activity의 this
// // 여기서 부터는 알림창의 속성 설정
// builder.setTitle("마이몰") // 제목 설정
// .setMessage("앱을 종료 하시 겠습니까?") // 메세지 설정
// .setCancelable(false) // 뒤로 버튼 클릭시 취소 가능 설정
// .setNegativeButton("취소", new DialogInterface.OnClickListener(){ // 취소 버튼 클릭시 설정
// public void onClick(DialogInterface dialog, int whichButton){
// dialog.cancel();
// }
// })
// .setPositiveButton("확인", new DialogInterface.OnClickListener(){ // 확인 버튼 클릭시 설정
// public void onClick(DialogInterface dialog, int whichButton){
// finish();
// }
// });
//
// AlertDialog dialog = builder.create(); // 알림창 객체 생성
// dialog.show(); // 알림창 띄우기
backPressCloseHandler.onBackPressed();
}else{
webview.goBack();
}
return;
}else{
// AlertDialog.Builder builder = new AlertDialog.Builder(this); // 여기서 this는 Activity의 this
// // 여기서 부터는 알림창의 속성 설정
// builder.setTitle("마이몰") // 제목 설정
// .setMessage("앱을 종료 하시 겠습니까?") // 메세지 설정
// .setCancelable(false) // 뒤로 버튼 클릭시 취소 가능 설정
// .setNegativeButton("취소", new DialogInterface.OnClickListener(){ // 취소 버튼 클릭시 설정
// public void onClick(DialogInterface dialog, int whichButton){
// dialog.cancel();
// }
// })
// .setPositiveButton("확인", new DialogInterface.OnClickListener(){ // 확인 버튼 클릭시 설정
// public void onClick(DialogInterface dialog, int whichButton){
// finish();
// }
// });
// AlertDialog dialog = builder.create(); // 알림창 객체 생성
// dialog.show(); // 알림창 띄우기
backPressCloseHandler.onBackPressed();
return;
}
//super.onBackPressed();
}
class WebClient extends WebViewClient {
final static String TAG = "MYCLIENT";
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Util.DEBUG("url: "+ url);
if(url.toLowerCase().endsWith(".pdf") || url.toLowerCase().endsWith(".hwp") || url.toLowerCase().endsWith(".doc") || url.toLowerCase().endsWith(".docx") || url.toLowerCase().endsWith(".xls") || url.toLowerCase().endsWith(".xlsx") || url.toLowerCase().endsWith(".ppt") || url.toLowerCase().endsWith(".pptx") ) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
// 마지막 구분자를 파일명으로 지정. 확장자를 포함하여야 내 파일에서 열린다.
String filename[] = url.split("/");
String myFilename = filename[filename.length - 1];
// String myFilename = filename[filename.length-1];
// String encodeFilename = "";
// try {
// encodeFilename = java.net.URLDecoder.decode(myFilename, "euc-kr");
// Log.e(TAG,"file name: "+ encodeFilename);
// } catch (UnsupportedEncodingException e) {
// encodeFilename = myFilename;
// Log.e(TAG,"file name.e.: "+ encodeFilename);
// e.printStackTrace();
// }
MimeTypeMap mtm = MimeTypeMap.getSingleton();
String fileExtension = myFilename.substring(myFilename.lastIndexOf(".") + 1, myFilename.length()).toLowerCase();
String mimeType = mtm.getMimeTypeFromExtension(fileExtension);
request.setMimeType(mimeType);
Log.e(TAG, "myFilename: " + myFilename);
Log.e(TAG, "mimeType: " + mimeType);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename[filename.length - 1]); //
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
dm.enqueue(request);
}else if (url.startsWith("mailto:") || url.startsWith("tel:")) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
}else if (url.startsWith("mymallpop://")) { // 새창 띄우기
Intent browserIntent = new Intent(Intent.ACTION_VIEW);
browserIntent.setData(Uri.parse(url.replace("mymallpop://", "")));
startActivity(browserIntent);
}else if(url.startsWith("market://")){
Intent browserIntent = new Intent(Intent.ACTION_VIEW);
browserIntent.setData(Uri.parse(url));
startActivity(browserIntent);
}else if(!url.startsWith("http")){ // ex) intent:// , vguardend://
// 해당앱이 있으면 실행, 없으면 마켓 이동
try {
Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
Intent existPackage = getPackageManager().getLaunchIntentForPackage(intent.getPackage());
if (existPackage != null) {
startActivity(intent);
} else {
Intent marketIntent = new Intent(Intent.ACTION_VIEW);
marketIntent.setData(Uri.parse("market://details?id=" + intent.getPackage()));
startActivity(marketIntent);
}
return true;
} catch (Exception e) {
e.printStackTrace();
}
}else{
view.loadUrl(url);
}
return true;
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// TODO Auto-generated method stub
//super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
//Log.d(TAG, "onPageFinished " + url);
}
}
private class AndroidBridge {
@JavascriptInterface
public void sendUserIdVersion(final String userId, final String lastVersion, final String mustYn) { // must be final
// Front javascript 에서 Native 호출하는 방식: window.HybridApp.sendUserIdVersion("mytestid","1.0.5");
handler.post(new Runnable() {
public void run() {
Util.DEBUG("HybridApp, sendUserIdVersion("+userId+","+lastVersion+","+mustYn+")");
//Toast.makeText(mContext,"UserID: "+userId +", 최신 Ver:"+lastVersion+", 설치팝업:"+mustYn, Toast.LENGTH_LONG).show();
// 최신 버전이 있으면 업데이트 팝업 띄우기
try{
String myVer = BuildConfig.VERSION_NAME;
int nLastVer = Integer.parseInt(lastVersion.replace(".",""));
int nCurVer = Integer.parseInt(myVer.replace(".",""));
if((nLastVer > nCurVer) && mustYn.equals("Y")){ // 최신버전이 있고, 설치요청팝업이 보여야하면
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
// 여기서 부터는 알림창의 속성 설정
builder.setTitle("마이몰") // 제목 설정
.setMessage("최신 버전의 마이몰앱을 설치하시겠습니까?") // 메세지 설정
.setCancelable(true) // 뒤로 버튼 클릭시 취소 가능 설정
.setNegativeButton("취소", new DialogInterface.OnClickListener(){ // 취소 버튼 클릭시 설정
public void onClick(DialogInterface dialog, int whichButton){
dialog.cancel();
}
})
.setPositiveButton("확인", new DialogInterface.OnClickListener(){ // 확인 버튼 클릭시 설정
public void onClick(DialogInterface dialog, int whichButton){
// https://m.blog.naver.com/chumy/220850047176
final String appPackageName = getPackageName();
Intent marketLaunch = new Intent(Intent.ACTION_VIEW);
marketLaunch.setData(Uri.parse("market://details?id="+appPackageName));
try{
startActivity(marketLaunch);
}catch (android.content.ActivityNotFoundException e){
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + appPackageName)));
}
}
});
AlertDialog dialog = builder.create(); // 알림창 객체 생성
dialog.show(); // 알림창 띄우기
}
}catch (Exception e){
Log.e(TAG,e.getMessage());
}
// Native에서 Front javascript호출하는 방식
if(!userId.equals("")){ // userid 가 있는 경우, 로그인이 된 상태일때
webview.loadUrl("javascript:mergeAppUserInfo('"+userId+"','"+BuildConfig.VERSION_NAME+"','android','"+android.os.Build.VERSION.SDK_INT+"');");
}
}
});
}
}
}
4. [[Front]] 샘플 소스
<script type="text/javascript">
//하이브리드앱 연동
$(document).ready(function(){
var appInfo = "<c:out value='${appInfo}'/>";
var androidVer = "<c:out value='${appInfo[0].APP_VERSION}'/>";
var iosVer = "<c:out value='${appInfo[1].APP_VERSION}'/>";
var androidMustYn = "<c:out value='${appInfo[0].MUST_YN}'/>";
var iosMustYn = "<c:out value='${appInfo[1].MUST_YN}'/>";
// console.log("appInfo="+appInfo);
console.log("androidVer="+androidVer);
console.log("iosVer="+iosVer);
var agent = navigator.userAgent.toLowerCase();
console.log("agent="+agent);
var isAppIOS = (agent.match('iosapp') != null);
var isAppAndroid = (agent.match('androidapp') != null);
//alert("<%=sMemberId%>");
console.log("sMemberId=<%=sMemberId%>"); // 로그인이 안된 상태이면 "" 값이 넘어감.
if(isAppAndroid) // 안드로이드 APP 인 경우
{
window.HybridApp.sendUserIdVersion("<%=sMemberId%>", androidVer, androidMustYn); // (Front --> 앱)
}else if(isAppIOS){ // 아이폰 APP 인 경우
window.HybridApp.sendUserIdVersion("<%=sMemberId%>", iosVer, iosMustYn); // (Front --> 앱)
}
});
// Native App에서 호출, 접속한 사용자 및 버전 정보 (앱 --> Front)
function mergeAppUserInfo(userid, app_version, os_type, os_version){
//alert("AppInfo:"+userid+", "+app_version+","+os_type+", "+os_version);
$.ajax({
type: "POST",
cache:false,
url: '<c:url value="/main/ajaxMergeAppUserInfo.json"/>',
dataType: "json",
data: {userid : userid, app_version : app_version ,os_type : os_type, os_version : os_version},
async:false,
success: function(obj) {
console.log("접속한 사용자 정보가 갱신되었습니다.");
},
error: function(obj) {
console.log("접속한 사용자 정보가 갱신실패 되었습니다.");
}
});
}
</script>
'안드로이드 개발 팁' 카테고리의 다른 글
안드로이드 하이브리드앱에서 쿠키 사용 방법 (0) | 2019.06.20 |
---|---|
안드로이드 아이콘에 뱃지 숫자 설정 (0) | 2019.06.07 |
스크롤뷰안에 리스트뷰가 있을때 높이 계산 (0) | 2017.10.30 |
안드로이드 캐쉬 지우기 (0) | 2016.03.30 |
Android Camera motion detection (카메라 모션) (0) | 2016.03.08 |