안경잡이개발자

728x90
반응형

  이번 시간에는 안드로이드 스튜디오(Android Studio)를 이용하여 현재까지 만들었던 웹 애플리케이션을 앱(App) 형태로 배포하도록 하겠습니다. 따라서 안드로이드 스튜디오를 실행하여 프로젝트를 생성하도록 하겠습니다.




  이후에 빈 액티비티 형태로 프로젝트를 구성합니다.




  이후에 다음과 같은 3개의 소스코드를 작업하시면 됩니다.


  먼저 레이아웃부터 작업해주시면 됩니다.


▶ activity_main.xml


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

</android.support.constraint.ConstraintLayout>


▶ MainActivity.java

package tk.wordcloudpython.wordcloud;

import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends AppCompatActivity {

private WebView webView;
private ValueCallback<Uri> filePathCallbackNormal;
private ValueCallback<Uri[]> filePathCallbackLollipop;
private final static int FILE_CHOOSER_NORMAL_REQ_CODE = 1;
private final static int FILE_CHOOSER_LOLLIPOP_REQ_CODE = 2;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = (WebView) findViewById(R.id.webView);
/* 웹 세팅 작업하기 */
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webSettings.setAllowFileAccessFromFileURLs(true);
webSettings.setSaveFormData(false);
webSettings.setSavePassword(false);
webSettings.setUseWideViewPort(true);
webSettings.setSupportMultipleWindows(true);
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
/* 리다이렉트 할 때 브라우저 열리는 것 방지 */
webView.setWebViewClient(new WebViewClient());
webView.setWebChromeClient(new WebChromeClient() {
// 안드로이드 3.0 이상
public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType) {
filePathCallbackNormal = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("text/plain");
startActivityForResult(Intent.createChooser(i, "File Chooser"), FILE_CHOOSER_NORMAL_REQ_CODE);
}
// 안드로이드 4.1 이상
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
openFileChooser(uploadMsg, acceptType);
}
// 안드로이드 5.0 이상
public boolean onShowFileChooser(
WebView webView, ValueCallback<Uri[]> filePathCallback,
WebChromeClient.FileChooserParams fileChooserParams) {
if (filePathCallbackLollipop != null) {
filePathCallbackLollipop.onReceiveValue(null);
filePathCallbackLollipop = null;
}
filePathCallbackLollipop = filePathCallback;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("text/plain");
startActivityForResult(Intent.createChooser(i, "File Chooser"), FILE_CHOOSER_LOLLIPOP_REQ_CODE);
return true;
}
});
/* 웹 뷰 띄우기 */
webView.loadUrl("https://wordcloud-e11f9.firebaseapp.com/");
}

public void onBackPressed() {
if (webView.canGoBack()) webView.goBack();
else finish();
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == FILE_CHOOSER_NORMAL_REQ_CODE) {
if (filePathCallbackNormal == null) return;
Uri result = (data == null || resultCode != RESULT_OK)? null : data.getData();
filePathCallbackNormal.onReceiveValue(result);
filePathCallbackNormal = null;
} else if (requestCode == FILE_CHOOSER_LOLLIPOP_REQ_CODE) {
if (filePathCallbackLollipop == null) return;
filePathCallbackLollipop.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
filePathCallbackLollipop = null;
}
} else {
if (filePathCallbackLollipop != null) {
filePathCallbackLollipop.onReceiveValue(null);
filePathCallbackLollipop = null;
}
}
}
}


▶ AndroidManifest.xml


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="tk.wordcloudpython.wordcloud">

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

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.NoActionBar">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>


  이제 안드로이드 애뮬레이터를 활용하여 프로젝트를 테스트 해보겠습니다.







  다만 파일 선택을 하고 싶어도 다음과 같이 파일이 존재하지 않는 것을 확인할 수 있습니다.



  따라서 안드로이드 애뮬레이터로 파일을 옮기기 위해서 일단 하나의 텍스트 파일을 생성하겠습니다.



  따라서 안드로이드 스튜디오에서 오른쪽 아래의 [Device File Explorer] 탭을 열어서 [sdcard] 폴더에 텍스트 파일을 넣어주시면 됩니다.



  우클릭 이후에 업로드(Upload)를 진행하시면 됩니다.




  이제 다시 텍스트 파일 업로드를 진행하시면 됩니다.




  다음과 같이 텍스트 파일을 추가해보도록 하겠습니다.



  이제 추가된 텍스트 파일을 확인해보도록 하겠습니다.




  성공적으로 워드 클라우드가 생성되는 것을 확인할 수 있습니다.




※ APK 파일 배포하기 ※


  실제로 구글 플레이스토어 마켓 등에 배포하기 위해서는 APK 파일로 추출하는 과정이 필요합니다. 안드로이드 스튜디오를 활용해 다음과 같은 과정으로 APK 파일을 추출할 수 있습니다. 가장 먼저 [Build] 탭에서 APK 파일을 추출하는 버튼을 누르시면 됩니다.



  저는 다음과 같이 앱 번들을 이용하지 않고 단순 APK 파일로 추출하도록 하겠습니다.



  먼저 APK 파일을 만들기 위해서는 먼저 키 페어를 생성해주셔야 합니다.



  저는 다음과 같은 경로에 키를 만들어 줄 거예요.



  키를 생성할 때는 키를 생성한 사람에 대한 서명 정보를 기입해주셔야 합니다.



  이후에 다음과 같이 해당 키로 APK 파일을 생성해주시면 됩니다.




  약간의 시간이 흐른 뒤에 빌드(Build)가 끝나면 릴리즈 된 APK 파일을 확인하실 수 있습니다.




※ 깃에 업로드하기 ※


  안드로이드 프로젝트를 깃에 업로드하여 관리하는 방법 또한 알아보도록 하겠습니다.



  깃 프로젝트를 설정할 때는 루트 프로젝트를 설정하시면 됩니다.



  이후에 ADD 및 COMMIT을 진행하시면 됩니다.





  커밋을 하실 때에는 [Unversioned Files]로 표시되어 있는 프로젝트의 환경 설정 파일들도 함께 커밋해주세요.



  커밋 이후에는 푸시를 진행하시면 됩니다.



  푸시를 하실 때에는 깃 허브(Git Hub)의 원격지 주소로 푸시하시면 됩니다. 따라서 [Define Remote]를 선택합니다.



  이후에 깃 허브(Git Hub)에 하나의 리포지터리를 만들어 주시고, 이를 넣어주시면 됩니다.




  전체 파일들을 다 푸시해주시면 다음과 같이 깃 허브에 프로젝트가 등록되는 것을 확인할 수 있습니다.



※ 완성된 프로젝트를 클론(Clone)하는 방법 ※


  이후에 완성된 프로젝트를 다른 개발 환경에서 클론하고자 할 때는 다음과 같이 해주시면 됩니다.



  클론 받기 위한 주소를 넣고, 특정한 폴더로 프로젝트를 다운로드 해주세요.




  이후에 다음과 같이 클론 된 소스코드를 통해 프로젝트를 구성하시면 됩니다.




  기본적으로 계속 다음(Next) 버튼을 누르시면 됩니다.



  다음과 같이 프로젝트 클론(Clone)까지 다루어 보았습니다.


728x90
반응형

728x90
반응형

  요즘 상당수의 안드로이드 어플리케이션이 '구독(Subscribe)'을 이용한 수익 모델을 채택하고 있습니다. 구독이란 말 그대로 특정한 서비스를 주기적으로 이용하겠다는 것을 밝히는 것입니다. 구글 플레이스토어에서는 구독을 하면 자동 결제가 이루어지는 서비스 또한 제공하고 있습니다. 대표적인 사례를 알아보도록 합시다. 저는 핸드폰으로 문서를 찍은 뒤에 이것을 PDF 파일로 변환해주는 캠 스캐너(Cam Scanner) 어플리케이션을 주기적으로 사용합니다. 이 어플리케이션의 무료 버전을 사용할 때는 변환된 PDF 파일에 캠 스캐너로 촬영했다는 워터마크가 남게 됩니다.



  그리고 위와 같이 워터마크를 지우기 위해서는 고급 계정으로 업데이트하라고 나옵니다. 기본적으로 7일 동안 무료 체험을 할 수 있다고 하네요. 저는 일단 당장 PDF 변환이 급해서 7일 무료 체험을 하겠다고 클릭했습니다.



  그랬더니 위와 같이 일주일 뒤부터 약 5달러의 요금이 청구될 것이라고 하네요. 사실 그렇게 부담스러운 돈은 아니지만 제가 이 어플리케이션을 계속 사용할 지는 모르는 일이므로 7일 무료 체험만 이용하고 구독은 취소하려고 합니다.



  일단 구독하기 버튼을 눌렀더니 위와 같이 체험 종료 이후에 자동 구독이 이루어져서 구독을 하지 않으려면 무료 체험 종료 전에 플레이스토어에 가서 구독을 취소하라고 하네요.



  저는 한 번 이용한 뒤에 바로 플레이스토어로 가서 구독 취소를 하려고 했습니다. 7일 뒤에 하려고 하면 까먹을 수 있기 때문에 지금 당장 취소를 해놓으려는 거죠. 플레이스토어로 가서 '설정'에 가신 뒤에 위와 같이 '내 구독'에 들어가주세요.



  그럼 위와 같이 현재 구독 중인 어플리케이션이 나오는 것을 알 수 있습니다. 여기에서 '관리'를 누릅니다.



  이제 위와 같이 '구독 취소' 버튼을 눌러주시기만 하면 끝입니다. 이렇게 해주시면 자동으로 금액이 청구되는 것을 막을 수 있습니다.


728x90
반응형