그 이유는 libjpeg-turbo 라는 프로젝트와 mozjpeg 라는 프로젝트에서 해당 버전의 libjpeg를 기반으로 개발되었기 때문이다.
그리고 6b 버전이후 거의 10년만에 업데이트된 버던7에서는 무손실 jpegtran 기능과 무슨 arithmetic coding 적용과 scaled DCT 으로 성능개선이 된것이 전부이다.
이후 버전 8 부터 버그랑 몇가지 기능들이 추가되기는 했지만, 하위버전 호환성을 유지하면서 jpeg에 새롭고 혁신적인 것이 추가되기는 어려운 상황으로 보인다. web 환경에 특화되어 있는 google에서 발표한 webP 형식처럼 새로운 술은 새부대가 아니고서는 혁신을 담아내기는 어려울듯 싶다.
이후 버전9 에서는 YCoCg 칼라스페이스 추가와 광색역(wide color gamut) 그리고 계산성능향상 ( computation improvements ) 등등의 변화가 추가되었다.
최신버전인 9e 버전에서는 msvc 빌드환경에서 arm / arm64 빌드가 지원된다고 한다.
추가로 6b 에서 파생되었다는 2가지 프로젝트에 대해서 간단하게 알고만 넘어가보자.
libjpeg-turbo
libjpeg-turbo는 SIMD 지침을 사용하여 기본 JPEG 인코딩 및 디코딩을 가속화하는 libjpeg의 포크입니다.
일반적으로 libjpeg 보다 2~4배정도 인코딩 속도가 빠릅니다. ( 디코딩 속도는 대략 1.5배정도 )
현재 널리 사용되는 Linux 배포판(Fedora, Debian, Mageia, openSUSE 등), Mozilla 및 Chrome을 포함하여 많은 프로젝트에서 libjpeg 대신 libjpeg-turbo를 사용하고 있습니다.
libjpeg-turbo는 SmartScale을 지원하지 않기로 결정했습니다.
왜냐하면 SmartScale은 ITU-T 표준이 아니고 자체 연구에서 이 기능(및 DCT 스케일링)이 비효율적이라고 판단했기 때문libjpeg v7, v8 및 v9는 이전 릴리스와의 ABI 호환성을 중단했습니다.
mozjpeg
mozjpeg는 Josh Aas와 Mozilla Research의 다른 사람들이 수행한 libjpeg-turbo의 포크입니다.
이미지 품질을 유지하면서 코딩 효율성 향상을 통해 파일 크기(약 10%)를 줄여서 저장할수 있게 합니다.
저장된 파일 크기가 작다는 것은 web 환경에서 전송 시간을 줄일수 있어서 웹페이지 로딩 시간을 단축할 수 있습니다.
이를 위해 JPEG 표준과의 완전한 호환성을 유지하고, 인코딩에 많은 시간이 소요되는 방식입니다.
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
플러터는 하나의 원소스 멀티플랫폼을 추구하는 GUI 프레임 워크이다.
하나의 소스로 android, iOS, Windows, Linux 및 웹용 애플리게이션을 만들수 있으므로, 요즘같은 시대에 매력적인 프레임워크라고 할 수있다.
또하나의 장점으로는 동일한 사용자 경험( User Experience )을 제공할수 있다는 것이다. 모바일 플랫폼인 android와 iOS만 하더라도 각각의 OS 가 추구하는 디자인이 다르고, UI 철학도 다른데 플러터를 이용하면 같은 UI 를 제공할 수 있게되므로 하나의 서비스라면 android, iOS, Windows 에 통일된 UX를 하나의 소스로 구현하게 되므로 생산성 향상및 서비스의 완성도도 올라간다고 할 수 있다.
안드로이드 스튜디오 설치가 되었으면, 플러터 닥터를 실행해서 안드로이드 연결을 위한 점검을 한다.
flutter doctor
그러면 자동으로 환경 체크를 하면서 문제가 있으면 문제가 있다고 알려준다. 예를들면 아래와 같은 형식이다. 아래는 Android SDK 경로는 찾았는데, command line tools 를 못찾았으니 친절하게 다운받는 경로도 알려주고 있다. ㅋ
[-] Android toolchain - develop for Android devices
• Android SDK at /Users/obiwan/Library/Android/sdk
✗ Android SDK is missing command line tools; download from https://goo.gl/XxQghQ
• Try re-installing or updating your Android SDK,
visit https://docs.flutter.dev/setup/#android-setup for detailed instructions.
여기까지 설치하였으면 이제는 Android Studio에서 플로터 플러그인을 설치하면 된다.
Android Studio의 preference를 열고 Plugins를 선택하고 검색창에 flutter를 치면 된다. 제일 상단에 있는 11.9M 크기를 선택해서 설치하면 끝이다. 추가로 flutter 관련된 여러가지 플러그인이 있는데, 요건 차차 사용해보면서 좋은것을 정리해서 따로 포스팅 하도록 하겠다.
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
Android 9.0 ( APL Level 28 ) 부터 public API가 아닌 API 사용에 대해서 제한이 생긴다. 그럼 pubic API가 아닌건 어떤 것일까?
Android의 View.java 파일을 보면 아래처럼 @hide로 주석이 달려 있는 코드들이 있다.
/** * Set an observer to collect stats for each frame rendered for this view. * * @hide */ public void addFrameMetricsListener(Window window, Window.OnFrameMetricsAvailableListener listener, Handler handler) { if (mAttachInfo != null) { if (mAttachInfo.mThreadedRenderer != null) { if (mFrameMetricsObservers == null) { mFrameMetricsObservers = new ArrayList<>(); }
FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler.getLooper(), listener); mFrameMetricsObservers.add(fmo); mAttachInfo.mThreadedRenderer.addFrameMetricsObserver(fmo); } else { Log.w(VIEW_LOG_TAG, "View not hardware-accelerated. Unable to observe frame stats"); } } else { if (mFrameMetricsObservers == null) { mFrameMetricsObservers = new ArrayList<>(); }
FrameMetricsObserver fmo = new FrameMetricsObserver(window, handler.getLooper(), listener); mFrameMetricsObservers.add(fmo); } }
이런 함수(또는 필드)들은 public 접근자로 되어 있는데도 사용할 수 가 없다. 바로 이런것들이 non-public function 가 되는 것이고, 이러한 함수와 필드(변수)를 통틀어서 non-SDK Interface 라고 부른다.
이렇게 숨겨진 함수들을 java의 reflection을 통해서 사용하는 방법이 있다. 그런데, 어떤 특정 기능을 구현할때 이런 함수들을 사용하면 상당히 편리한 경우가 있는데, 구글에서는 이런 편법적인 사용을 금지한 것이다. 이유는 public 으로 오픈한 함수가 아니라서 구글에서는 해당 함수이름을 변경하거나 삭제하거나 맘대로 하게 되는데, 특정 App에서 non-SDK Interface를 사용하였다면 문제가 발생하기 때문이다.
그리고 구글에서는 non-SDK Interface에 대해서 아래처럼 3가지로 구분하고 있다.
블랙리스트 : 앱의 target API와 상관없이 사용하면 안되는 리스트
다크그레이 리스트 : target API를 28로 설정하는 경우에 사용에 제한이 되는 리스트
라이트그레이 리스트 : target API를 28로 설정하는 경우에 사용은 가능하지만 잠제적으로 문제가 될 수 있는 리스트
그리고 android 9.0부터는 이러한 non-SDK를 사용했을때 발생하는 문제는 아래와 같다.
액세스 수단
결과
필드를 참조하는 Dalvik 명령어
NoSuchFieldError 발생
메소드를 참조하는 Dalvik 명령어
NoSuchMethodError 발생
Class.getDeclaredField() 또는 Class.getField()를 통한 리플렉션
NoSuchFieldException 발생
Class.getDeclaredMethod(), Class.getMethod()를 통한 리플렉션
NoSuchMethodException 발생
Class.getDeclaredFields(), Class.getFields()를 통한 리플렉션
결과에 비 SDK 구성원 없음
Class.getDeclaredMethods(), Class.getMethods()를 통한 리플렉션
결과에 비 SDK 구성원 없음
env->GetFieldID()를 통한 JNI
NULL이 반환되고 NoSuchFieldError발생
env->GetMethodID()를 통한 JNI
NULL이 반환되고 NoSuchMethodError 발생
target API를 28로 설정하것이 아니면 일단은 블랙리스트의 사용 여부만 검점하면 되는데, 이건 검사해 주는 도구가 veridex 도구 이다.
또는 StrictMode의 detectNonSdkApiUsage을 사용해도 되는데, 이방법은 실행시간에 오류를 알려 주게 되므로 모든 기능을 다 사용해 봐야 어느 정도 검증을 할 수 있게 된다. 그래서 target API를 28로 올리는 시점에는 veridex로 한번 체크하는것을 권한다.
renderscriptSupportModeEnabled 항목을 true로 하면, buildtool 버전에 따라서 알맞는 버전의 so 파일이 같이 바인딩되어서 apk에 포함되는데, buildtool 버전을 28.0.3 사용하고 있다면 대략 64bit 기준으로 2.2MB 정도되는 so 파일이 포함된다.
설명 : renderscriptSupportModeEnabled- Specifies that the generated bytecode should fall back to a compatible version if the device it is running on does not support the target version.
그런데 신기한점은 내가 renderscript를 사용안하고 있는데, 해당 so 파일이 포함되었다. ㅠㅠ
조금더 찾아 보니, 원인은 glide-transformations 이었다.
해당 현상이 issue로도 등록되어 있는데 ( https://github.com/wasabeef/glide-transformations/issues/133 ) 아직 문제해결은 안되어 있는 상태다. glide-transformations에서 제공하는 BlurTransformation 에서 rs를 사용하는듯 하다. 사용안하는 기능때문에 32bit, 64bit 합쳐서 4MB가 추가된다니 좀 아까워서.. gradle 설정에서 아래를 추가해보고 확인해 봤다.
renderscriptSupportModeEnabled false
그래도 추가된다. 그지같다.
결론 : 사용하고 있는 transform 코드만 가져다 붙이고 glide-transforamtions 의존성을 제거하는 방법 밖에 없다.. ㅠㅠ