2015년 8월 29일 토요일

WebView 사용 예 (JavaScript <> Android 연동), 이미지 다운로드 기능

1. Activity의 Layout 정의
WebView를 배치


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:textAlignment="center" >

    <LinearLayout
        android:id="@+id/adSpace"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:gravity="bottom"
        android:orientation="horizontal" />

    <LinearLayout
        android:id="@+id/btnSpace"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/adSpace"
        android:gravity="bottom"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Hey"
            android:gravity="bottom"
            android:orientation="horizontal" >
        </Button>
    </LinearLayout>

    <WebView
        android:id="@+id/webView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/btnSpace"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="1dp" />

</RelativeLayout>






2. Activity Java 파일 작성

public class JavaScriptActivity extends Activity {

 //전역으로 WebView 타입의  변수 선언
 private WebView webView;

 @Override 
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  requestWindowFeature(Window.FEATURE_NO_TITLE);
  setContentView(R.layout.web_view_activity);

  //다른 Activity에서 넘겨준 데이터 가져오기.WebView에 load할 url
  String url = getIntent().getStringExtra("url");

  //Layout에서 WebView가져오기
  webView = (WebView)findViewById(R.id.webView1);
  
  //다양한 WebView 설정들
  WebSettings settings = webView.getSettings();
  settings.setJavaScriptEnabled(true);
  settings.setSaveFormData(false);
  //settings.setSupportZoom(true);
  //settings.setBuiltInZoomControls(true);

  //JavaScript와 AndroidNative와의 연결고리 설정
  webView.addJavascriptInterface(new JavaScriptInterface(this), "Android");
  webView.setWebChromeClient(new ChromeClient());

  //asset에 있는 url을 webview에서 오픈한다.
  String resourceURI = "file:///android_asset/1.html";
  
  if (!url.isEmpty()) {
   resourceURI = "file:///android_asset/"+url;
  }
  
  webView.loadUrl(resourceURI);

  //안드로이드의 버튼을 클릭하면 html문서 상의 javascript함수를 호출하는 예제.
  Button btn = (Button)findViewById(R.id.btn);
  btn.setOnClickListener(new OnClickListener() {
   @Override
   public void onClick(View v) {
    webView.loadUrl("javascript:setText('change text')");
   }
  });
 }

 
 @Override 
 public void onBackPressed () {
  //뒤로 가기 버튼을 클릭했을 시, 브라우저 history상 이전 페이지로 가도록 
  if (webView.canGoBack()) {
   webView.goBack();
  }
  else
   super.onBackPressed();
 }
 
 //asset에 있는 파일을 사용자의 sdcard에 저장하는 함수
 public void saveFileFromAsset(String filePathInAsset, String targetPathInSDCard) {
  AssetManager assetManager = getAssets();

  InputStream in = null;
  OutputStream out = null;
  try {
   in = assetManager.open(filePathInAsset);   // if files resides inside the "Files" directory itself
   out = new FileOutputStream(Environment.getExternalStorageDirectory().toString() + targetPathInSDCard + filePathInAsset);
   copyFile(in, out);
   in.close();
   in = null;
   out.flush();
   out.close();
   out = null;
   
   
   //sd카드에 파일을 쓴 후, 시스템에 알려줘야 한다. 
   final String outputPath = Environment.getExternalStorageDirectory().toString() + targetPathInSDCard + filePathInAsset;

   MediaScannerConnection.scanFile(JavaScriptActivity.this, 
     new String[] { outputPath.toString() }, 
     null,
     new MediaScannerConnection.OnScanCompletedListener() {
      public void onScanCompleted(String path, Uri uri) {
       Toast.makeText(getApplicationContext(), 
         "Image downloaded on \n" + outputPath, 
         Toast.LENGTH_SHORT).show();
    }
   });
  } catch(Exception e) {
   Log.e("tag", e.getMessage());
  }
 }
 
 private void copyFile(InputStream in, OutputStream out) throws IOException {
  byte[] buffer = new byte[1024];
  int read;
  while((read = in.read(buffer)) != -1){
   out.write(buffer, 0, read);
  }
 }

 public class JavaScriptInterface {    
  Context context = null;

  JavaScriptInterface(Context aContext)    {        
   context = aContext;    
  }

  //HTML 문서 내에서 JavaScript로 호출가능한 함수
  //브라우저에서 load가 완료되었을 때 호출하는 함수
  @JavascriptInterface
  public void onload() {
   Toast.makeText(getApplicationContext(), 
     "JavaScript onLoad", 
     Toast.LENGTH_SHORT).show();
  }

  //HTML 문서 내에서 JavaScript로 호출가능한 함수
  //asset의 파일을 로컬에 저장 
  @JavascriptInterface
  public void saveFile(String path) {
   saveFileFromAsset(path, "/Pictures/KakaoTalk/");
  }
 }

 public final class ChromeClient extends WebChromeClient {
  @Override
  public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
   result.confirm();
   return true;
  }
 } 
}

3. asset에 html 파일 배치하기 (1.html)



<html>
<head>
 <script> 
 window.onload = function() {
  Android.onload();
 };

 function saveImage(filename) {
  Android.launch(filename);
 };
 
 function setText(change) {
  var textArea = document.getElementById('text');
  textArea.innerHTML = change;
 };
 </script>
</head>

<body>
 <div id ='text'>
  This is hawaii
 </div>
 
 <input id="b1"
     type="button" 
     value="Save Image" 
     onClick="saveImage('hawaii.png')" />
 
 <img id="myimg" 
      src="hawaii.png" />
   
</body>
</html>

4. androidManifest.xml에 권한 설정

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />

댓글 없음:

댓글 쓰기