App Center 배포 – Android 앱 내 업데이트

중요

Visual Studio App Center는 2025년 3월 31일에 사용 중지될 예정입니다. Visual Studio App Center가 완전히 사용 중지될 때까지 계속 사용할 수 있지만 마이그레이션을 고려할 수 있는 몇 가지 권장 대안이 있습니다.

지원 타임라인 및 대안에 대해 자세히 알아보세요.

App Center 배포를 사용하면 App Center를 통해 배포할 때 사용자가 새 버전의 앱을 설치할 수 있습니다. 새 버전의 앱을 사용할 수 있는 경우 SDK는 사용자에게 업데이트 대화 상자를 표시하여 새 버전을 다운로드하거나 연기합니다. 업데이트하도록 선택하면 SDK가 애플리케이션을 업데이트하기 시작합니다.

경고

Google Play는 앱 내 업데이트 코드가 런타임에 사용되지 않더라도 악의적인 동작으로 간주합니다. 이 섹션의 지시에 따라 SDK 배포의 변형을 사용하거나 Google Play에 앱을 제출하기 전에 앱 내 업데이트 코드가 포함된 SDK 배포를 완전히 제거합니다. 이렇게 하지 않으면 Google Play에서 앱이 비준수 및 제거됩니다.

참고

자동화된 UI 테스트를 실행하는 경우 앱 내 업데이트를 사용하도록 설정하면 App Center 백 엔드에 대해 인증을 시도하므로 자동화된 UI 테스트가 차단됩니다. UI 테스트에 App Center 배포를 사용하도록 설정하지 않는 것이 좋습니다.

앱에 앱 내 업데이트 추가

아직 애플리케이션에서 SDK를 설정하고 시작하지 않은 경우 시작 섹션을 따릅니다.

1. App Center 배포 모듈 추가

App Center SDK는 모듈식 접근 방식으로 설계되었습니다. 개발자는 관심 있는 서비스의 모듈만 통합하면 됩니다.

  1. 프로젝트의 앱 수준 build.gradle 파일(app/build.gradle)을 열고 다음에 apply plugin다음 줄을 추가합니다.

    dependencies {
       def appCenterSdkVersion = '5.0.4'
       implementation "com.microsoft.appcenter:appcenter-distribute:${appCenterSdkVersion}"
    }
    

    참고

    Android Gradle 플러그 인 버전이 3.0.0보다 낮은 경우 구현컴파일로 바꿔야 합니다.

  2. build.gradle 파일을 저장하고 Android Studio에서 Gradle 동기화를 트리거해야 합니다.

  3. DownloadManager 는 업데이트를 다운로드하는 데 사용됩니다. App Center SDK는 보안을 개선하기 위해 TLS 1.2를 적용합니다.

2. App Center 배포 시작

App Center를 사용하려면 사용하려는 모듈을 옵트인합니다. 기본적으로 모듈은 시작되지 않으며 SDK를 시작할 때 각 모듈을 명시적으로 호출해야 합니다.

메서드에 배포 클래스를 추가하여 App Center 배포 서비스를 시작합니다 AppCenter.start() .

AppCenter.start(getApplication(), "{Your App Secret}", Distribute.class);
AppCenter.start(application, "{Your App Secret}", Distribute::class.java)

위의 코드 샘플에서 를 앱 비밀로 대체 {Your App Secret} 했는지 확인합니다. 메서드에 클래스 start() 에 대한 참조 Distribute 를 추가하면 Android Studio에서 필요한 import 문을 자동으로 제안하지만 클래스 이름이 인식되지 않는다는 오류가 표시되면 작업 클래스의 import 문에 다음 줄을 추가합니다.

import com.microsoft.appcenter.AppCenter;
import com.microsoft.appcenter.distribute.Distribute;
import com.microsoft.appcenter.AppCenter
import com.microsoft.appcenter.distribute.Distribute

참고

Android 10 이상에는 백그라운드에서의 시작 활동에 대한 제한이 있습니다. 백그라운드에서 활동 시작에 대한 제한 사항에 대한 문서를 참조하세요.

참고

Android 10(Go 버전)에서 실행되는 앱은 SYSTEM_ALERT_WINDOW 권한을 받을 수 없습니다. Go 디바이스의 SYSTEM_ALERT_WINDOW 대한 문서를 참조하세요.

참고

Android 11 ACTION_MANAGE_OVERLAY_PERMISSION 부터 의도는 항상 사용자가 앱에 대한 권한을 부여하거나 취소 SYSTEM_ALERT_WINDOW 할 수 있는 최상위 설정 화면으로 사용자를 가져옵니다. Android 11의 권한 업데이트에 대한 문서를 참조하세요.

Google Play 빌드 준비

Google Play는 앱 내 업데이트 코드가 런타임에 사용되지 않더라도 악의적인 동작으로 간주합니다. 이 섹션의 지시에 따라 SDK 배포의 변형을 사용하거나 Google Play에 앱을 제출하기 전에 앱 내 업데이트 코드가 포함된 SDK 배포를 완전히 제거합니다. 이렇게 하지 않으면 Google Play에서 앱이 비준수 및 제거됩니다. 더 쉽게 하기 위해 스텁된 API를 사용하여 App Center 배포 SDK 버전을 제공하므로 종속성 교환만 변경됩니다.

  1. 프로젝트의 앱 수준 build.gradle 파일(app/build.gradle)을 엽니다.

  2. 제품 버전을 추가하여 빌드 변형을 구성합니다.

    android {
        flavorDimensions "distribute"
        productFlavors {
            appCenter {
                dimension "distribute"
            }
            googlePlay {
                dimension "distribute"
            }
        }
    }
    
  3. 종속성 블록을 수정하여 제품 버전에 따라 다른 종속성을 사용합니다.

    dependencies {
        def appCenterSdkVersion = "5.0.4"
        appCenterImplementation "com.microsoft.appcenter:appcenter-distribute:${appCenterSdkVersion}"
        googlePlayImplementation "com.microsoft.appcenter:appcenter-distribute-play:${appCenterSdkVersion}"
    }
    
  4. build.gradle 파일을 저장하고 Android Studio에서 Gradle 동기화를 트리거해야 합니다.

  5. 빌드 > 변형 선택 빌드 변형 드롭다운 메뉴 또는 도구 창 표시줄에서 변형 빌드에서 빌드 변형을 변경할 수 있습니다.

빌드 변형 구성에 대한 자세한 내용은 Android 설명서에서 확인할 수 있습니다.

프라이빗 메일 그룹 사용

기본적으로 배포는 공용 메일 그룹을 사용합니다. 프라이빗 메일 그룹을 사용하려면 API를 통해 setUpdateTrack 명시적으로 설정해야 합니다.

Distribute.setUpdateTrack(UpdateTrack.PRIVATE);
Distribute.setUpdateTrack(UpdateTrack.PRIVATE)

참고

기본값은 UpdateTrack.PUBLIC입니다. 이 메서드는 메서드 호출 전에 AppCenter.start 만 호출할 수 있습니다. 업데이트 트랙에 대한 변경 내용은 애플리케이션 프로세스가 다시 시작될 때 유지되지 않으므로 메서드가 호출 전에 AppCenter.start 항상 호출되지 않는 경우 기본적으로 공개됩니다.

앱이 포그라운드(및 AppCenter.start이후Distribute.setUpdateTrack(UpdateTrack.PRIVATE);)에 있으면 브라우저 창이 열리고 사용자를 인증합니다. 모든 후속 업데이트 검사는 프라이빗 트랙에서 최신 릴리스를 가져옵니다.

사용자가 프라이빗 트랙에 있는 경우 인증이 성공하면 멤버인 프라이빗 메일 그룹에서 최신 릴리스를 받게 됩니다. 사용자가 공개 트랙에 있는 경우 모든 퍼블릭 배포 그룹에서 최신 릴리스를 받게 됩니다.

자동 업데이트 확인 사용 안 함

기본적으로 SDK는 새 릴리스를 자동으로 확인합니다.

  • 애플리케이션이 시작될 때.
  • 백그라운드로 전환한 후 애플리케이션이 포그라운드로 전환되는 경우
  • 이전에 사용하지 않도록 설정된 경우 배포 모듈을 사용하도록 설정하는 경우.

새 릴리스에 대해 수동으로 검사 경우 업데이트에 대한 자동 검사 사용하지 않도록 설정할 수 있습니다. 이렇게 하려면 SDK가 시작되기 전에 다음 메서드를 호출합니다.

Distribute.disableAutomaticCheckForUpdate();
Distribute.disableAutomaticCheckForUpdate()

참고

메서드를 호출하기 전에 이 메서드를 AppCenter.start 호출해야 합니다.

그런 다음, 다음 섹션에 checkForUpdate 설명된 API를 사용할 수 있습니다.

수동으로 업데이트 확인

Distribute.checkForUpdate();
Distribute.checkForUpdate()

그러면 App Center에 요청을 보내고 사용 가능한 새 릴리스가 있는 경우 업데이트 대화 상자를 표시합니다.

참고

자동 업데이트를 사용하도록 설정한 경우에도 업데이트 호출에 대한 수동 검사 작동합니다. 다른 검사 이미 수행 중인 경우 업데이트에 대한 수동 검사 무시됩니다. 사용자가 업데이트를 연기한 경우(최신 버전이 필수 업데이트가 아닌 경우) 업데이트에 대한 수동 검사 처리되지 않습니다.

앱 내 업데이트 대화 상자 사용자 지정 또는 지역화

1. 텍스트 사용자 지정 또는 지역화

업데이트 대화 상자에 표시된 텍스트를 변경하거나 지역화하려는 경우 사용자 고유의 리소스 문자열을 쉽게 제공할 수 있습니다. 이 리소스 파일의 문자열 파일을 확인합니다. 동일한 문자열 이름/키를 사용하고 사용자 고유의 앱 리소스 파일의 대화 상자에 반영할 지역화된 값을 지정합니다.

2. 업데이트 대화 상자 사용자 지정

인터페이스를 구현하여 기본 업데이트 대화 상자의 모양을 사용자 지정할 수 있습니다 DistributeListener . 다음 예제와 같이 를 호출 AppCenter.start 하기 전에 수신기를 등록해야 합니다.

Distribute.setListener(new MyDistributeListener());
AppCenter.start(...);
Distribute.setListener(MyDistributeListener())
AppCenter.start(...)

다음은 SDK 대화 상자를 사용자 지정 대화 상자로 대체하는 수신기 구현의 예입니다.

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.net.Uri;

import com.microsoft.appcenter.distribute.Distribute;
import com.microsoft.appcenter.distribute.DistributeListener;
import com.microsoft.appcenter.distribute.ReleaseDetails;
import com.microsoft.appcenter.distribute.UpdateAction;

public class MyDistributeListener implements DistributeListener {

    @Override
    public boolean onReleaseAvailable(Activity activity, ReleaseDetails releaseDetails) {

        // Look at releaseDetails public methods to get version information, release notes text or release notes URL
        String versionName = releaseDetails.getShortVersion();
        int versionCode = releaseDetails.getVersion();
        String releaseNotes = releaseDetails.getReleaseNotes();
        Uri releaseNotesUrl = releaseDetails.getReleaseNotesUrl();

        // Build our own dialog title and message
        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(activity);
        dialogBuilder.setTitle("Version " + versionName + " available!"); // you should use a string resource instead, this is just a simple example
        dialogBuilder.setMessage(releaseNotes);

        // Mimic default SDK buttons
        dialogBuilder.setPositiveButton(com.microsoft.appcenter.distribute.R.string.appcenter_distribute_update_dialog_download, new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {

                // This method is used to tell the SDK what button was clicked
                Distribute.notifyUpdateAction(UpdateAction.UPDATE);
            }
        });

        // We can postpone the release only if the update isn't mandatory
        if (!releaseDetails.isMandatoryUpdate()) {
            dialogBuilder.setNegativeButton(com.microsoft.appcenter.distribute.R.string.appcenter_distribute_update_dialog_postpone, new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {

                    // This method is used to tell the SDK what button was clicked
                    Distribute.notifyUpdateAction(UpdateAction.POSTPONE);
                }
            });
        }
        dialogBuilder.setCancelable(false); // if it's cancelable you should map cancel to postpone, but only for optional updates
        dialogBuilder.create().show();

        // Return true if you're using your own dialog, false otherwise
        return true;
    }
    
    @Override
    public void onNoReleaseAvailable(Activity activity) {
        Toast.makeText(activity, activity.getString(R.string.no_updates_available), Toast.LENGTH_LONG).show();
    }
}
import android.app.Activity
import android.app.AlertDialog
import com.microsoft.appcenter.distribute.Distribute
import com.microsoft.appcenter.distribute.DistributeListener
import com.microsoft.appcenter.distribute.ReleaseDetails
import com.microsoft.appcenter.distribute.UpdateAction

class MyDistributeListener : DistributeListener {

    override fun onReleaseAvailable(activity: Activity, releaseDetails: ReleaseDetails): Boolean {

        // Look at releaseDetails public methods to get version information, release notes text or release notes URL
        val versionName = releaseDetails.shortVersion
        val versionCode = releaseDetails.version
        val releaseNotes = releaseDetails.releaseNotes
        val releaseNotesUrl = releaseDetails.releaseNotesUrl

        // Build our own dialog title and message
        val dialogBuilder = AlertDialog.Builder(activity)
        dialogBuilder.setTitle("Version $versionName available!") // you should use a string resource instead, this is just a simple example
        dialogBuilder.setMessage(releaseNotes)

        // Mimic default SDK buttons
        dialogBuilder.setPositiveButton(
            com.microsoft.appcenter.distribute.R.string.appcenter_distribute_update_dialog_download
        ) { dialog, which ->
            // This method is used to tell the SDK what button was clicked
            Distribute.notifyUpdateAction(UpdateAction.UPDATE)
        }

        // We can postpone the release only if the update isn't mandatory
        if (!releaseDetails.isMandatoryUpdate) {
            dialogBuilder.setNegativeButton(
                com.microsoft.appcenter.distribute.R.string.appcenter_distribute_update_dialog_postpone
            ) { dialog, which ->
                // This method is used to tell the SDK what button was clicked
                Distribute.notifyUpdateAction(UpdateAction.POSTPONE)
            }
        }
        dialogBuilder.setCancelable(false) // if it's cancelable you should map cancel to postpone, but only for optional updates
        dialogBuilder.create().show()

        // Return true if you're using your own dialog, false otherwise
        return true
    }

    override fun onNoReleaseAvailable(activity: Activity) {
        Toast.makeText(activity, activity.getString(R.string.no_updates_available), Toast.LENGTH_LONG).show()
    }
}

예제와 같이 를 호출하거나 수신기가 를 반환true하는 경우 를 호출 Distribute.notifyUpdateAction(UpdateAction.UPDATE);Distribute.notifyUpdateAction(UpdateAction.POSTPONE); 해야 합니다.

를 호출 notifyUpdateAction하지 않으면 모든 활동 변경에 대해 콜백이 반복됩니다.

사용자 작업이 SDK에 알림이 표시되기 전에 활동이 변경되면 동일한 릴리스로 수신기를 다시 호출할 수 있습니다.

이 동작은 다음 시나리오를 다루는 데 필요합니다.

  • 애플리케이션이 백그라운드로 전송된 다음(예: 누르기) 다른 작업에서 다시 시작됩니다.
  • 애플리케이션을 벗어나지 않고도(예: 일부 알림을 클릭하는 경우) 활동이 다른 작업으로 처리됩니다.
  • 다른 유사한 시나리오.

이 경우 대화 상자를 호스트하는 활동이 사용자 상호 작용 없이 대체될 수 있습니다. 따라서 SDK는 사용자 지정 대화 상자를 복원할 수 있도록 수신기를 다시 호출합니다.

SDK가 업데이트를 확인하고 현재 사용된 업데이트보다 최신 업데이트를 찾지 못하는 경우 인터페이스 콜백에서 DistributeListeneronNoReleaseAvailable 호출됩니다. 이렇게 하면 이러한 시나리오에서 사용자 지정 코드를 실행할 수 있습니다. 위의 예제에서는 업데이트를 찾을 수 없을 때 알림 메시지를 표시하는 방법을 보여 줍니다.

런타임에 App Center 배포 사용 또는 사용 안 함

런타임에 App Center 배포를 사용하도록 설정하고 사용하지 않도록 설정할 수 있습니다. 사용하지 않도록 설정하면 SDK에서 앱 내 업데이트 기능을 제공하지 않지만 App Center 포털에서 서비스 배포를 계속 사용할 수 있습니다.

Distribute.setEnabled(false);
Distribute.setEnabled(false)

App Center 배포를 다시 사용하도록 설정하려면 동일한 API를 사용하지만 매개 변수로 전달 true 합니다.

Distribute.setEnabled(true);
Distribute.setEnabled(true)

상태는 애플리케이션이 시작되는 동안 디바이스의 스토리지에 유지됩니다.

이 API는 비동기입니다. 자세한 내용은 App Center 비동기 API 가이드에서 확인할 수 있습니다.

참고

이 메서드는 가 시작된 후에 Distribute 만 사용해야 합니다.

App Center 배포가 사용하도록 설정되어 있는지 확인

App Center 배포를 사용하는지 여부를 검사 수도 있습니다.

Distribute.isEnabled();
Distribute.isEnabled()

이 API는 비동기입니다. 자세한 내용은 App Center 비동기 API 가이드에서 확인할 수 있습니다.

참고

이 메서드는 가 시작된 후에 Distribute 만 사용해야 하며, 시작 전에 항상 반환 false 됩니다.

디버그 빌드에 대한 앱 내 업데이트 사용

기본적으로 App Center는 릴리스 빌드에 대해서만 앱 내 업데이트를 사용하도록 설정합니다.

디버그 빌드에서 앱 내 업데이트를 사용하도록 설정하려면 전에 AppCenter.start다음 메서드를 호출합니다.

Distribute.setEnabledForDebuggableBuild(true);
Distribute.setEnabledForDebuggableBuild(true)

참고

이 메서드는 디버그 빌드에만 영향을 줍니다. 릴리스 빌드에는 영향을 주지 않습니다. 디버그 빌드는 플래그가 android:debuggable (일반적으로 미리 정의된 gradle 디버그 빌드 변형에 의해 자동으로 설정됨)로 설정 true 됨을 의미합니다. 그렇지 않으면 릴리스 빌드입니다.

앱 내 업데이트는 어떻게 작동합니까?

참고

앱 내 업데이트가 작동하려면 링크에서 앱 빌드를 다운로드해야 합니다. IDE에서 설치하거나 수동으로 설치하면 작동하지 않습니다.

앱 내 업데이트 기능은 다음과 같이 작동합니다.

  1. 이 기능은 App Center 배포 서비스를 사용하여 배포되는 릴리스 빌드(기본적으로)에서만 작동합니다.

  2. SDK를 통합하고 앱의 릴리스 버전을 빌드하고 App Center에 업로드하면 해당 메일 그룹의 사용자에게 이메일을 통해 새 릴리스에 대한 알림이 표시됩니다.

  3. 각 사용자가 전자 메일에서 링크를 열면 애플리케이션이 디바이스에 설치됩니다. 전자 메일 링크를 사용하여 설치하는 것이 중요합니다. 사이드 로드는 지원하지 않습니다. 링크에서 애플리케이션을 다운로드하면 SDK는 쿠키에서 중요한 정보를 저장하여 나중에 업데이트를 위해 검사 저장합니다. 그렇지 않으면 SDK에 해당 키 정보가 없습니다.

  4. 애플리케이션이 트랙을 프라이빗으로 설정하면 브라우저가 열리고 사용자를 인증하고 앱 내 업데이트를 사용하도록 설정합니다. 공용 트랙으로 다시 전환하고 나중에 다시 프라이빗으로 다시 전환하는 경우에도 인증 정보가 유효한 상태로 유지되는 한 브라우저가 다시 열리지 않습니다. 브라우저 인증에 성공하면 사용자가 자동으로 애플리케이션으로 다시 리디렉션됩니다. 트랙이 공용(기본값)이면 다음 단계가 직접 수행됩니다.

  5. 앱의 새 릴리스는 다음과 같은 경우 사용자에게 애플리케이션을 업데이트하도록 요청하는 앱 내 업데이트 대화 상자를 보여줍니다.

    • 또는 의 versionCode 더 높은 값
    • 의 값이 versionCode 같지만 의 다른 값입니다 versionName.

동일한 APK를 두 번째로 업로드하면 버전이 동일하기 때문에 대화 상자가 표시되지 않습니다 .

앱 내 업데이트를 테스트할 어떻게 할까요? 있나요?

App Center Portal에 릴리스 빌드(App Center SDK의 배포 모듈 사용)를 업로드하여 앱 내 업데이트를 테스트하고 매번 버전 번호를 늘려야 합니다.

  1. 아직 앱이 없는 경우 App Center 포털에서 앱을 만듭니다.
  2. 새 메일 그룹을 만들고 이름을 지정하여 앱에서 바로 업데이트 기능을 테스트하기 위한 것임을 인식할 수 있습니다.
  3. 자신(또는 앱 내 업데이트 기능 테스트에 포함하려는 모든 사용자)을 추가합니다. 이를 위해 App Center에서 해당 앱에 사용되지 않은 새 전자 메일 주소 또는 버리기 전자 메일 주소를 사용합니다. 이렇게 하면 실제 테스터의 환경에 가까운 경험을 할 수 있습니다.
  4. 위에서 설명한 대로 App Center 배포 를 포함하고 설치 논리를 포함하는 앱의 새 빌드를 만듭니다. 그룹이 프라이빗인 경우 setUpdateTrack API 사용을 시작하기 전에 프라이빗 앱 내 업데이트 트랙을 설정하는 것을 잊지 마세요.
  5. 포털에서 새 릴리스 배포 단추를 클릭하고 앱 빌드를 업로드합니다.
  6. 업로드가 완료되면 다음을 클릭하고 해당 앱 배포의 대상으로 만든 배포 그룹을 선택합니다.
  7. 배포를 검토하고 앱 내 테스트 그룹에 빌드를 배포합니다.
  8. 해당 그룹의 사람 앱의 테스터로 초대를 받습니다. 초대를 수락하면 모바일 디바이스에서 App Center 포털에서 앱을 다운로드할 수 있습니다. 앱 내 업데이트가 설치되면 앱 내 업데이트를 테스트할 준비가 된 것입니다.
  9. 앱의 를 versionCode 부딪치세요.
  10. 앱의 릴리스 버전을 빌드하고 이전 단계에서 수행한 것처럼 앱의 새 빌드를 업로드하고 이전에 만든 배포 그룹에 배포합니다. 다음에 앱이 시작될 때 메일 그룹의 구성원에게 새 버전을 입력하라는 메시지가 표시됩니다.

메일 그룹 등에 대한 자세한 내용은 App Center 배포를 활용하는 방법에 대한 정보를 살펴보십시오. App Center 배포를 사용하여 코드를 추가하지 않고도 새 버전의 앱을 배포할 수 있지만 앱 코드에 App Center 배포를 추가하면 테스터와 사용자가 앱에서 바로 업데이트 환경을 얻을 때 더 원활한 환경이 제공됩니다.