Development record of developer who study hard everyday.

레이블이 안드로이드에러인 게시물을 표시합니다. 모든 게시물 표시
레이블이 안드로이드에러인 게시물을 표시합니다. 모든 게시물 표시
, , ,

[Solved] ViewPager.setAdapter throws IllegalArgumentException in Android

 ViewPager.setAdapter throws IllegalArgumentException in Android

안드로이드 개발 블로그

java.lang.IllegalArgumentException

at androidx.core.util.Preconditions.checkArgument(Preconditions.java:38)

at androidx.viewpager2.adapter.FragmentStateAdapter.onAttachedToRecyclerView(FragmentStateAdapter.java:132)

at androidx.recyclerview.widget.RecyclerView.setAdapterInternal(RecyclerView.java:1243)

at androidx.recyclerview.widget.RecyclerView.setAdapter(RecyclerView.java:1194)

at androidx.viewpager2.widget.ViewPager2.setAdapter(ViewPager2.java:461)

at net.twobeone.pink.fragments.MainFragment.activityInit(MainFragment.kt:58)

at net.twobeone.pink.fragments.MainFragment.onViewCreated(MainFragment.kt:49)

at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3128)

at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:552)

at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)

at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1890)

at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1823)

at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1760)

at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:547)

at android.os.Handler.handleCallback(Handler.java:938)

at android.os.Handler.dispatchMessage(Handler.java:99)

at android.os.Looper.loop(Looper.java:246)

at android.app.ActivityThread.main(ActivityThread.java:8653)

at java.lang.reflect.Method.invoke(Native Method)

at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)

at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)


Solution : 

Initialize ViewPagerAdapter in onCreateView.


Wrong Example:

class MainFragment : BaseFragment<FragmentMainBinding>() {

private val viewPagerAdapter : ViewPagerAdapter by lazy { ExampleViewPagerAdapter(this) }
}




vallayoutResID 재정의: Int get() = R.layout.fragment_main
Share:
Read More
, ,

Execution failed for task ':app:configureNdkBuildDebug[arm64-v8a]'.

Execution failed for task ':app:configureNdkBuildDebug[arm64-v8a]'해결방법

개발블로그

OpenCV에 정의되어있는 c++ 함수들을 사용하기 위해서 ndk 빌드를 하고있는데 아래와 같은 에러가 발생했다.

Execution failed for task ':app:configureNdkBuildDebug[arm64-v8a]'.


이 문제로 하루정도 골머리를 앓았는데 해결방법은 매우 간단했다;; ㅜㅜ

역시 개발은 삽질의 연속이다.

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

#opencv library
OPENCVROOT:=/Users/boo/StudioProjects/My-SampleProject/OpenCV-android-sdk
OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=on
OPENCV_LIB_TYPE:=SHARED
include ${OPENCVROOT}/sdk/native/jni/OpenCV.mk

LOCAL_MODULE:=native-lib
LOCAL_SRC_FILES:=main.cpp
LOCAL_LDLIBS:=-llog
LOCAL_LDFLAGS+=-ljnigraphics

include $(BUILD_SHARED_LIBRARY)
위의 코드는 ndk빌드를 할 때, 사용하는 Android.mk 파일이다.

mac에서는 파일경로 구분자는 '/' 이다.

하지만 윈도우에서 사용하던 프로젝트를 맥으로 가져오다보니 파일경로 구분자가 '\' 로 되어있었다;;

위 코드에서 OPENCVROOT와 OpenCV.mk 의 파일경로를 / 로 바꿔주니 빌드가 되었다.

Share:
Read More
, ,

Unable to create call adapter for retrofit2.Response 에러 해결방법

Unable to create call adapter for retrofit2.Response


안드로이드 개발 블로그

회사에서 오랜만에 신규프로젝트에 투입되었다.

오랜만에 api 호출을 위한 Retrofit 세팅을 하다가 아래와 같은 에러로그가 발생했다.

Unable to create call adapter for retrofit2.Response

해결방법은 간단했다.

api 호출하는 함수에 suspend를 붙이지 않아서였다;;

interface ApiService {
@FormUrlEncoded
@POST("/api/login/hospital")
/*여기 suspend 안 붙였었음;;*/suspend fun loginHospital(
@Field("hospitalId") hospitalId: String
) : Response<LoginHospitalResponse>


}

 




Share:
Read More
,

Android 10(target SDK 29) does not meet the requirements to access device identifiers 오류 해결 방법

 Android 10(target SDK 29) does not meet the requirements to access device identifiers

개발 블로그

회사에서 오래된 프로젝트 sdk업데이트를 진행했다.

22년 11월부터 targetSdkVersion이 29이하인 앱들은 플레이스토어에서 앱이 내려간다.

이 정책때문에 도대체 sdk업데이트를 몇 개의 프로젝트를 진행했는지 셀 수가 없다;;


그렇게 targetSdkVersion을 올리면서 해당 오류를 발견하였다.

Android 10(target SDK 29) does not meet the requirements to access device identifiers

android OS 10부터 TelephonyManager 클래스를 통해 제공되는 고유ID를 사용할 수 없게되었다.

기존의 프로젝트의 코드는 아래와 같았다.

 /**
     * UUID를 가져온다
     * @param mContext
     * @return
     */
    public static String getDevicesUUID(Context mContext){
        String tmDevice = null, tmSerial = null, androidId;
        UUID deviceUuid;

        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            deviceUuid = UUID.randomUUID(); // UUID 대체코드
        } else {
            // 기존 UUID 로직
            TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
            tmDevice = "" + tm.getDeviceId();
            tmSerial = "" + tm.getSimSerialNumber();
            
            androidId = "" + android.provider.Settings.Secure.getString(mContext.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
            deviceUuid = new UUID(androidId.hashCode(), ((long)tmDevice.hashCode() << 32) | tmSerial.hashCode());
        }

        String deviceId = deviceUuid.toString();

        return deviceId;
    }

이 부분을 아래와 같이 바꾸어주면된다.

/**
     * UUID를 가져온다
     * @param mContext
     * @return
     */
    public static String getDevicesUUID(Context mContext) {
        String tmDevice = null, tmSerial = null, androidId;
        UUID deviceUuid;
        String deviceId = null;

        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // Q(29)이상일 때 UUID가져오는 방식
            deviceUuid = new UUID(-0x121074568629b532L, -0x5c37d8232ae2de13L);
            try {
                // DRM - WIDEVINE_UUID(앱 삭제 or 데이터 삭제해도 변경x)
                MediaDrm mediaDrm = new MediaDrm(deviceUuid);
                deviceId = android.util.Base64.encodeToString(mediaDrm.getPropertyByteArray(MediaDrm.PROPERTY_DEVICE_UNIQUE_ID), 0).trim();

            } catch (UnsupportedSchemeException e) {
                e.printStackTrace();
            }
        } else { // 기존 UUID 조합해서 사용하는 방식
            if (ContextCompat.checkSelfPermission(EBookCaseApplication.Instance().getApplicationContext(), Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
                TelephonyManager tm = (TelephonyManager) EBookCaseApplication.Instance().getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
                tmDevice = "" + tm.getDeviceId();
                tmSerial = "" + tm.getSimSerialNumber();
                androidId = "" + Settings.Secure.getString(EBookCaseApplication.Instance().getApplicationContext().getContentResolver(), Settings.Secure.ANDROID_ID);

                deviceUuid = new UUID(androidId.hashCode(), ((long)tmDevice.hashCode() << 32) | tmSerial.hashCode());
                deviceId = deviceUuid.toString();
            }
        }

        return deviceId;
    }

기존의 tmDevice와 tmSerial을 WedevineID로 대체한다.

앱을 삭제하고 재설치하여도 변하지않는 고유 ID값이다.








Share:
Read More
, ,

Duplicate class androidx.lifecycle.ViewModelLazy found in modules jetified-lifecycle-viewmodel-ktx-2.3.1-runtime 에러 해결 방법

 Duplicate class androidx.lifecycle.ViewModelLazy found in modules jetified-lifecycle-viewmodel-ktx-2.3.1-runtime 에러 해결 방법

안드로이드 블로그

지금 회사에서 안드로이드 소스 그래들 버전을 올리고 라이브러리 버전을 올리면서 아래 에러가 발생했다.

안드로이드 에러 로그

Execution failed for task ':app:checkDebugDuplicateClasses'.

> A failure occurred while executing com.android.build.gradle.internal.tasks.CheckDuplicatesRunnable

   > Duplicate class androidx.lifecycle.ViewModelLazy found in modules jetified-lifecycle-viewmodel-ktx-2.3.1-runtime (androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1) and lifecycle-viewmodel-2.5.1-runtime (androidx.lifecycle:lifecycle-viewmodel:2.5.1)

     Duplicate class androidx.lifecycle.ViewTreeViewModelKt found in modules jetified-lifecycle-viewmodel-ktx-2.3.1-runtime (androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1) and lifecycle-viewmodel-2.5.1-runtime (androidx.lifecycle:lifecycle-viewmodel:2.5.1)


검색해보니까
def lifecycle_version = "2.5.1"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"

위 두 라이브러리의 버전을 2.5.1로 하면 된다고한다. ㅋㅋ




















Share:
Read More
, , ,

'@JvmDefault' members is only allowed with -Xjvm-default option 해결방법

 '@JvmDefault' members is only allowed with -Xjvm-default option 해결방법

안드로이드 블로그

Gradle 버전을 올리다가 에러가 발생했다.

나같은 경우에는 빌드는 되지만 소스코드에 빨간줄 뜨는게 너무 맘에 안들었다.

그래서 이리저리 구글링을 해보고 해결방법을 찾았다.

android {

compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}

kotlinOptions {
freeCompilerArgs = ['-Xjvm-default=enable']
jvmTarget = '11'
}

}

build.gradle에 kotlinOptions를 위와 같이 작성해주면 된다. ㅎ

나 같은 경우에는 모듈코드에서 에러가 발생한거라 build.gradle 모듈레벨에서도 위와 같이 kotlinOptions를 작성해주니까 코드에 빨간줄이 사라지면서 정상적으로 빌드가 되었다.

Share:
Read More
, ,

안드로이드 Unsupported metadata version. Check that your Kotlin version is >= 1.0 에러 해결 방법

Unsupported metadata version. Check that your Kotlin version is >= 1.0 해결방법

안드로이드 블로그

현재 SI업체에서 일하면서 제일 짜증나는게 과거 오래된 프로젝트를 유지보수하는 일이다.

예전 라이브러리가 많이 쓰여있고 코드도 옛날 스타일인데다가 그래들이나 코틀린 버전도 예전버전이다.

유지보수를 위해서 그래들을 올리고 targetSDK 버전을 올리면 온갖 에러가 발생한다....

그래들 버전을 올리면서 

Unsupported metadata version. Check that your Kotlin version is >= 1.0


에러가 발생했다.

코틀린 버전이 1.0 이상인지 확인해보라는데 나의 코틀린 버전은 1.6.10이다.

뚜껑이 열리는걸 참고 차분히 구글링을 해본다.

하지만 나오는 글들은 전부 hilt의 버전을 올리라는 이야기 뿐이다.

예를들어, 아래와 같은 자료를 찾았다.

Unsupported metadata version. Check that your Kotlin version is >= 1.0

하지만 내가 유지보수하는 프로젝트 소스에는 hilt가 쓰이지 않는다.

그러다가 "혹시 hilt 이전의 종속성주입을 사용하는 Dagger2 라이브러리의 버전이 관련되어있지 않을까?" 하는 생각이 떠올랐다.

그래서 위 자료처럼 코틀린 버전을 1.7.0으로 올리고 Dagger2 버전을 가장 최신버전인 2.45로 올렸다.

그랬더니 에러 로그가 달라졌다. ㅋㅋ

viewmodelprovider 'create' overrides nothing

위와 같은 에러가 발생했다.

override fun <T : ViewModel?> create(modelClass: Class<T>): T {
val creator = creators[modelClass]
//....


return try {
creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
DaggerViewModelFactory를 정의하는 곳에서 create 메소드의 제네릭 타입이 잘 못되어서 그렇다.

<T : ViewModel?> 타입을 <T : ViewModel>로 바꿔주면된다.

이제 빌드에 성공했다.

참 힘들었다....

빨리 실력을 쌓아서 이 SI업체를 빠져나가야겠다!!


Share:
Read More
, , ,

Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent 해결방법 총정리

Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent 해결방법 총정리

안드로이드 블로그

Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent 해결방법을 소개한다.


SI업체에서 일하는 안드로이드 개발자로서 무수히 많은 프로젝트들의 SDK 업데이트 작업을 하다보면 수없이 보는 에러로그다.


찬찬히 해석해보면 해결방법은 너무나 간단하지만 경우에 따라 다른 해결방법이 존재하기때문에 이 글에 총 정리를 해본다.


1. PendingIntent의 Flag 수정

에러로그를 해석해보면 targetSDK 버전이 31 이상일 때는 PendingIntent의 Flag를 FLAG_IMMUTABLE 또는 FLAG_MUTABLE을 사용해야한다는 뜻이다.

PendingIntent pending;
Intent intent = new Intent(this, MainActivity.class);
pending = PendingIntent.getActivity(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);

👇위와 같은 코드를 아래처럼 바꿔주면 된다.👇

PendingIntent pending;
Intent intent = new Intent(this, MainActivity.class);

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
pending = PendingIntent.getActivity(this, 1, intent, PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
} else {
pending = PendingIntent.getActivity(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}

앱이 실행되고있는 기기의 SDK 버전이 S(31)이상이면 PendingIntent의 flag를FLAG_IMMUTABLE 또는 FLAG_MUTABLE로 바꿔주면된다.

나같은 경우에는 Push 메시지 수신시 내요을 바꿔주기위해 FLAG_MUTABLE과 FLAG_UPDATE_CURRENT를 or 연산해주었다.


2. dependency 추가

현재 프로젝트 소스를 자바로하느냐 코틀린으로 하는지에 따라서 아래 dependency를 선택해서 추가해준다.

implementation "androidx.work:work-runtime:2.7.1" // java
implementation "androidx.work:work-runtime-ktx:2.7.1" // kotlin


3. Firebase-Messaging 라이브러리 버전 올리기

1번과 2번 같은 경우에는 다른 개발 블로그에도 왕왕 많이 나오는데 이번에 소개할 내용은 찾을 수가 없어서 삽질을 좀 했다;; (1시간 정도?)

처음에는 firebase-messaging 라이브러리 버전이 11점대를 쓰고 있었는데 이것을 23.1.1로 바꿔주니까 에러가 사라졌다!!

근데 좀 짜증나는게 이럴 경우에 파이어베이스 푸시 메시지와 관련해서 토큰값을 받는 코드를 수정해야한다.

아마 원래 아래와 같은 코드가 존재했을 것이다.

public class FcmService extends FirebaseInstanceIdService {    //이 클래스와 관련된 코드는 싹 다 지워버리자

@Override
public void onCreate() {
super.onCreate();
updateToken(FirebaseInstanceId.getInstance().getToken());
}

@Override
public void onTokenRefresh() {
super.onTokenRefresh();
updateToken(FirebaseInstanceId.getInstance().getToken());
}

private void updateToken(String token) {
if (isEmpty(token)) {
Log.d("FcmService", "token is not exist.");
return;
}
Log.d("FcmService", "token is refreshed : " + token);
PreferencesRepositoryImpl repository = PreferencesRepositoryImpl.getInstance();
repository.setToken(token);
}

}

FirebaseInstanceIdService 클래스가 deprecated 되었기 때문에 Firebase token 값을 받는 부분을 FirebaseMessagingService에서 onNewToken() 메서드를 override해서 처리한다,.

아래 코드를 참고하길 바란다.

@Override
public void onNewToken(@NonNull String token) {
super.onNewToken(token);
updateToken(token);
}

private void updateToken(String token) {
if (isEmpty(token)) {
Log.d("FcmService", "token is not exist.");
return;
}
Log.d("FcmService", "token is refreshed : " + token);
PreferencesRepositoryImpl repository = PreferencesRepositoryImpl.getInstance();
repository.setToken(token);
}


Share:
Read More

Can only use lower 16 bits for requestCode 에러 해결방법

 Can only use lower 16 bits for requestCode 에러 해결방법

안드로이드 블로그

구글로그인을 구현하는데 Can only use lower 16 bits for requestCode 에러가 떴다;;

너무 당황해서 구글링을 해봤는데 쉽게 해결가능했다.



☝ 위 링크가 도움이 됐다.

앱수준의 build.gradle에 
implementation "androidx.activity:activity-ktx:1.5.0"
implementation 'androidx.fragment:fragment:1.5.0'
를 추가해서 해결하였다.

Share:
Read More
, , ,

android:exported needs to be explicitly specified for 빌드에러 해결방법

android:exported needs to be explicitly specified for <activity> 빌드에러 해결방법

안드로이드 개발 블로그

안드로이드 프로젝트 그래들 업데이트를 하다가 아래와 같은 에러를 만났다.

> Manifest merger failed with multiple errors, see logs

android:exported needs to be explicitly specified for <activity>. Apps targeting Android 12 and higher are required to specify an explicit value for `android:exported` when the corresponding component has an intent filter defined. See https://developer.android.com/guide/topics/manifest/activity-element#exported for details.

해석하면 안드로이드 12를 타겟하는 순간부터 manifest.xml 파일에 activity 태그에 exported 속성을 정의해주어야한다.

(단, activity가 intent-filter 태그를 품고있는 경우에만 해당된다.)

하지만, 난 아무리 activity 태그에 다 exported 속성을 정의해주어도 같은 에러가 발생한다.

아직도 명확한 이유를 모르겠지만, 베이스 코드(모듈)의 naver login을 위한 activity에 exported가 명시되지 않아서 그렇더라;;

쨌든 해결방법은!!

manifest 파일에서 


<activity android:name="com.nhn.android.naverlogin.ui.OAuthCustomTabActivity"
android:exported="false"/>

위 코드를 <application>태그 안에 추가해주면된다.


Share:
Read More
,

java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/common/R$string 빌드 에러 해결방법

java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/common/R$string 빌드 에러 해결방법


안드로이드 개발 블로그


회사에서 옛날 프로젝트의 그래들을 업그레이드하다가 에러가 났다.

에러내용은 아래와 같다.

java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/common/R$string

아래처럼 objectboxVersion을 2.5.1로 변경해주면 해결된다.
buildscript {
ext.kotlin_version = '1.6.10'
ext.objectboxVersion = '2.5.1'    //objectbox 버전
repositories {
// maven { url "http://1.201.142.80:8014/artifactory/list/ark/" }
google()
jcenter()
// maven { url "https://nexus.uzuki.live/repository/ark/" }
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "io.objectbox:objectbox-gradle-plugin:$objectboxVersion"

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath 'com.google.gms:google-services:4.3.8'
}
}


Share:
Read More
, ,

안드로이드 unsupported or unrecognized ssl message 빌드 에러 해결방법

 unsupported or unrecognized ssl message 빌드 에러 해결방법

안드로이드 개발 블로그

회사에서 옛날 프로젝트의 그래들과 sdk를 업데이트하다가 

unsupported or unrecognized ssl message

에러를 맞이했다.

문제는 Maven 스토리지 url이 잘못되어서 그렇다.


우리 회사는 에이전시회사라서 앱을 최대한 빨리 찍어내야한다.

그래서 자주쓰이는 기능들을 abstract 클래스와 라이브러리로 세팅을 해놓는다.

그 중에 sns로그인을 위해서 카카오 maven 저장소 url을 추가해놓았다.

근데 이게 예전 프로젝트라서 http url로 적혀있었다.

http://devrepo.kakao.com:8088/nexus/content/groups/public/

👇

https://devrepo.kakao.com/nexus/content/groups/public/

위에서 아래로 바꿔주면 된다.


그리고 unsupported or unrecognized ssl message 에러가 발생하기 이전에 maven 저장소의 url을 http에서 https로 변경하라는 에러가 뜰 것이다.

그때 기존 http://devrepo.kakao.com:8088/nexus/content/groups/public/에서 https로만 바꿔주면 안된다.

https://devrepo.kakao.com/nexus/content/groups/public/로 완전히 바꿔주면 unsupported or unrecognized ssl message 에러는 뜰 일이 없다.



Share:
Read More
, , ,

안드로이드 WorkManager 사용하기 (자바 JAVA)

 안드로이드 WorkManager 사용법 소개


회사 프로젝트를 진행하던 중 매우 난감한 상황에 봉착했다.

깃에서 가장 최신 소스를 clone 받아보니 targetSDK가 29였다.

마켓에 올리려면 targetSDK가 30은 되야하는데 어짜피 내년에도 내가 이 프로젝트를 건드려야하니까 32까지 올려보려고 했다. (매년 조금씩 수정할 것이 있는 프로젝트임)

tartgetSDK는 32까지 겨우겨우 올렸는데 여기에 쓰인 라이브러리 중에 android.evernote.job 이란 라이브러리가 있었다.

근데 이 라이브러리가 targetSDK 31부터는 deprecated 되었으니 workManager랑 alarmManager를 사용하라는 것이다!!

하.... 일이 늘어나버렸다.

내년에도 어짜피 내가 해야할 프로젝트라서 그냥 이번에 큰 맘 먹고 대폭 수정하기로 했다.

겸사겸사 전에 잠깐 공부해뒀던 WorkManager도 활용해보기로하고 말이다.

그럼 WorkManager 사용법에 대해 알아보자!

참, 기존의 프로젝트가 자바로 된 녀석이여서 자바 기준으로 설명하겠다;;

1. WorkManager dependency 추가

def work_version = "2.7.1"
implementation "androidx.work:work-runtime:$work_version"

앱수준 build.gradle에 위와 같이 workManager 라이브러리를 추가해준다.

되도록 2.7.0 이상의 버전을 추가하길 바란다.

너무 낮은 버전을 추가하면 

Targeting S+ (version 31 and above) requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent. Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if some functionality depends on the PendingIntent being mutable, e.g. if it needs to be used with inline replies or bubbles.

위와 같은 에러가 발생하는 경우가 있다.

2.  Worker 객체 만들기

public class DetectionWork extends Worker {    //1
public static final String TAG = DetectionWork.class.getSimpleName();
private static final int NOTIFICATION_ID = 1111;

public DetectionWork(
@NonNull Context context,
@NonNull WorkerParameters params) {
super(context, params);
}

@NonNull
@Override
public Result doWork() {    //2
Log.d(TAG, "DetectionWork doWork()");    //3
NotificationTool.show(getApplicationContext(), "이번 달 유방암 자가검진일인 핑크터치 데이입니다",    //3
null, "유방암 자가검진 시작", new HashMap<>(), NOTIFICATION_ID);    //3

return Result.success();    //4
}
}

1-> Worker 객체를 상속한다.

2-> doWork() 메소드를 override 해준다.

3-> workManager로 동작할 코드를 적어준다.

4-> 성공을 return 해준다.

3-> WorkRequest 객체 만들기

WorkRequest DetectionWorkRequest = new OneTimeWorkRequest.Builder(DetectionWork.class)    //1
.addTag(DetectionWork.
TAG)    //2
.setInitialDelay(getAlarmTime()
, TimeUnit.MILLISECONDS)    //3
.build();

WorkManager.getInstance(mApplication.getApplicationContext()).enqueue(DetectionWorkRequest);    //4

1-> 한 번만 실행할 거라서 OneTimeWorkRequest 객체를 만든다.

2-> 나중에 취소할 경우를 생각해서 Tag를 만들어준다.

3-> 특정 시간 뒤에 동작하기위해 setInitialDelay 메소드 사용

4-> WorManager 객체에 enqueue를 하면 Worker 객체가 실행된다!


내가 작성한 코드가 WorkManager의 가장 기본적인 형태라고 보면된다.

이외에도 다양한 기능들이 있는데 공식홈페이지를 참고하길 바란다.


✋여기서 잠깐!

내가 WorkManager를 사용하면서 매우 당황한 에러로그가 있었다.

WorkManager is not initialized properly.  You have explicitly disabled WorkManagerInitializer in your manifest, have not manually called WorkManager#initialize at this point, and your Application does not implement Configuration.Provider.

위와 같은 로그였는데, 아직도 왜 발생했는지 정확한 이유는 모르겠다..

아무리 문서를 찾아보고 스택오버플로우를 뒤져봐도 아직 모르겠다...

다만, addTag 기능을 사용하면서 기본 WorkManager의 초기화가 아니라 커스텀 초기화가 필요했던 것 같다.

아무튼, 위와 같은 로그가 발생했을 때 해결 방방법은 다음과 같다.

1. 워크매니저의 기본 초기화 제거

<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<!-- If you are using androidx.startup to initialize other components -->
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>

manifest.xml 파일에 <application> 태그 안에 위 코드를 넣어준다.

코드의 내용은 간단히 설명하면 WorkManager의 기본 초기화를 제거한다는 뜻이다.

2. 워크매니저의 커스텀 초기화

기본 초기화를 제거했으니 WorkManager를 커스텀 초기화를 해주어야한다.

public class MainApplication extends BaseApplication implements Configuration.Provider {

@Override
public void onCreate() {
super.onCreate();

addRegisterCallback();

ViewPump.init(ViewPump.builder()
.addInterceptor(new CalligraphyInterceptor(
new CalligraphyConfig.Builder()
.setDefaultFontPath("fonts/youth.ttf")
.build()))
.build());
}

@NonNull
@Override
public Configuration getWorkManagerConfiguration() {
return new Configuration.Builder()
.setMinimumLoggingLevel(Log.INFO)
.build();
}
}

Application을 상속하는 클래스(여기서는 MainApplication)에 가서 Configuration.Provider를 implements 해준다.

그리고 getWorkManagerConfiguration 메소드를 override해준다.

이렇게하면 WorkManager를 커스텀 초기화를 하게된다.

그리고 에러로그는 사라진다!




Share:
Read More
, , , ,

A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptWithoutKotlincTask$KaptExecutionWorkAction 에러 해결

 


옛날 프로젝트를 수정하면서 A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptWithoutKotlincTask$KaptExecutionWorkAction 에러가 발생하였다.


// Dependency Inject - Dagger2
def dagger_version = "2.35.1"
implementation "com.google.dagger:dagger:$dagger_version"
implementation "com.google.dagger:dagger-android:$dagger_version"
implementation "com.google.dagger:dagger-android-support:$dagger_version"
kapt "com.google.dagger:dagger-compiler:$dagger_version"

Dagger2 버전을 2.35.1로 만들어주니까 해결!


Share:
Read More
, , , ,

Required DataBindingComponent is null in class ItemContainerTvShowBindingImpl 해결방법



 java.lang.IllegalStateException: Required DataBindingComponent is null in class ItemContainerTvShowBindingImpl. A BindingAdapter in com.codinginflow.mvvmtvshow.utilities.BindingAdapters is not static and requires an object to use, retrieved from the DataBindingComponent. If you don't use an inflation method taking a DataBindingComponent, use DataBindingUtil.setDefaultComponent or make all BindingAdapter methods static.

class BindingAdapters {

@BindingAdapter("android:imageURL")
fun setImageURL(imageView: ImageView, URL: String){
try {
imageView.alpha = 0f
Picasso.get().load(URL).noFade().into(imageView, object : Callback {
override fun onSuccess() {
imageView.animate().setDuration(300).alpha(1f).start()
}

override fun onError(e: java.lang.Exception?) {

}
})
} catch(ignored: Exception) {

}
}
}
@BindingAdapter를 클래스 안에 넣어서 문제가 발생했다.
클래스 밖에 꺼내주면 해결된다;;









Share:
Read More
, ,

Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.6.0, expected version is 1.1.16 에러 해결



안드로이드 앱을 빌드하다가

Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.6.0, expected version is 1.1.16 

에러가 발생했다.

코틀린 버전을 1.4.32로 변경하니까 해결되었다.

빌드시 사용하는 코틀린 버전을 좀 올려보길 바란다.

Share:
Read More
, , , ,

cvc-complex-type.2.4.a: Invalid content was found starting with element 'base-extension'. One of '{layoutlib}' is expected 에러 해결 방법

 cvc-complex-type.2.4.a: Invalid content was found starting with element 'base-extension'. One of '{layoutlib}' is expected 해결방법


회사에서 가끔 옛날 프로젝트 소스를 전달해주면서 약간의 수정을 해달라고 요구할 때가 있다.

그래서 소스를 받아서 압축을 풀고 실행해보면 

안드로이드 빌드 에러

이런 에러가 발생한다.

구글링해보면 정확히는

cvc-complex-type.2.4.a: Invalid content was found starting with element 'base-extension'. One of '{layoutlib}' is expected

인가보다.

해결방법은 간단하다.

그래들 버전을 올려보면 된다!





Share:
Read More
, ,

View must have a tag 에러 해결방법

 View must have a tag 에러 해결방법


안드로이드 개발 블로그

view Must have a TAG

태블릿 최적화 앱을 만들다가 위 화면과 같은 에러를 만나게 되었다.

    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.appg.joowon/com.appg.joowon.main.IntroActivity}: java.lang.RuntimeException: view must have a tag

나 같은 경우에는 태블릿 전용 앱을 만들고 있어서 layout이 일반 핸드폰용 하나 그리고 태블릿용 하나.

이렇게 2개가 있는데 태블릿용(sw600dp) 레이아웃에만 데이터 바인딩을 적용해서 생기는 문제였다.

일반 핸드폰용 레이아웃에도 데이터바인딩을 적용하면 에러는 사라진다!



Share:
Read More
, ,

Can't access ViewModels from detached fragment 해결방법




안드로이드 에러

    java.lang.IllegalStateException: Can't access ViewModels from detached fragment

        회사 프로젝트에 MVVM 적용하다가 위와 같은 에러가 발생했다.

원인은 onCreateView 로 프래그먼트가 attached 되기 전에 뷰모델에 접근했기 때문이다.

해결방법은 Fragment 생명주기 상 onCreateView 뒤에 있는 onViewCreated에서 뷰모델을 접근하였다.

Share:
Read More
,

unable to load class 'javax.xml.bind.JAXBException'. 에러 해결방법

안드로이드 개발블로그

회사에서 옛날 프로젝트의 그래들과 sdk 버전을 업그레이드 해야했다.

근데 2018년도에 만든 프로젝트라서 이것저것 바꿔줘야할게 한 두가지가 아니다.

unable to load class 'javax.xml.bind.JAXBException'.

기본적으로 에러 로그는 위와 같다.

찾아보니 방법은 2가지가 있었다.


1. JDK를 1.8로 설정한다


2. 그래들 버전을 업그레이드 한다.


현재 안드로이드 스튜디오 chipmunk를 사용하고있어서 JDK를 11로 써야만 했다.

따라서 그래들을 업그레이드하면서 해결을 했다.














Share:
Read More