폰갭은 기본적으로 HTML 로 되어 있는데, 거기에 <a>태그를 이용한 링크를 걸면 지금 열려있는 페이지가 새로운 링크의 페이지로 바뀌어 버립니다. 당연한 작동 방식일텐데, 이것 말고 내가 평소에 사용하던 기본 브라우저를 열어서 거기에 보여주고 싶을 때가 있습니다. 왜?? 폰갭으로 제작한건 웹페이지가 아니고 앱처럼 보이고 싶으니까! 그리고 지금 열고자 하는 페이지는 웹 페이지니까!!!!
이것을 해결할 수 있는 방법으로는 InAppBrowser를 이용한 방법이 있는 것 같습니다.
저도 한번 해 봤습니다. iOS에서는 사파리에서 잘 열리는 것 같더라구요. 그런데, 안드로이드 에서는 기본 브라우저로 설정된 브라우저가 열리는게 아니라 내장된 다른 브라우저가 열리는 것 같더라구요. 인터페이스도 다르고, 뭔가 이상합니다.
그리고 또 맘에 안들었 것은 외부 브라우저로 띄울 링크를 다 따로 설정해야 하더라구요.
<a href="#" onclick="window.open('http://xxxxx.co.kr/','_system');">Link</a>
위와 같은 방식으로 링크를 변경해 주어야 정상 작동합니다.
제 경우에 이런 방식으로 바꿀 때 가장 문제가 됐던 점은, 내부에 저장된 문서가 아니라 인터넷에 있는 문서를 연 후에 거기서 링크를 거쳐 나갈 때 외부 브라우저로 열고 싶었는데, 인터넷 상에 있는 문서에는 자바스크립트 파일을 포함시키거나 링크를 위와 같이 변경하는 것이 까다로운 일이라서 위의 방법 말고 다른 방법이 필요했습니다.
webview 에서 url이 변경될 때마다 체크한다면 원하는대로 구현이 되겠구만!
그래서 안드로이드 소스 코드를 수정해 봤습니다.
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
super.init();
this.appView.clearCache(true);
this.appView.clearHistory();
this.appView.setWebViewClient(new CordovaWebViewClient(this, this.appView) {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(!url.startsWith("http://")) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(browserIntent);
return true;
}
//Implement your code
return super.shouldOverrideUrlLoading(view, url);
}
});
// Set by <content src="index.html" /> in config.xml
super.loadUrl(Config.getStartUrl());
//super.loadUrl("file:///android_asset/www/index.html");
}
이렇게 소스코드를 변경하면, http://로 시작하는 링크를 열게되면 기본 브라우저를 이용해 열어줍니다.
이 방식을 이용하면, 특정 사이트의 경우에만 작동하게 하거나, 작동하지 않게 하는 등의 방식으로 사용도 가능할 것 같네요.
iOS에서도 동일한 방식으로 사용 가능합니다.
MainViewController.m 파일을 수정하면 됩니다.
(...생략...)
/* Comment out the block below to over-ride */
/*
- (void) webViewDidStartLoad:(UIWebView*)theWebView
{
return [super webViewDidStartLoad:theWebView];
}
- (void) webView:(UIWebView*)theWebView didFailLoadWithError:(NSError*)error
{
return [super webView:theWebView didFailLoadWithError:error];
}
- (BOOL) webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
return [super webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType];
}
*/
-(BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
// url match check
NSURL *url = [request URL];
if([[url absoluteString] isEqualToString:[[request mainDocumentURL] absoluteString]]) {
if([[url scheme] isEqualToString:@"http"]) {
[[UIApplication sharedApplication] openURL:url];
return false;
}
}
return [super webView:webView shouldStartLoadWithRequest:request navigationType:navigationType];
}
@end
(...생략...)
iOS에서 사용한 shouldStartLoadWithRequest 메소드는 안드로이드에서 사용한 메소드와는 다르게 iframe처럼 내부에서 로딩이 발생하는 URL을 로딩할 때에도 매번 요청이 발생합니다.
그래서, 실제 요청한 메인 URL과 현재 요청을 발생시킨 URL을 비교해서 일치할 경우에만 작동하도록 했습니다.
진한 녹색으로 음영처리 된 부분은 http프로토콜을 이용하는지 체크한 후에 사파리로 열지 결정을 하기 위한 조건문입니다.
해당 조건문을
if(![[url absoluteString] hasPrefix:@"file://"] && ![[url absoluteString] hasPrefix:@"http://xxx.co.kr"]) {
위와 같이 변경하면 외부 URL중 일부는 사파리를 이용하지 않고 그냥 띄울 수 있게 해 줍니다.
이런 요청이 발생할 경우에 메인 URL 요청이 있을 때만 메소드가 실행되면 좋을텐데, 그런 메소드가 있는지는 잘 모르겠네요. 혹시 이것보다 더 좋은 방법 아시는 분 계시면 댓글 부탁드립니다.
<참고>
Android url 변경 이벤트 체크: http://stackoverflow.com/questions/12601491/android-phonegap-intercept-url-equivalent-of-ios-shouldstartloadwithrequest
iOS 변경 이벤트 체크: http://stackoverflow.com/questions/10118649/open-external-links-in-phone-gap-1-6-0