브라더(Brother) 라벨 프린터는 무려 3가지 App.이 제공됩니다.

PC용 1종, Mobile 용 2종 입니다.

** Android 기준으로 설명합니다. iPhone은 제가 가지고 있지 않고 수정 방법도 모릅니다.

 

그런데 Mobile용에는 한글 글꼴이 단 2종 - 네! 단 2종 / 다른 Mobile app인 iPrint&Label 은 단 1종만 제공이 됩니다.

놀랍지 않나요?

당연하지만 PC용 App.은 시스템 설치된 글꼴 모두 사용할 수 있고, 고해상도 출력도 지원이 됩니다(일부 모델)

여러 이유가 있겠지만 저는 PC App 사용이 더 나을 듯 하지만, 그래도 Mobile app. 사용도 아쉬워 작업을 해 보았습니다.

구글 플레이 사용기에 보면 - 추가 글꼴 요청이 연이어 등록되었지만 제대로 된 답변이 없는 상황입니다. 이전 버전(1)에서는 되었는데 2가 나오면서 막힌듯 하더군요.

 

결과를 먼저 소개하면 아래와 같이 추가 글꼴 사용은 가능합니다

당연히 출력도 확인이 되었습니다.










 

개선해 볼 App.은 P-touch Design&Print 2 입니다

과정은 아래와 같이 요약이 되고, 직접 재 수정하실 분은 알아서 잘 하실 것으로 보입니다.

1. APK 추출

SAI(Split APKs Installer) 등을 통해서 이미 설치한 "Design&Print 2"를 "백업" 기능을 통해 추출합니다.

이때 4개 파일 모두 선택 후 / 백업 진행.

 > Design&Print 2 / 기본 APK를 위한 arm64_v8a 코드 / xxhdpi (480DPI) resoucesfor base APK / 한국어 언어

최종으로 Desing&Print 2...... apks 파일이 생성됩니다.

 

2. 단일 APK 생성

1번 과정에서 생성된 apks 파일을 PC로 가져오고, 확장자를 zip으로 수정 후, 내용물을 압축 해제합니다.

아래 URL로 가셔서 단일화 도구 - "SAP (Split APKs Packer) v6.9.0 (Convert Apks To APK)" 를 받습니다.

https://apk4all.com/android/apps/sap-split-apks-packer-windows-linux/ 

적절히(!!) 설치하여 guide 설명과 같이 합치기 과정을 진행합니다.

단! 분명 최종 과정 전에 error가 날 것이고, 그 상태에서 아래 파일만 수정 진행합니다.

파일: AndroidManifest.xml

삭제 문자열: android:localeConfig="@xml/locales_config" 

 

3. 글꼴 파일 추가

시대적 유행으로 무료 글꼴을 여러 단체에서 제공해 주고 있습니다. 저는 아래 사이트에서 미리 보기 후 제가 마음에 드는 글꼴을 다운로드하여 추가했습니다. - 개인 사용에 문제없고, 기왕이면 이상한 제약 없는 글꼴을 사용하세요.

눈누https://noonnu.cc/ 

확인한 결과 TTF / OTF 상관없이 모두 잘 동작 하기에 적절히 선택하셔서 포함하면 됩니다.

앞서 단일 APK 생성 시점에 만들어진 풀어진 package의 아래 위치로 저장하시면 됩니다(다른 기본 font 파일이 존재)

 

\assets\fonts

⛔주의 사항!

App 제약으로 두께는 기본과 BOLD 정도만 구별이 되어서 글꼴 정보에 의해서 추가 두께로 구성한 글꼴이 보이지 않을 수 있습니다. 어떤 경우는 정보가 겹쳐서 한벌만 보이는 현상이 있어서 직접 넣고 확인해야 합니다.

 

4. 재패키징 (디컴파일 하지 않았으므로 재컴파일 단어를 사용하지 않았습니다)

apktool을 이용하여 앞서 단일화 처리된 패키지를 새롭게 APK로 생성합니다.

앞서 단일 APK 생성 과정에서는 decompile을 수행하지 않고 original ***.dex 를 그대로 사용합니다.

apktool 사용이 부담스러우면 여러 GUI frontend를 사용하여 패키징을 완성하면 됩니다.

  *이 과정은 너무나 자세하고 상세한 설명이 인터넷에 있으므로 추가로 언급드리지 않습니다.

 

5. 설치

패키징 결과를 Mobile phone에 설치합니다.

단! - 앞서 재패키징 단계에 의해서 서명 단계를 건너뛰거나 임의 서명을 사용했으므로 기존 설치된 App.은 삭제 후 진행하셔야 합니다!

 

 

일반 사용자를 위한 글꼴이 추가된 sample - apk 패키징 파일

⛔주의 사항!

본 패키지 사용은 개인 사용자를 위해 편의를 위해 sample로 올려 두는 것이며, 이 파일 사용에 대한 결과에 대해서 그 어떠한 보장을 제공하는 것이 아닙니다. 

본 패키지 이용하여 발생하는 법적인 문제에 대해서는 사용하는 당사자들의 책임임을 밝혀 둡니다.
아래 파일에 대해서는 질문에 대해서도 답변을 드리지 않습니다.

 

분할 압축 파일을 모두 받은 후 압축 해제, 생성된 apk 파일을 설치하면 sample을 사용할 수 있습니다.

본 sample은 글꼴 파일 추가 이외에는 일체의 수정 사항이 없습니다.

AdditionalFontsMod.z01
19.00MB
AdditionalFontsMod.z02
19.00MB
AdditionalFontsMod.z03
19.00MB
AdditionalFontsMod.z04
19.00MB
AdditionalFontsMod.z05
19.00MB
AdditionalFontsMod.z06
19.00MB
AdditionalFontsMod.z07
19.00MB
AdditionalFontsMod.zip
4.40MB

 

추가 글꼴(삼립 호빵체)을 이용한 출력 sample

 

Android Brother label printer app. How to add fonts

나름 최신의 Intel 프로세스 기반 노트북을 구입했습니다.

데스크톱에서는 아무런 문제가 없던 무선 마우스(MX Master 3)와 키보드가 버벅거림이 없어지지 않고 사용하다 멈추고, 다시 풀리고... 엄청 힘들게 하더군요.

문제는 Intel 최신 노트북 기준에서 매우 흔하게 나타나는 증상입니다.

그런데 그런 글을 따라 해도 잠시 해결되더니 다시 현상이 반복.

 

아래처럼 USB 허브의 전원 관리 옵션을 수정해서 해결 완료했습니다.

요약하면 마우스, 키보드가 물려 있는 USB 허브의 전원 관리 해제하는 것!

 

 

1. Window key + X  누르고, 장치 관리자를 선택

 

2. 장치 관리자 - 버벅거리고 있는 마우스 선택 (그런데 어느 마우스? 아래 3에서 확인)

 

3. 마우스 각각을 선택 후 '이벤트' - 정보 부분에 보이는 VID_XXX 부분을 기억

모든 마우스에 대해 확인(별도 기록 해 두세요), 마우스를 뽑습니다(혹은 무선 마우스 어댑터 뽑기)

그리고 앞서 기록 해 둔 정보 부분과 비교하여 대상 마우스를 선택합니다.

 

4. 대상 마우스(HID 규격 마우스) 선택 상태에서, 아래처럼 '보기'메뉴에서 '연결 별 디바이스' 선택합니다.

 

 

5. 아래처럼 Tree 형태로 표시됩니다.

 

6. 상위에 위치한 'USB 허브'를 찾아 선택합니다.

이번 예시에서는 '일반 USB 허브' 선택

 

7. Enter 혹은 마우스 더블 클릭으로 속성을 열고, '전원 관리'탭을 선택

마지막으로 [v]전원을 절약하기 위해 컴퓨터가 이 장치를 끌 수 있음(A) 을 선택하여 check를 없앱니다. 

아래처럼 만들면 됩니다.

 

고생하셨습니다. 이제 끊김 없는 마우스, 키보드 사용을 ~

 

** 저는 동일 허브로 무선 마우스, USB 키보드를 연결했기에 무선 마우스가 물린 허브만 찾아서 모두 해결했습니다.

나름 깔끔한 날씨 프로그램인 eWeather HD를 Android P OS까지 문제없이 사용하고 있었습니다.

그런데 Galaxy S9을 최신 Q OS 업그레이드 직후 eWeather HD 실행, 화면이 보이는 동시에 crash가 나고 죽어 버립니다.

 

죽는 위치는 dump 하면 쉽게 확인됩니다.

JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0xc30e076c

from java.lang.String com.skt.arm.ArmManager.ARMPluginMakeChallenge(java.lang.String)

 

crash log 중요 내용은 아래와 같습니다.

02-17 02:25:19.945 10426 13450 16754 F nt.WeatherCloc: java_vm_ext.cc:570] JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0xc30e076c
02-17 02:25:19.945 10426 13450 16754 F nt.WeatherCloc: java_vm_ext.cc:570]     from java.lang.String com.skt.arm.ArmManager.ARMPluginMakeChallenge(java.lang.String)
...
...
02-17 02:25:20.220 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641] Runtime aborting...
02-17 02:25:20.220 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641] Dumping all threads without mutator lock held
02-17 02:25:20.220 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641] All threads:
02-17 02:25:20.220 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641] DALVIK THREADS (17):
02-17 02:25:20.220 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641] "AsyncTask #1" prio=4 tid=7 Runnable
02-17 02:25:20.220 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   | group="" sCount=0 dsCount=0 flags=0 obj=0x12e5fe20 self=0xd6567800
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   | sysTid=16754 nice=10 cgrp=default sched=0/0 handle=0xc3208230
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   | state=R schedstat=( 33144883 457271 28 ) utm=1 stm=1 core=5 HZ=100
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   | stack=0xc3105000-0xc3107000 stackSize=1040KB
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   | held mutexes= "abort lock" "mutator lock"(shared held)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #00 pc 002fe4ef  /apex/com.android.runtime/lib/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, int, BacktraceMap*, char const*, art::ArtMethod*, void*, bool)+78)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #01 pc 003a768b  /apex/com.android.runtime/lib/libart.so (art::Thread::DumpStack(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, bool, BacktraceMap*, bool) const+358)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #02 pc 003a3e63  /apex/com.android.runtime/lib/libart.so (art::Thread::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, bool, BacktraceMap*, bool) const+34)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #03 pc 003bc485  /apex/com.android.runtime/lib/libart.so (art::DumpCheckpoint::Run(art::Thread*)+576)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #04 pc 003b70c7  /apex/com.android.runtime/lib/libart.so (art::ThreadList::RunCheckpoint(art::Closure*, art::Closure*)+354)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #05 pc 003b67ad  /apex/com.android.runtime/lib/libart.so (art::ThreadList::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char>>&, bool)+1416)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #06 pc 00376953  /apex/com.android.runtime/lib/libart.so (art::Runtime::Abort(char const*)+1058)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #07 pc 0000855f  /system/lib/libbase.so (android::base::LogMessage::~LogMessage()+406)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #08 pc 0028806f  /apex/com.android.runtime/lib/libart.so (art::JavaVMExt::JniAbort(char const*, char const*)+1194)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #09 pc 00288211  /apex/com.android.runtime/lib/libart.so (art::JavaVMExt::JniAbortF(char const*, char const*, ...)+64)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #10 pc 003ac06f  /apex/com.android.runtime/lib/libart.so (art::Thread::DecodeJObject(_jobject*) const+538)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   native: #11 pc 00417905  /apex/com.android.runtime/lib/libart.so (_ZN3artL37JniMethodEndWithReferenceHandleResultEP8_jobjectjPNS_6ThreadE.llvm.5386863320803738609+36)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   at com.skt.arm.ArmManager.ARMPluginMakeChallenge(Native method)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   at com.skt.arm.ArmManager.a(unavailable:-1)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   at com.skt.arm.f.a(unavailable:-1)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   at com.skt.arm.f.doInBackground(unavailable:-1)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   at android.os.AsyncTask$3.call(AsyncTask.java:378)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   at java.util.concurrent.FutureTask.run(FutureTask.java:266)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
02-17 02:25:20.221 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641]   at java.lang.Thread.run(Thread.java:919)
02-17 02:25:20.230 10426 13450 16754 F nt.WeatherCloc: runtime.cc:641] 
02-17 02:25:20.230 10426 13450 16754 F nt.WeatherCloc: runtime.cc:649] JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0xc30e076c
02-17 02:25:20.230 10426 13450 16754 F nt.WeatherCloc: runtime.cc:649]     from java.lang.String com.skt.arm.ArmManager.ARMPluginMakeChallenge(java.lang.String)
...
...
--------- beginning of crash
02-17 02:25:20.230 10426 13450 16754 F libc    : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 16754 (AsyncTask #1), pid 13450 (nt.WeatherClock)
02-17 02:25:20.251  1000  4997  5086 E libprocessgroup: Failed to kill process cgroup uid 10158 pid 13776 in 206ms, 1 processes remain
02-17 02:25:20.279 10426 16786 16786 E crash_dump32: unknown process state: t
02-17 02:25:20.290 10426 16786 16786 I crash_dump32: obtaining output fd from tombstoned, type: kDebuggerdTombstone
02-17 02:25:20.295  1058  4758  4758 I /system/bin/tombstoned: received crash request for pid 16754
02-17 02:25:20.296  1000  4777  5396 D bauth_FPBAuthService: pcf : 0x1012, 0 ,2 ,0 ,0 ,0 ,2, 5.0.0.0
02-17 02:25:20.296  1000  4777  5396 D bauth_FPBAuthService: thread id : 2, preenroll_flag : 0, nd cnt : 1, cso : 0, et : 0
02-17 02:25:20.296  1000  4777  5396 D bauth_FPBAuthService: FPBAuthService, 10979
02-17 02:25:20.296 10426 16786 16786 I crash_dump32: performing dump of process 13450 (target tid = 16754)
02-17 02:25:20.307 10426 16786 16786 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
02-17 02:25:20.308 10426 16786 16786 F DEBUG   : Build fingerprint: 'samsung/starlteks/starlteks:10/QP1A.190711.020/G960NKSU2DTAB:user/release-keys'
02-17 02:25:20.308 10426 16786 16786 F DEBUG   : Revision: '26'
02-17 02:25:20.308 10426 16786 16786 F DEBUG   : ABI: 'arm'
02-17 02:25:20.308 10426 16786 16786 F DEBUG   : Timestamp: 2020-02-17 02:25:20+0900
02-17 02:25:20.308 10426 16786 16786 F DEBUG   : pid: 13450, tid: 16754, name: AsyncTask #1  >>> com.Elecont.WeatherClock <<<
02-17 02:25:20.308 10426 16786 16786 F DEBUG   : uid: 10426
02-17 02:25:20.308 10426 16786 16786 F DEBUG   : signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
02-17 02:25:20.308 10426 16786 16786 F DEBUG   : Abort message: 'JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0xc30e076c

대충 보면 skt에서 제공하는 so library의 특정 native 함수에서 죽는 문제입니다.

업데이트가 매우 오래전에 멈추어진 App.이라 그럴 수도 있겠죠.

 

핵심 호출 부분은 아래입니다.

at com.skt.arm.f.a(unavailable:-1)

at com.skt.arm.f.doInBackground(unavailable:-1)

 

즉 doInBackground 안에서 호출하는 com.skt.arm.f.a 호출 흐름에서 죽습니다.

이걸 해결할 방법은 없고 대신 호출을 막습니다.

그리고 test하니 - SKT 서비스가 없다면서 App. 을 강제 종료 해 버립니다 우쓰!

 

그래서 doInBackground 종료 후 호출되는 onPostExecute 의 주요 호출을 막으니, 정상 동작이 됩니다.

아마다 예전 SKT 관련 서비스 유무 확인 혹은 여러 내용(라이센?!)을 확인하는 루틴이 Q OS에서 동작이 되지 않은 듯 합니다.

 

어찌 되었건 문제는 해결되었습니다.

비록 오래된 App.이지만 더 이상 update 되지 않는 버전이지만 문제만 해결해서 계속 사용하게 되었습니다.

** 해당 App. 은 Play store에 최신 버전의 App. 이 제공되지만 예전 T Store 와는 다른 signature 사용으로 인해 업그레이드를 할 수 없습니다.

 

주요 수정 point는 아래와 같이 요약할 수 있습니다. 단순히 smali 수준에서 문제 함수를 막아서 해결했습니다.

맨 앞에 # 한 부분입니다.

# virtual methods
.method protected final varargs synthetic doInBackground([Ljava/lang/Object;)Ljava/lang/Object;
    .locals 1

#    invoke-direct {p0}, Lcom/skt/arm/f;->a()Ljava/lang/String;

#    move-result-object v0
	const-string v0, " Not ACTIVITY"

    return-object v0
.end method

.method protected final synthetic onPostExecute(Ljava/lang/Object;)V
    .locals 1

    check-cast p1, Ljava/lang/String;

    invoke-super {p0, p1}, Landroid/os/AsyncTask;->onPostExecute(Ljava/lang/Object;)V

#    iget-object v0, p0, Lcom/skt/arm/f;->a:Lcom/skt/arm/e;

#    invoke-static {v0}, Lcom/skt/arm/e;->a(Lcom/skt/arm/e;)Lcom/skt/arm/ArmManager;

#    move-result-object v0

#    invoke-static {v0}, Lcom/skt/arm/ArmManager;->b(Lcom/skt/arm/ArmManager;)V

    return-void
.end method

위 내용 참고요 스크린 샷 (APK Studio)

APK Studio to fix the crash

* 수정 후 정상 동작 스크린 샷~

 

 

** 리버스 엔지니어링은 더이상 업그레이드가 제공되지 않는 S/W 에 대한 호환성 확보를 위한 목적에는 적법합니다.

컴퓨터프로그램 보호법 - 역분석 관련 법

제12조의2 (프로그램코드역분석)
①정당한 권원에 의하여 프로그램을 사용하는 자 또는 그의 허락을 받은 자가 호환에 필요한 정보를 쉽게 얻을 수 없고 그 획득이 불가피한 경우 당해 프로그램의 호환에 필요한 부분에 한하여 프로그램저작권자의 허락을 받지 아니하고 프로그램코드역분석을 할 수 있다.
②제1항의 규정에 의한 프로그램코드역분석을 통하여 얻은 정보는 다음 각호의 1에 해당하는 경우에는 이를 사용할 수 없다.
   1. 호환 목적외의 다른 목적을 위하여 이용하거나 제3자에게 제공하는 경우
   2. 프로그램코드역분석의 대상이 되는 프로그램과 표현이 실질적으로 유사한 프로그램을 개발·제작·판매하거나 기타의 프로그램저작권을 침해하는 행위에 이용하는 경우
      [본조신설 2001·1·16][[시행일 2001·7·17]]

 


집에서 java app.을 실행 하려 했더니 실행 즉시 app.이 닫혀 버리는 증상이 확인 되었습니다.

해당 app.을 다른 컴퓨터(Windows 7 구동)에서는 정상 작동 하는 것을 확인 했던 것이라 매우 이상한 상황!


Java crash log의 핵심만 요약 하면 아래와 같습니다.

. . .

# A fatal error has been detected by the Java Runtime Environment:

#

#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000062146adf, pid=8912, tid=0x00000000000009b8

#

# JRE version: Java(TM) SE Runtime Environment (8.0_131-b11) (build 1.8.0_131-b11)

# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.131-b11 mixed mode windows-amd64 compressed oops)

# Problematic frame:

# C  [msvcr100.dll+0x36adf]


. . .

. . .


Stack: [0x000000001f680000,0x000000001f780000],  sp=0x000000001f77ecc8,  free space=1019k

Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)

C  [msvcr100.dll+0x36adf]


Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)

J 2701  sun.awt.shell.Win32ShellFolder2.getDisplayNameOf(JJI)Ljava/lang/String; (0 bytes) @ 0x00000000028412c9 [0x0000000002841280+0x49]

j  sun.awt.shell.Win32ShellFolder2.access$1600(JJI)Ljava/lang/String;+4

j  sun.awt.shell.Win32ShellFolder2$13.call()Ljava/lang/String;+15

j  sun.awt.shell.Win32ShellFolder2$13.call()Ljava/lang/Object;+1

J 1987 C1 java.util.concurrent.FutureTask.run()V (126 bytes) @ 0x0000000002d4764c [0x0000000002d47400+0x24c]

. . .

. . .


결론은 아래의 bug report를 보면 되는데.

요약 하면 Windows 10 최신 update로 인하여 GOD mode를 설정한 폴더명이 NULL 로 처리 되어 java awt내부 code에서 crash를 일어키는 현상 입니다.

MS를 미워할 수는 없는것이 결국 java에서 exception handling을 안해서 여서...


그런데 수정 내용을 보니, 원 Java 9에서만 수정 반영 했다는 것! 

Java 8은 그냥 쌩....


그래서 해결 방법은 만일 바탕화면에 GOD mode 설정한 폴더가 있다면 (이름이 없습니다) 이것을 삭제 하거나 다른 폴더로 이동 후 java app.을 실행 하면 됩니다.


Java 9 을 사용할 계획이 없다면 가장 적절한 선택일 것 같습니다.


위 내용에 대한 java bug report는 아래 URL에서 확인 가능 합니다.

http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8179014


관련 사항은 아래와 같이 여러 리포트가 있습니다.

Backport:
Backport:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Duplicate:
Relates:
Relates:


이로서 Bug는 가만히 있어도 (남들에 의해서) 만들어 진다는 진리? 를 아주 큰 S/W 기업에서도 확인이 되었네요^^ (그렇다고 엄청난 예외 code를 넣는 것도 쉽지 않으니)


보너스~ 해당 문제 해결 code 변경 사항은 아래와 같습니다.

http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/a7c8147f1891


files src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp test/javax/swing/JFileChooser/GodMode/JFileChooserTest.java

--- a/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp	Tue May 09 12:19:08 2017 -0700
+++ b/src/java.desktop/windows/native/libawt/windows/ShellFolder2.cpp	Thu May 11 12:41:35 2017 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -205,14 +205,19 @@
 static jstring jstringFromSTRRET(JNIEnv* env, LPITEMIDLIST pidl, STRRET* pStrret) {
     switch (pStrret->uType) {
         case STRRET_CSTR :
-            return JNU_NewStringPlatform(env, reinterpret_cast<const char*>(pStrret->cStr));
+            if (pStrret->cStr != NULL) {
+                return JNU_NewStringPlatform(env, reinterpret_cast<const char*>(pStrret->cStr));
+            }
+            break;
         case STRRET_OFFSET :
             // Note : this may need to be WCHAR instead
             return JNU_NewStringPlatform(env,
                                          (CHAR*)pidl + pStrret->uOffset);
         case STRRET_WSTR :
-            return env->NewString(reinterpret_cast<const jchar*>(pStrret->pOleStr),
-                static_cast<jsize>(wcslen(pStrret->pOleStr)));
+            if (pStrret->pOleStr != NULL) {
+                return env->NewString(reinterpret_cast<const jchar*>(pStrret->pOleStr),
+                    static_cast<jsize>(wcslen(pStrret->pOleStr)));
+            }
     }
     return NULL; 

} 


즐 개발 / 즐 컴퓨팅 되시길~


Android play store에서 대용량 게임 업그레이드 후 실행 문제 해결 내용을 잊기 전에 정리 해 봅니다.




최근 업데이트한 게임(Angry Birds 2 이하 AB 2)이 갑자기 실행이 되지 않고... 이상한 메시지만 보이는 문제가 있었습니다.


문제 보고 메시지가 단지 ". Google Play" 라고만 나오는데, 황당할 따름이죠.

더욱이 AB 2 의 경우 Google 계정으로는 백업이 되지 않습니다. 

결국 Rovio 쪽으로도 contact 했지만 - 역시나 그들도 뭘 알겠습니까?!


앞서 이상한 메시지라도 바로 보기 위해 device 언어를 한글 -> 영어로 바꾸어서 실행하니 문제가 명확 해 지더군요.

요약하면 "Asset 을 읽어 들일 수 없다. 삭제 후 재설치 해라" 라는 영문 메시지가 이제 서야 잘 보이더군요. 한글 상태에서는 어떤 이유에서인지 - 아마도 번역이 제대로 되지 않았지 않을까 상상만.


어찌 되었건 문제를 해결하려면 재설치 인데 - 그러면 data가 모조리 날아 가기에 제가 했던 게임 내용도 포기 해야 합니다. 그렇게는 할 수 없고... APK를 직접 구해서 재설치 하는 방향으로 바꾸었습니다.


다행이 AB 2 의 경우 유명 게임이기도 하고 해서 apkplz.com 이라는 곳에서 APK를 쉽게 구할 수 있습니다.


그리고 알아낸 것이 게임의 경우 한개의 초 대용량 APK가 아닌, OBB 파일을 따로 두어서 별도 리소스 부분은 이 OBB에 두는 형식 이더군요!


문제가 분명 해 졌습니다!

Play store에서 분명 업그레이드를 했음에도 불구하고(Google이 잘못 했네?) APK는 제대로 설치(실행은 되니) 별도 리소스 파일인 OBB에 문제가 있었던 것이죠.


아래 위치에 있어야 할 data파일이 누락되어 있었던 것입니다.

문제 상황에서 아래의 obb/com.rovio.baba 가 통으로 존재 하지 않았다는 문제!

/storage/emulated/0/Android/obb/com.rovio.baba/main.2060008.com.rovio.baba.obb


그런데 디렉토리 흔적은 아래에서 확인이 됩니다. 즉 파일은 미존재 상태.

/storage/extSdCard/Android/obb/com.rovio.baba/



결국 앞서 언급한 APK 저장 사이트(apkplz.com)에서 패키지를 다운로드 후, 수작업으로 .obb 파일을 올려 두니 이제 서야 게임이 정상 작동!



요약

(게임과 같은 단일 APK로 설치가 완료 되지 않는 경우)

실행이 되지 않는 문제가 있을 경우 .OBB 파일이 제대로 설치 되었는지 확인 후 적절히 해당 파일을 복사 하면 잘 실행 됨.


아래는 apkplz.com 에서 언급한 해당 사항입니다.


This download file have .apk and .obb (data) file.

Install APK and OBB on your android phone:


Place the APK file in your phone’s SDcard or Internal memory (preferably external SDcard).

Browse your phone memory/external memory and tap on the APK file.

Click ‘install’

Wait for the APK to install.

Do not run the application yet.

Copy the OBB folder to SDCard, ex: SDCARD/Android/obb/com.rovio.baba/obb_filename*

What are .OBB file?

.OBB file are APK Expansion Files Developers create OBB files to contain and bundle larger assets using the JOBB tool for Android SDK. They hold additional encrypted format data not stored in the main application package, including graphics and media files. They can be uploaded with the APK file using the Google Play Developer Console.



기술 자료를 좀더 보니, .obb 파일에 대한 관리를 application에서 직접 할 수 있더군요.

즉 실행 시점에 해당 파일이 없거나 문제가 있을 경우, 혹은 의도적으로 처음 실행시에 .obb 파일을 application에서 직접 다운로드가 가능 하다는 것!

즉 1차 잘못은 구글 설치자에 있었겠지만, 궁극적으로는 Rovio 의 AB 2에서 실행 시점에 해당 파일이 어떤 연유로 없거나 사용 불가면 다시 한번 다운로드 처리 해야 하는데 그러한 예외 처리가 빠져 있는 것 같네요.


Most of the time, Google Play downloads and saves your expansion files at the same time it downloads the APK to the device. However, in some cases Google Play cannot download the expansion files or the user might have deleted previously downloaded expansion files. To handle these situations, your app must be able to download the files itself when the main activity starts, using a URL provided by Google Play.



+ Recent posts