윈도우를 새로 설치했다. 안드로이드 스튜디오에서 Installed Build Tools revision 31.0.0 is corrupted. 라는 오류를 뿜는다. 구글에 검색해보니 build-tools를 30.0.3으로 낮추라는 글만 나온다. 이러면 근본적인 해결책이 아니라 임시방편이잖아? 조금 더 찾아본다. dx.bat와 dx.jar이 없어서 나오는 오류라고 한다. 탐색기에서 C:/Users/username/AppData/Local/Android/Sdk/build-tools/31.0.0 으로 이동한다. d8.bat파일이 보인다. 복사, 붙여넣기, dx.bat로 이름변경 lib폴더에 들어가 d8.jar 파일도 마찬가지로 원본 복사 후 dx.bat로 이름을 바꿔준다. 끝. Reference: https:/..
Mobile App
본 포스팅은 "방법"을 제시할 뿐 해결책을 제시하지는 못합니다. 삼성 스마트폰은 Knox라는 보안 솔루션이 적용되어 있으며, 은행 앱과 삼성페이 이용에는 Knox가 필수입니다. 본 포스팅을 따라 진행하면 Knox가 영구적으로 비활성화되어 고가의 부품인 메인보드를 교체하기 전까지는 은행 앱 및 삼성페이 사용이 불가합니다. 본 포스팅을 따라 진행하다가 스마트폰이 무한 재부팅 하거나, 부팅이 되지 않는 경우 책임질 수 없습니다. 1. 준비물 - 오딘 - TWRP for S8+ (G995N), 다른 폰은 여기에서 검색 후 다운로드 2. 사전 작업 - 설정 → 휴대전화 정보 → 소프트웨어 정보 - "빌드번호" 항목을 연속해서 5회 이상 터치 - 개발자모드가 활성화되면 뒤로가기→개발자 옵션 - USB 디버깅 체크 ..
플레이스토어에 targetSdkVersion이 31이하면 앱이 올라가지 않아서 31로 맞춘 후 아래 형식으로 FCM 메세지를 보내면 백그라운드에서 앱이 실행되지 않는 문제가 생겼다. { "to": "", "notification": { "title": "", "body": "", "click_action": "MAIN_ACTIVITY" }, "data": { "title": "", "body": "" } } 안드로이드 10, 11이 설치된 기기에서는 정상인데, 안드로이드 12에서만 해당 오류가 발생했다. 위에서 notification을 빼면 실행이 잘 되긴 하는데, 백엔드에서는 플랫폼 구분 없이 전송하는 형태여서 여태 개발된 많은 앱들을 전부 수정해줄 수는 없는 노릇이었다. 구글링을 아무리 해봐도 옛날 ..
플레이스토어에 앱 업로드 시 versionCode가 기존에 올라가있는 Bundle과 같거나 작을 경우 업로드가 차단된다. 매번 까먹고 다시 빌드해서 다시 올리는건 상당히 귀찮은 일이다. 다행히도 Gradle 문법에서 Programmatically Versioning이 가능하다. 먼저 Module단계의 폴더(기본: app)에 version.properties 파일을 하나 생성해 주고 관리하고 싶은 버전의 이름을 넣는다. VERSION_MAIN=0 VERSION_SUB=1 VERSION_CHILD=5 VERSION_RELEASE=5 이후 Module 단계의 build.gradle을 수정해주면 된다. 나는 Main은 신규기능 추가나 시스템 개편 등 업데이트를 설치하지 않으면 앱 사용이 불가할 정도의 업데이트 ..
Intro SSL Handler가 구현되어있는 최초 버전 (버전코드 1번)이 테스트 트랙에 올라가 있다는 이유로 구글플레이에서 삭제되었다. 당장 해당 트랙을 비활성화 한 뒤 업데이트를 시도해 보았지만 Cross App Scripting Vulnerability로 리젝되어 클라이언트의 요청이 지속되는 상황이었다. Vulnerability APK Version(s) Past Due Date Cross-app Scripting Your app(s) are using a WebView that is vulnerable to cross-app scripting. To address this issue, follow the steps in this Google Help Center article. 33 August..
iOS 에서의 Javascript Interface Bridge는 단방향, JS -> Native로밖에 값을 전달하지 못한다. 따라서 js에 setValue() 등의 함수를 사용해야 한다.. 그러나 window.webkit.messageHandler.foo.postMessage(args) 를 호출하고, 네이티브에서 evalJavascript로 setFooValue(bar) 함수를 호출해 밸류를 지정해준다 한들, 완성된 js코드를 보는 후임 개발자 입장에서 코드가 쉽게 눈에 들어오지 않을 것이고, 예쁘지도 않다. 또 리턴받아야 하는 함수가 여러 개인 경우 setValue() 함수를 여러번 생성해야 하며, Android JavascriptInterface Bridge와 다른 방식으로 사용해야 한다. 안드로이..
카톡로그인 인텐트를 아래와 같이 처리해줬다. @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith("intent:")) { 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.ACTI..
MainActivity.java private long backKeyPressedTime = 0; private Toast toast; @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK)) { // 웹뷰 History상 이전 페이지가 있을 경우 if(mWebView.canGoBack()){ mWebView.goBack(); // 뒤로가기 return true; } // 없을 경우 앱 종료 전 Toast로 물어보기 else{ // 토스트메세지 출력 if (System.currentTimeMillis() > backKeyPressedTime + 2000) { backKeyP..
Activity에서 처리하는 경우 activity_main.xml MainActivity.java WebView mWebView; WebSettings mWebSettings; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mWebView = (WebView) findViewById(R.id.mWebview); // 웹뷰 선언 mWebSettings = mWebView.getSettings(); mWebView.setWebChromeClient(new WebChromeClient()); // 크롬클라이언트 사용 mWebVi..
이전 포스팅 : 안드로이드 프래그먼트 활용하기 안드로이드 프래그먼트 활용하기 MainActivity.java public class MainActivity extends AppCompatActivity { private FragmentManager fragmentManager; private Fragment_Main fragment_main; private Fragment_MyPage fragment_my_page; privat.. jyspw.tistory.com 사전 작업 1. res 폴더 우클릭 -> New -> Android Resources Directory -> menu 폴더 생성 2. res/drawable -> New -> Vector Asset -> 사용할 Clipart 이미지 생성 Mai..