안드로이드 하이브리드앱(기본 브라우져 사용)시 서버의 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

 

iOS 하이브리드앱(기본 브라우져 사용)에서시 서버의 Front에서 javaScript를 이용하여 연동하는 방법

iOS 하이브리드앱(기본 브라우져 사용)에서시 서버의 Front에서 javaScript를 이용하여 연동하는 방법 (Swift에서 WKWebView를 이용하는 경우) 1. Native앱 ---> Front의 javaScript로 데이터 전송시 (swift) 1) [..

androi.tistory.com

 

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>

 

안드로이드하이브리드스크립트연동.txt
0.02MB

+ Recent posts