package com.majorworld.alldeal;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import android.Manifest;
import android.annotation.TargetApi;
import android.content.Intent;
import android.graphics.Bitmap;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.util.Log;
import android.view.KeyEvent;
import android.webkit.JsResult;
import android.webkit.ValueCallback;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.Toast;
import java.io.File;
//import com.google.android.gms.tasks.OnCompleteListener;
//import com.google.android.gms.tasks.Task;
//import com.google.firebase.iid.FirebaseInstanceId;
//import com.google.firebase.iid.InstanceIdResult;
//import com.google.firebase.iid.FirebaseInstanceId;
//import com.google.firebase.iid.InstanceIdResult;
import java.net.URISyntaxException;
import java.util.HashMap;
public class MainActivity extends AppCompatActivity {
// --------------------------- SETTING --------------------------- //
private static final String TAG = "MainActivityLog";
private WebView webView1;
private ProgressBar pBar;
private String defaultUrl = "https://alldeal.kr";
private WebSettings webSettings;
private long time = 0;
public ValueCallback<Uri> filePathCallbackNormal;
public ValueCallback<Uri[]> filePathCallbackLollipop;
public final static int FILECHOOSER_NORMAL_REQ_CODE = 2001;
public final static int FILECHOOSER_LOLLIPOP_REQ_CODE = 2002;
private Uri cameraImageUri = null;
// ------------------------- ONCREATE -------------------------- //
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView1 = (WebView) findViewById(R.id.wView);
pBar = findViewById(R.id.pBar);
//초기 권한 필요할 시
//checkVerify();
webSettings = webView1.getSettings();
webSettings.setJavaScriptEnabled(true); // 자바스크립트 사용
webSettings.setSupportMultipleWindows(true); // 새창 띄우기 허용
webSettings.setJavaScriptCanOpenWindowsAutomatically(true); // 자바스크립트 새창 띄우기 허용
webSettings.setLoadWithOverviewMode(true); // 메타태그 허용
webSettings.setUseWideViewPort(true); // 화면 사이즈 맞추기 허용
webSettings.setSupportZoom(false); // 화면줌 허용 여부
webSettings.setBuiltInZoomControls(false); // 화면 확대 축소 허용 여부
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); // 컨텐츠 사이즈 맞추기
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); // 브라우저 노캐쉬
webSettings.setDomStorageEnabled(true); // 로컬저장소 허용
webSettings.setAllowUniversalAccessFromFileURLs(true);
webSettings.setSaveFormData(false);
webSettings.setTextZoom(95);
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
webView1.loadUrl(defaultUrl);
webView1.setWebChromeClient(new WebChromeClientClass()); //웹뷰에 크롬 사용 허용. 이 부분이 없으면 크롬에서 alert가 뜨지 않음
webView1.setWebViewClient(new WebViewClientClass());
}
// ------------------------- BACK PRESSED -------------------------- //
@Override
public void onBackPressed() {
//super.onBackPressed();
if(System.currentTimeMillis()-time>=2000){
time=System.currentTimeMillis();
Toast.makeText(getApplicationContext(),"뒤로 버튼을 한번 더 누르면 종료합니다.",Toast.LENGTH_SHORT).show();
}else if(System.currentTimeMillis()-time<2000){
finish();
return;
}
}
// ------------------------- CAMERA ACTIVATE & FILE UPLOAD -------------------------- //
//권한 획득 여부에 따른 결과 반환
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
{
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//Log.d("onRequestPermissionsResult() : ","들어옴");
if (requestCode == 1)
{
if (filePathCallbackLollipop != null) {
filePathCallbackLollipop.onReceiveValue(null);
filePathCallbackLollipop = null;
}
HashMap<String, Boolean> grantResultsMap = new HashMap<>();
if (grantResults.length > 0)
{
boolean chk = true;
for (int i = 0; i < permissions.length; i++) {
String permission = permissions[i];
int grantResult = grantResults[i];
// Check if the permission is granted or not
if (grantResult == PackageManager.PERMISSION_GRANTED) {
grantResultsMap.put(permission, true);
Log.d(TAG, permission + " is granted");
} else {
grantResultsMap.put(permission, false);
Log.d(TAG, permission + " is denied");
}
}
boolean cameraChk = grantResultsMap.get("android.permission.CAMERA");
boolean writeChk = grantResultsMap.get("android.permission.WRITE_EXTERNAL_STORAGE");
boolean readChk1 = grantResultsMap.get("android.permission.READ_EXTERNAL_STORAGE");
boolean readChk2 = grantResultsMap.get("android.permission.READ_MEDIA_IMAGES");
if(cameraChk && ((writeChk && readChk1) || readChk2)){
//runCamera(false);
Toast.makeText(getApplicationContext(),"카메라 및 저장소 사용이 허용되었습니다.",Toast.LENGTH_SHORT).show();
return;
}
}
}
}
//액티비티가 종료될 때 결과를 받고 파일을 전송할 때 사용
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//Log.d("onActivityResult() ","resultCode = " + Integer.toString(requestCode));
switch (requestCode)
{
case FILECHOOSER_NORMAL_REQ_CODE:
if (resultCode == RESULT_OK)
{
if (filePathCallbackNormal == null) return;
Uri result = (data == null || resultCode != RESULT_OK) ? null : data.getData();
// onReceiveValue 로 파일을 전송한다.
filePathCallbackNormal.onReceiveValue(result);
filePathCallbackNormal = null;
}
break;
case FILECHOOSER_LOLLIPOP_REQ_CODE:
//Log.d("onActivityResult() ","FILECHOOSER_LOLLIPOP_REQ_CODE = " + Integer.toString(FILECHOOSER_LOLLIPOP_REQ_CODE));
if (resultCode == RESULT_OK)
{
//Log.d("onActivityResult() ","FILECHOOSER_LOLLIPOP_REQ_CODE 의 if문 RESULT_OK 안에 들어옴");
if (filePathCallbackLollipop == null) return;
if (data == null)
data = new Intent();
if (data.getData() == null)
data.setData(cameraImageUri);
filePathCallbackLollipop.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
filePathCallbackLollipop = null;
}
else
{
//Log.d("onActivityResult() ","FILECHOOSER_LOLLIPOP_REQ_CODE 의 if문의 else문 안으로~");
if (filePathCallbackLollipop != null)
{ // resultCode에 RESULT_OK가 들어오지 않으면 null 처리하지 한다.(이렇게 하지 않으면 다음부터 input 태그를 클릭해도 반응하지 않음)
//Log.d("onActivityResult() ","FILECHOOSER_LOLLIPOP_REQ_CODE 의 if문의 filePathCallbackLollipop이 null이 아니면");
filePathCallbackLollipop.onReceiveValue(null);
filePathCallbackLollipop = null;
}
if (filePathCallbackNormal != null)
{
filePathCallbackNormal.onReceiveValue(null);
filePathCallbackNormal = null;
}
}
break;
default:
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
// 카메라 기능 구현
private void runCamera(boolean _isCapture)
{
Intent intentCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//intentCamera.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//File path = getFilesDir();
/* 2023-04-25 주석처리
File path = Environment.getExternalStorageDirectory();
File file = new File(path, "sample.png"); // sample.png 는 카메라로 찍었을 때 저장될 파일명이므로 사용자 마음대로
// File 객체의 URI 를 얻는다.
*/
// 2023-04-25 수정코드
File path = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),"androidExampleFolder");
if(!path.exists()){
path.mkdirs();
}
File file = new File(path+File.separator+"IMG_" + String.valueOf(System.currentTimeMillis())+".jpg");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
String strpa = getApplicationContext().getPackageName();
cameraImageUri = FileProvider.getUriForFile(this, strpa + ".fileprovider", file);
}
else
{
cameraImageUri = Uri.fromFile(file);
}
intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, cameraImageUri);
if (!_isCapture)
{ // 선택팝업 카메라, 갤러리 둘다 띄우고 싶을 때
Intent pickIntent = new Intent(Intent.ACTION_PICK);
pickIntent.setType(MediaStore.Images.Media.CONTENT_TYPE);
pickIntent.setData(MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
String pickTitle = "사진 가져올 방법을 선택하세요.";
Intent chooserIntent = Intent.createChooser(pickIntent, pickTitle);
// 카메라 intent 포함시키기..
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{intentCamera});
startActivityForResult(chooserIntent, FILECHOOSER_LOLLIPOP_REQ_CODE);
}
else
{// 바로 카메라 실행..
startActivityForResult(intentCamera, FILECHOOSER_LOLLIPOP_REQ_CODE);
}
}
// ------------------------- ONKEY DOWN -------------------------- //
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode==KeyEvent.KEYCODE_BACK) && webView1.canGoBack()) {
webView1.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
// ------------------------- CHROME CLIENT -------------------------- //
private class WebChromeClientClass extends WebChromeClient {
// 자바스크립트의 alert창
@Override
public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
new AlertDialog.Builder(view.getContext())
.setTitle("Alert")
.setMessage(message)
.setPositiveButton(android.R.string.ok,
new AlertDialog.OnClickListener(){
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
})
.setCancelable(false)
.create()
.show();
return true;
}
// 자바스크립트의 confirm창
@Override
public boolean onJsConfirm(WebView view, String url, String message,
final JsResult result) {
new AlertDialog.Builder(view.getContext())
.setTitle("Confirm")
.setMessage(message)
.setPositiveButton("Yes",
new AlertDialog.OnClickListener(){
public void onClick(DialogInterface dialog, int which) {
result.confirm();
}
})
.setNegativeButton("No",
new AlertDialog.OnClickListener(){
public void onClick(DialogInterface dialog, int which) {
result.cancel();
}
})
.setCancelable(false)
.create()
.show();
return true;
}
// For Android 5.0+ 카메라 - input type="file" 태그를 선택했을 때 반응
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public boolean onShowFileChooser(
WebView webView, ValueCallback<Uri[]> filePathCallback,
FileChooserParams fileChooserParams) {
//Log.d("TAG", "5.0+");
if (
ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ||
(
(
ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
) && ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED
)
){
Toast.makeText(getApplicationContext(),"추가 권한 요청이 필요한 서비스입니다.",Toast.LENGTH_SHORT).show();
ActivityCompat.requestPermissions(MainActivity.this,new String[]{
Manifest.permission.INTERNET,
Manifest.permission.CAMERA,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.READ_MEDIA_IMAGES
}, 1);
return false;
}
// Callback 초기화 (중요!)
if (filePathCallbackLollipop != null) {
filePathCallbackLollipop.onReceiveValue(null);
filePathCallbackLollipop = null;
}
filePathCallbackLollipop = filePathCallback;
boolean isCapture = fileChooserParams.isCaptureEnabled();
//Log.d("onShowFileChooser : " , String.valueOf(isCapture));
runCamera(isCapture);
return true;
}
}
// ------------------------- WEBVIEW CLIENT (INTENT SETTING) -------------------------- //
private class WebViewClientClass extends WebViewClient {
@Override // 1) Loading
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
pBar.setVisibility(View.VISIBLE); // Show Loading
}
@Override // 2) Start
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
pBar.setVisibility(View.GONE); // Hide Loading
}
@TargetApi(Build.VERSION_CODES.N)
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
//Log.d("WebViewClient URL : " , request.getUrl().toString());
if (request.getUrl().getScheme().equals("intent")) {
try {
// Intent 생성
Intent intent = Intent.parseUri(request.getUrl().toString(), Intent.URI_INTENT_SCHEME);
// 실행 가능한 앱이 있으면 앱 실행
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
//Log.d(TAG, "ACTIVITY: " + intent.getPackage());
return true;
}
// Fallback URL이 있으면 현재 웹뷰에 로딩
String fallbackUrl = intent.getStringExtra("browser_fallback_url");
if (fallbackUrl != null) {
view.loadUrl(fallbackUrl);
//Log.d(TAG, "FALLBACK: " + fallbackUrl);
return true;
}
// 앱이 설치되어 있지 않으면 마켓으로 이동
Intent marketIntent = new Intent(Intent.ACTION_VIEW);
//카카오링크 예외처리
String packageName;
if(request.getUrl().toString().contains("kakaolink")){
packageName = "com.kakao.talk";
}else{
packageName = intent.getPackage();
}
marketIntent.setData(Uri.parse("market://details?id=" + packageName));
if (marketIntent.resolveActivity(getPackageManager()) != null) {
startActivity(marketIntent);
//Log.d(TAG, "MARKET: " + intent.getPackage());
return true;
}
//Log.e(TAG, "Could not parse anything");
} catch (URISyntaxException e) {
//Log.e(TAG, "Invalid intent request", e);
}
}
view.loadUrl(request.getUrl().toString());
return true;
}
}
}