Google Play, kullanıcıların indirdiği sıkıştırılmış APK'nın en fazla 100 MB olmasını gerektirir. Çoğu uygulama için bu, uygulamanın tüm kodu ve öğeleri için yeterli alan demektir. Ancak bazı uygulamalar yüksek kaliteli grafikler, medya dosyaları veya diğer büyük öğeler için daha fazla alana ihtiyaç duyar. Daha önce, uygulamanızın sıkıştırılmış indirme boyutu 100 MB'ı aşıyorsa kullanıcı uygulamayı açtığında ek kaynakları kendiniz barındırmanız ve indirmeniz gerekiyordu. Ek dosyaları barındırmak ve sunmak maliyetli olabilir ve kullanıcı deneyimi genellikle ideal olmaktan uzaktır. Google Play, bu süreci sizin için daha kolay ve kullanıcılar için daha keyifli hale getirmek amacıyla APK'nıza ek olarak iki büyük genişletme dosyası eklemenize olanak tanır.
Google Play, uygulamanızın genişletme dosyalarını barındırır ve size maliyet yansıtılmaksızın cihaza sunar. Genişletme dosyaları, uygulamanızın bu dosyalara erişebileceği cihazın paylaşılan depolama alanında (SD kart veya takılabilir USB bölümü; "harici" depolama olarak da bilinir) depolanır. Google Play, çoğu cihazda APK ile birlikte genişletme dosyalarını da indirir. Böylece, kullanıcı uygulamanızı ilk kez açtığında uygulamanızda ihtiyaç duyulan her şey bulunur. Ancak bazı durumlarda uygulamanız, başladığında dosyaları Google Play'den indirmelidir.
Genişletme dosyası kullanmak istemiyorsanız ve uygulamanızın sıkıştırılmış indirme boyutu 100 MB'tan büyükse uygulamanızı 200 MB'a kadar sıkıştırılmış indirme boyutuna izin veren Android Uygulama Paketleri'ni kullanarak yüklemeniz gerekir. Ayrıca, uygulama paketlerinin kullanılması APK oluşturma ve imzalama işlemlerini Google Play'e ertelediği için kullanıcılar yalnızca uygulamanızı çalıştırmak için ihtiyaç duydukları kod ve kaynaklarla optimize edilmiş APK'lar indirir. Birden fazla APK veya genişletme dosyası oluşturmanız, imzalamanız ve yönetmeniz gerekmez. Böylece kullanıcılar daha küçük ve daha optimize edilmiş indirme işlemleri gerçekleştirir.
Genel Bakış
Google Play Console'u kullanarak her APK yüklediğinizde APK'ya bir veya iki genişletme dosyası ekleyebilirsiniz. Her dosya en fazla 2 GB olabilir ve istediğiniz biçimde olabilir ancak indirme sırasında bant genişliğini korumak için sıkıştırılmış bir dosya kullanmanızı öneririz. Her genişletme dosyasının işlevi farklıdır:
- Ana genişletme dosyası, uygulamanızın ihtiyaç duyduğu ek kaynaklar için birincil genişletme dosyasıdır.
- Yama genişletme dosyası isteğe bağlıdır ve ana genişletme dosyasında küçük güncellemeler için kullanılır.
İki genişletme dosyasını istediğiniz şekilde kullanabilirsiniz. Ancak ana genişletme dosyasının birincil öğeleri yayınlamasını ve nadiren güncellenmesini öneririz. Yama genişletme dosyası daha küçük olmalı ve her büyük sürümle veya gerektiğinde güncellenen bir "yama taşıyıcısı" olarak kullanılmalıdır.
Ancak uygulama güncellemeniz için yalnızca yeni bir yama genişletme dosyası gerekiyorsa bile manifest dosyasında güncellenmiş bir versionCode
içeren yeni bir APK yüklemeniz gerekir. (Play Console, mevcut bir APK'ya genişletme dosyası yüklemenize izin vermez.)
Not: Yama genişletme dosyası, anlamsal olarak ana genişletme dosyasıyla aynıdır. Her dosyayı istediğiniz şekilde kullanabilirsiniz.
Dosya adı biçimi
Yüklediğiniz her genişletme dosyası, seçtiğiniz herhangi bir biçimde (ZIP, PDF, MP4 vb.) olabilir. Bir kaynak dosyası grubunu ve bu gruba ait sonraki yamaları kapsayıp şifrelemek için JOBB aracını da kullanabilirsiniz. Google Play, dosya türünden bağımsız olarak bu dosyaları opak ikili blob olarak kabul eder ve aşağıdaki şemayı kullanarak dosyaları yeniden adlandırır:
[main|patch].<expansion-version>.<package-name>.obb
Bu şemanın üç bileşeni vardır:
main
veyapatch
- Dosyanın ana genişletme dosyası mı yoksa yama genişletme dosyası mı olduğunu belirtir. Her APK için yalnızca bir ana dosya ve bir yama dosyası olabilir.
<expansion-version>
- Bu, genişletmenin ilk ilişkilendirildiği APK'nın sürüm koduyla eşleşen bir tam sayıdır (uygulamanın
android:versionCode
değeriyle eşleşir).Play Console, yüklenen bir genişletme dosyasını yeni bir APK ile yeniden kullanmanıza izin verse de genişletme dosyasının adı değişmez. Dosya, ilk yüklediğinizde uygulanan sürümü korur. Bu nedenle "ilk" ifadesi vurgulanmıştır.
<package-name>
- Uygulamanızın Java tarzı paket adı.
Örneğin, APK sürümünüzün 314159 ve paket adınızın com.example.app olduğunu varsayalım. Ana genişletme dosyası yüklerseniz dosya şu şekilde yeniden adlandırılır:
main.314159.com.example.app.obb
Depolama konumu
Google Play, genişleme dosyalarınızı bir cihaza indirdiğinde bunları sistemin ortak depolama konumuna kaydeder. Doğru şekilde çalışmasını sağlamak için genişleme dosyalarını silmemeli, taşımamalı veya yeniden adlandırmamalısınız. Uygulamanızın Google Play'den indirme işlemini gerçekleştirmesi gerekiyorsa dosyaları tam olarak aynı konuma kaydetmeniz gerekir.
getObbDir()
yöntemi, genişleme dosyalarınızın belirli konumunu aşağıdaki biçimde döndürür:
<shared-storage>/Android/obb/<package-name>/
<shared-storage>
, paylaşılan depolama alanının yoludur vegetExternalStorageDirectory()
adresinden kullanılabilir.<package-name>
, uygulamanızın Java tarzı paket adıdır vegetPackageName()
adresinden kullanılabilir.
Her uygulama için bu dizinde en fazla iki genişletme dosyası bulunur.
Bunlardan biri ana genişletme dosyası, diğeri ise yama genişletme dosyasıdır (gerekirse). Uygulamanızı yeni genişletme dosyalarıyla güncellediğinizde önceki sürümlerin üzerine yazılır. Android 4.4 (API düzeyi 19) sürümünden itibaren uygulamalar, harici depolama izni olmadan OBB
genişletme dosyalarını okuyabilir. Ancak Android 6.0 (API düzeyi 23) ve sonraki sürümlerin bazı uygulamalarında izin almaya devam etmeniz gerekir. Bu nedenle, READ_EXTERNAL_STORAGE
iznini uygulama manifestinde beyan etmeniz ve aşağıdaki şekilde çalışma zamanında izin istemeniz gerekir:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Android 6 ve sonraki sürümlerde harici depolama alanı izninin çalışma zamanında istenmesi gerekir. Ancak Android'in bazı uygulamalarında OBB dosyalarını okuma izni gerekmez. Aşağıdaki kod snippet'inde, harici depolama alanı izni istemeden önce okuma erişimini nasıl kontrol edeceğiniz gösterilmektedir:
Kotlin
val obb = File(obb_filename) var open_failed = false try { BufferedReader(FileReader(obb)).also { br -> ReadObbFile(br) } } catch (e: IOException) { open_failed = true } if (open_failed) { // request READ_EXTERNAL_STORAGE permission before reading OBB file ReadObbFileWithPermission() }
Java
File obb = new File(obb_filename); boolean open_failed = false; try { BufferedReader br = new BufferedReader(new FileReader(obb)); open_failed = false; ReadObbFile(br); } catch (IOException e) { open_failed = true; } if (open_failed) { // request READ_EXTERNAL_STORAGE permission before reading OBB file ReadObbFileWithPermission(); }
Genişletme dosyalarınızın içeriğini açmanız gerekiyorsa OBB
genişletme dosyalarını daha sonra silmeyin ve açılmış verileri aynı dizine kaydetmeyin. Ayıkladığınız dosyaları getExternalFilesDir()
tarafından belirtilen dizine kaydetmeniz gerekir. Ancak mümkünse verileri açmanızı gerektirmek yerine doğrudan dosyadan okumanıza olanak tanıyan bir genişleme dosyası biçimi kullanmanız en iyisidir. Örneğin, verilerinizi doğrudan ZIP dosyasından okuyan APK Expansion Zip Library adlı bir kitaplık projesi sağladık.
Dikkat: APK dosyalarının aksine, paylaşılan depolama alanına kaydedilen dosyalar kullanıcı ve diğer uygulamalar tarafından okunabilir.
İpucu: Medya dosyalarını ZIP olarak paketliyorsanız ZIP'inizi açmak zorunda kalmadan, ofset ve uzunluk kontrolleri (ör. MediaPlayer.setDataSource()
ve SoundPool.load()
) içeren dosyalarda medya oynatma çağrılarını kullanabilirsiniz. Bunun işe yaraması için ZIP paketlerini oluştururken medya dosyalarında ek sıkıştırma işlemi gerçekleştirmemeniz gerekir. Örneğin, zip
aracını kullanırken sıkıştırılmaması gereken dosya uzantılarını belirtmek için -n
seçeneğini kullanmanız gerekir:
zip -n .mp4;.ogg main_expansion media_files
İndirme işlemi
Google Play, çoğu zaman APK'yı cihaza indirirken aynı anda genişletme dosyalarınızı indirip kaydeder. Ancak bazı durumlarda Google Play genişletme dosyalarını indiremez veya kullanıcı daha önce indirilen genişletme dosyalarını silmiş olabilir. Bu durumların üstesinden gelmek için uygulamanızın, ana etkinlik başladığında Google Play tarafından sağlanan bir URL'yi kullanarak dosyaları kendi başına indirebilmesi gerekir.
İndirme işlemi genel hatlarıyla şu şekildedir:
- Kullanıcı, uygulamanızı Google Play'den yüklemeyi seçer.
- Google Play, genişletme dosyalarını indirebiliyorsa (çoğu cihazda bu mümkündür) APK ile birlikte indirir.
Google Play, genişletme dosyalarını indiremezse yalnızca APK'yı indirir.
- Kullanıcı uygulamanızı başlattığında, uygulamanız genişleme dosyalarının cihaza önceden kaydedilip kaydedilmediğini kontrol etmelidir.
- Cevabınız evet ise uygulamanız kullanıma hazırdır.
- Aksi takdirde, uygulamanız genişletme dosyalarını Google Play'den HTTP üzerinden indirmelidir. Uygulamanız, Google Play'in uygulama lisanslama hizmetini kullanarak Google Play istemcisine bir istek göndermelidir. Bu hizmet, her genişleme dosyasının adını, dosya boyutunu ve URL'sini içeren bir yanıt verir. Bu bilgilerle dosyaları indirip uygun depolama konumuna kaydedebilirsiniz.
Dikkat: Uygulamanız başladığında dosyalar cihazda yoksa genişleme dosyalarını Google Play'den indirmek için gerekli kodu eklemeniz önemlidir. Genişleme dosyalarını indirme ile ilgili aşağıdaki bölümde belirtildiği gibi, bu süreci büyük ölçüde basitleştiren ve indirme işlemini bir hizmetten sizin minimum miktarda kod göndermenizle gerçekleştiren bir kitaplık hazırladık.
Geliştirme kontrol listesi
Uygulamanızla genişletme dosyalarını kullanmak için yapmanız gereken görevlerin özetini aşağıda bulabilirsiniz:
- Öncelikle, uygulamanızın sıkıştırılmış indirme boyutunun 100 MB'tan fazla olması gerekip gerekmediğini belirleyin. Alan değerlidir ve toplam indirme boyutunuzu mümkün olduğunca küçük tutmanız gerekir. Uygulamanız, birden fazla ekran yoğunluğu için grafik öğelerinizin birden fazla sürümünü sağlamak amacıyla 100 MB'tan fazla yer kaplıyorsa bunun yerine her APK'nın yalnızca hedeflediği ekranlar için gereken öğeleri içerdiği birden fazla APK yayınlamayı düşünebilirsiniz. Google Play'de yayınlarken en iyi sonuçları elde etmek için uygulamanızın tüm derlenmiş kod ve kaynaklarını içeren ancak APK oluşturma ve imzalama işlemini Google Play'e bırakan bir Android App Bundle yükleyin.
- APK'nızdan hangi uygulama kaynaklarının ayrılacağını belirleyin ve bunları ana genişletme dosyası olarak kullanmak için bir dosyada paketleyin.
Normalde, ikinci yama genişletme dosyasını yalnızca ana genişletme dosyasında güncelleme yaparken kullanmalısınız. Ancak kaynaklarınız ana genişletme dosyası için belirlenen 2 GB sınırını aşarsa öğelerinizin geri kalanı için yama dosyasını kullanabilirsiniz.
- Uygulamanızı, cihazın paylaşılan depolama alanındaki genişletme dosyalarınızdaki kaynakları kullanacak şekilde geliştirin.
Genişletme dosyalarını silmeniz, taşımanız veya yeniden adlandırmamanız gerektiğini unutmayın.
Uygulamanız belirli bir biçim gerektirmiyorsa genişletme dosyalarınız için ZIP dosyaları oluşturmanızı ve ardından bunları APK Genişletme ZIP Kitaplığı'nı kullanarak okumanızı öneririz.
- Uygulamanızın ana etkinliğine, başlangıçta cihazda genişleme dosyalarının olup olmadığını kontrol eden bir mantık ekleyin. Dosyalar cihazda yoksa Google Play'in uygulama lisanslama hizmetini kullanarak genişleme dosyalarının URL'lerini isteyin, ardından dosyaları indirip kaydedin.
Yazmanız gereken kod miktarını büyük ölçüde azaltmak ve indirme sırasında iyi bir kullanıcı deneyimi sağlamak için indirme davranışınızı uygulamak üzere Downloader Library'yi kullanmanızı öneririz.
Kitaplığı kullanmak yerine kendi indirme hizmetinizi oluşturursanız genişleme dosyalarının adını değiştirmemeniz ve bunları uygun depolama konumuna kaydetmeniz gerektiğini unutmayın.
Uygulamanızın geliştirmesini tamamladıktan sonra Genişletme Dosyalarınızı Test Etme başlıklı kılavuzu uygulayın.
Kurallar ve Sınırlılıklar
APK genişletme dosyası ekleme özelliği, uygulamanızı Play Console'u kullanarak yüklediğinizde kullanılabilir. Uygulamanızı ilk kez yüklerken veya genişletme dosyaları kullanan bir uygulamayı güncellerken aşağıdaki kurallara ve sınırlamalara dikkat etmeniz gerekir:
- Her genişletme dosyası en fazla 2 GB olabilir.
- Genişleme dosyalarınızı Google Play'den indirmek için kullanıcı, uygulamanızı Google Play'den edinmiş olmalıdır. Uygulama başka bir yöntemle yüklendiyse Google Play, genişletme dosyalarınızın URL'lerini sağlamaz.
- İndirme işlemini uygulamanızdan gerçekleştirirken Google Play'in her dosya için sağladığı URL, her indirme için benzersizdir ve uygulamanıza sağlandıktan kısa bir süre sonra geçerlilik süresi sona erer.
- Uygulamanızı yeni bir APK ile güncellerseniz veya aynı uygulama için birden fazla APK yüklerseniz önceki bir APK için yüklediğiniz genişletme dosyalarını seçebilirsiniz. Genişleme dosyasının adı değişmez. Dosyanın orijinal olarak ilişkilendirildiği APK tarafından alınan sürüm korunur.
- Farklı cihazlar için farklı genişletme dosyaları sağlamak amacıyla genişletme dosyalarını birden fazla APK ile birlikte kullanıyorsanız yine de her cihaz için benzersiz bir
versionCode
değeri sağlamak ve her APK için farklı filtreler tanımlamak üzere ayrı APK'lar yüklemeniz gerekir. - Genişletme dosyalarını değiştirerek uygulamanızda güncelleme yayınlayamazsınız. Uygulamanızı güncellemek için yeni bir APK yüklemeniz gerekir. Değişiklikleriniz yalnızca genişletme dosyalarınızdaki öğelerle ilgiliyse APK'nızı yalnızca
versionCode
(ve belki deversionName
) dosyasını değiştirerek güncelleyebilirsiniz. obb/
dizininizle ilişkili başka veriler kaydetmeyin. Bazı verileri açmanız gerekiyorsa bunlarıgetExternalFilesDir()
tarafından belirtilen konuma kaydedin.- Güncelleme yapmıyorsanız
.obb
genişletme dosyasını silmeyin veya yeniden adlandırmayın. Bu işlem, Google Play'in (veya uygulamanızın) genişletme dosyasını tekrar tekrar indirmesine neden olur. - Bir genişletme dosyasını manuel olarak güncellerken önceki genişletme dosyasını silmeniz gerekir.
Genişletme dosyalarını indirme
Google Play, çoğu durumda APK'yı yüklerken veya güncellerken genişletme dosyalarınızı da indirip cihaza kaydeder. Bu sayede, uygulamanız ilk kez başlatıldığında genişleme dosyaları kullanılabilir. Ancak bazı durumlarda uygulamanızın, Google Play'in uygulama lisanslama hizmetinden gelen bir yanıtta size sağlanan bir URL'den isteyerek genişletme dosyalarını kendisinin indirmesi gerekir.
Genişletme dosyalarınızı indirmek için kullanmanız gereken temel mantık şudur:
- Uygulamanız başladığında, paylaşılan depolama alanında (
Android/obb/<package-name>/
dizininde) genişletme dosyalarını arayın.- Genişletme dosyaları mevcutsa uygulamanız çalışmaya devam edebilir.
- Genişletme dosyaları bulunmuyorsa:
- Uygulamanızın genişleme dosyası adlarını, boyutlarını ve URL'lerini almak için Google Play'in uygulama lisanslama özelliğini kullanarak bir istek gönderin.
- Genişletme dosyalarını indirmek ve kaydetmek için Google Play tarafından sağlanan URL'leri kullanın. Dosyaları paylaşılan depolama konumuna (
Android/obb/<package-name>/
) kaydetmeniz ve Google Play'in yanıtında sağlanan dosya adını aynen kullanmanız gerekir.Not: Google Play'in genişletme dosyalarınız için sağladığı URL, her indirme için benzersizdir ve her birinin süresi, uygulamanıza verildikten kısa bir süre sonra dolar.
Uygulamanız ücretsizse (ücretli değilse) muhtemelen uygulama lisanslama hizmetini kullanmamışsınızdır. Bu özellik, öncelikle uygulamanız için lisanslama politikalarını uygulamanız ve kullanıcının uygulamanızı kullanma hakkına sahip olmasını (Google Play'de bunun için ödeme yaptığından) sağlamak üzere tasarlanmıştır. Genişletme dosyası işlevini kolaylaştırmak için lisanslama hizmeti, uygulamanıza Google Play'de barındırılan uygulamanızın genişleme dosyalarının URL'sini içeren bir yanıt verecek şekilde geliştirildi. Bu nedenle, uygulamanız kullanıcılar için ücretsiz olsa bile APK genişletme dosyalarını kullanmak için Lisans Doğrulama Kitaplığı'nı (LVL) eklemeniz gerekir. Elbette, uygulamanız ücretsizse lisans doğrulamasını zorunlu tutmanız gerekmez. Kitaplığın, genişleme dosyalarınızın URL'sini döndüren isteği gerçekleştirmesi yeterlidir.
Not: Uygulamanız ücretsiz olsun veya olmasın Google Play, genişleme dosyası URL'lerini yalnızca kullanıcı uygulamanızı Google Play'den edindiyse döndürür.
LVL'ye ek olarak, genişleme dosyalarını bir HTTP bağlantısı üzerinden indirip cihazın ortak depolama alanındaki uygun konuma kaydeden bir kod grubuna ihtiyacınız vardır. Bu prosedürü uygulamanıza eklerken dikkate almanız gereken birkaç konu vardır:
- Cihazda genişletme dosyaları için yeterli alan olmayabilir. Bu nedenle, indirme işlemine başlamadan önce alanı kontrol etmeniz ve yeterli alan yoksa kullanıcıyı uyarmanız gerekir.
- Dosya indirme işlemleri, kullanıcı etkileşimini engellememek ve indirme tamamlanırken kullanıcının uygulamanızdan çıkmasına izin vermek için arka plan hizmetinde yapılmalıdır.
- İstek ve indirme sırasında çeşitli hatalar oluşabilir. Bu hataları düzgün bir şekilde ele almanız gerekir.
- Ağ bağlantısı indirme sırasında değişebilir. Bu nedenle, bu tür değişiklikleri yönetmeniz ve kesinti olursa mümkün olduğunda indirme işlemini devam ettirmeniz gerekir.
- İndirme işlemi arka planda gerçekleşirken indirme ilerleme durumunu gösteren, indirme işlemi tamamlandığında kullanıcıyı bilgilendiren ve kullanıcının seçmesi durumunda kullanıcıyı uygulamanıza geri götüren bir bildirim sağlamanız gerekir.
Bu işlemi sizin için basitleştirmek amacıyla, lisanslama hizmeti aracılığıyla genişleme dosyası URL'lerini isteyen, genişleme dosyalarını indiren, yukarıda listelenen tüm görevleri gerçekleştiren ve hatta etkinliğinizin indirme işlemini duraklatmasına ve devam ettirmesine olanak tanıyan İndirici Kitaplığı'nı oluşturduk. Uygulamanıza İndirici Kitaplığı'nı ve birkaç kod kancası ekleyerek genişleme dosyalarını indirmeyle ilgili neredeyse tüm işlemleri sizin için kodlamış olursunuz. Bu nedenle, en iyi kullanıcı deneyimini sunmak için en az çabayı göstermeniz gerekir. Bu nedenle, genişletme dosyalarınızı indirmek üzere İndirme Arşivi'ni kullanmanızı öneririz. Aşağıdaki bölümlerdeki bilgilerde, kitaplığın uygulamanıza nasıl entegre edileceği açıklanmaktadır.
Google Play URL'lerini kullanarak genişleme dosyalarını indirmek için kendi çözümünüzü geliştirmeyi tercih ederseniz lisans isteği göndermek için uygulama lisanslama dokümanlarını uygulamanız, ardından genişleme dosyası adlarını, boyutlarını ve URL'lerini yanıt ekstralarından almanız gerekir. Lisanslama politikanız olarak APKExpansionPolicy
sınıfını (Lisans Doğrulama Kitaplığı'na dahildir) kullanmanız gerekir. Bu sınıf, lisanslama hizmetinden genişleme dosyası adlarını, boyutlarını ve URL'lerini yakalar.
İndirme Aracı Kitaplığı hakkında
APK genişletme dosyalarını uygulamanızla kullanmak ve en az çabayla en iyi kullanıcı deneyimini sunmak için Google Play APK Genişletme Kitaplığı paketine dahil olan İndirme Aracı Kitaplığı'nı kullanmanızı öneririz. Bu kitaplık, genişleme dosyalarınızı arka plan hizmetinde indirir, indirme durumunu içeren bir kullanıcı bildirimi gösterir, ağ bağlantısının kesilmesini yönetir, mümkün olduğunda indirme işlemini devam ettirir ve daha birçok işlem yapar.
İndirme Aracı Kitaplığı'nı kullanarak genişletme dosyası indirmelerini uygulamak için tek yapmanız gereken:
- Her biri sizden yalnızca birkaç satır kod gerektiren özel bir
Service
alt sınıfı veBroadcastReceiver
alt sınıfı genişletin. - Ana etkinliğinize, genişleme dosyalarının indirilip indirilmediğini kontrol eden ve indirilmediyse indirme işlemini başlatan ve ilerleme kullanıcı arayüzü gösteren bir mantık ekleyin.
- Ana etkinliğinizde, indirme ilerleme durumuyla ilgili güncellemeler alan birkaç yöntem içeren bir geri çağırma arayüzü uygulayın.
Aşağıdaki bölümlerde, İndirici Kitaplığı'nı kullanarak uygulamanızı nasıl ayarlayacağınız açıklanmaktadır.
İndirme Aracı Kitaplığı'nı kullanmaya hazırlanma
İndirici kitaplığını kullanmak için SDK Yöneticisi'nden iki paket indirmeniz ve uygun kitaplıkları uygulamanıza eklemeniz gerekir.
Öncelikle Android SDK Yöneticisi'ni (Araçlar > SDK Yöneticisi) açın ve Görünüm ve Davranış > Sistem Ayarları > Android SDK bölümünde SDK Araçları sekmesini seçerek aşağıdakileri indirin:
- Google Play Lisanslama Kitaplığı paketi
- Google Play APK Genişleme Kitaplığı paketi
Lisans Doğrulama Kitaplığı ve İndirici Kitaplığı için yeni bir kitaplık modülü oluşturun. Her kütüphane için:
- Dosya > Yeni > Yeni Modül'ü seçin.
- Yeni Modül Oluştur penceresinde Android Kitaplığı'nı, ardından Sonraki'yi seçin.
- "Google Play Lisans Kitaplığı" ve "Google Play İndirici Kitaplığı" gibi bir uygulama/kitaplık adı belirtin, Minimum SDK düzeyi'ni seçin ve ardından Son'u seçin.
- Dosya > Proje Yapısı'nı seçin.
- Özellikler sekmesini seçin ve Kitaplık Deposu'nda
<sdk>/extras/google/
dizininden kitaplığı girin (Lisans Doğrulama Kitaplığı içinplay_licensing/
veya İndirici Kitaplığı içinplay_apk_expansion/downloader_library/
). - Yeni modülü oluşturmak için Tamam'ı seçin.
Not: İndirici Kitaplığı, Lisans Doğrulama Kitaplığı'na bağlıdır. Lisans Doğrulama Kitaplığı'nı İndirici Kitaplığı'nın proje özelliklerine eklediğinizden emin olun.
Alternatif olarak, komut satırından projenizi kitaplıkları içerecek şekilde güncelleyebilirsiniz:
- Dizinleri
<sdk>/tools/
dizinine değiştirin. - Hem LVL'yi hem de İndirici Kitaplığı'nı projenize eklemek için
android update project
'yi--library
seçeneğiyle çalıştırın. Örnek:android update project --path ~/Android/MyApp \ --library ~/android_sdk/extras/google/market_licensing \ --library ~/android_sdk/extras/google/market_apk_expansion/downloader_library
Uygulamanıza hem Lisans Doğrulama Kitaplığı'nı hem de İndirici Kitaplığı'nı eklediğinizde, Google Play'den genişletme dosyası indirme özelliğini hızlıca entegre edebilirsiniz. Genişleme dosyaları için seçtiğiniz biçim ve bu dosyaları paylaşılan depolama alanından nasıl okuyacağınız, uygulama ihtiyaçlarınıza göre dikkate almanız gereken ayrı bir uygulamadır.
İpucu: Apk Expansion paketinde, Downloader Library'nin bir uygulamada nasıl kullanılacağını gösteren bir örnek uygulama bulunur. Örnekte, Apk Expansion paketinde bulunan APK Expansion Zip Library adlı üçüncü bir kitaplık kullanılır. Genişletme dosyalarınız için ZIP dosyaları kullanmayı planlıyorsanız APK Genişletme ZIP Kitaplığı'nı da uygulamanıza eklemenizi öneririz. Daha fazla bilgi için aşağıdaki APK Genişletme ZIP Kitaplığı'nı kullanma bölümüne bakın.
Kullanıcı izinlerini beyan etme
İndirme Arşivi'nin genişletme dosyalarını indirmesi için uygulamanızın manifest dosyasında belirtmeniz gereken çeşitli izinler gerekir. Bunlar:
<manifest ...> <!-- Required to access Google Play Licensing --> <uses-permission android:name="com.android.vending.CHECK_LICENSE" /> <!-- Required to download files from Google Play --> <uses-permission android:name="android.permission.INTERNET" /> <!-- Required to keep CPU alive while downloading files (NOT to keep screen awake) --> <uses-permission android:name="android.permission.WAKE_LOCK" /> <!-- Required to poll the state of the network connection and respond to changes --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- Required to check whether Wi-Fi is enabled --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <!-- Required to read and write the expansion files on shared storage --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> ... </manifest>
Not: İndirici kitaplığı için varsayılan olarak API düzeyi 4 gerekir ancak APK genişletme ZIP kitaplığı için API düzeyi 5 gerekir.
İndirme hizmetinin uygulanması
İndirme işlemini arka planda gerçekleştirmek için İndirici Kitaplığı, genişletmeniz gereken DownloaderService
adlı kendi Service
alt sınıfını sağlar. DownloaderService
, genişletme dosyalarını sizin için indirmenin yanı sıra şunları da yapar:
- Gerekli olduğunda (ör. bağlantı kaybı nedeniyle) indirme işlemini duraklatmak ve mümkün olduğunda (bağlantı elde edildiğinde) indirme işlemini devam ettirmek için cihazın ağ bağlantısında (
CONNECTIVITY_ACTION
yayını) değişiklikleri dinleyen birBroadcastReceiver
kaydeder. - Hizmetin sonlandırıldığı durumlarda indirme işlemini yeniden denemek için bir
RTC_WAKEUP
alarmı planlar. - İndirme ilerleme durumunu ve hataları ya da durum değişikliklerini gösteren özel bir
Notification
oluşturur. - Uygulamanızın indirme işlemini manuel olarak duraklatmasına ve devam ettirmesine olanak tanır.
- Genişleme dosyalarını indirmeden önce ortak depolama alanının bağlı ve kullanılabilir olup olmadığını, dosyaların mevcut olup olmadığını ve yeterli alan olup olmadığını doğrular. Ardından, bunlardan herhangi biri doğru değilse kullanıcıyı bilgilendirir.
Bunun için uygulamanızda DownloaderService
sınıfını genişleten bir sınıf oluşturmanız ve belirli uygulama ayrıntılarını sağlamak için üç yöntemi geçersiz kılmanız yeterlidir:
getPublicKey()
- Bu işlev, yayıncı hesabınız için Base64 kodlu RSA ortak anahtarı olan bir dize döndürmelidir. Bu anahtarı Play Console'daki profil sayfasından bulabilirsiniz (Lisanslama için ayarlama bölümüne bakın).
getSALT()
- Bu işlev, lisanslama
Policy
'ınObfuscator
oluşturmak için kullandığı rastgele baytlardan oluşan bir dizi döndürmelidir. Tuz, lisanslama verilerinizin kaydedildiği karartılmışSharedPreferences
dosyanızın benzersiz ve bulunamaz olmasını sağlar. getAlarmReceiverClassName()
- Bu, uygulamanızda indirme işleminin yeniden başlatılması gerektiğini belirten alarmı alması gereken
BroadcastReceiver
sınıfının adını döndürmelidir (indirme hizmeti beklenmedik bir şekilde durursa bu durumla karşılaşılabilir).
Örneğin, DownloaderService
için eksiksiz bir uygulamayı aşağıda bulabilirsiniz:
Kotlin
// You must use the public key belonging to your publisher account const val BASE64_PUBLIC_KEY = "YourLVLKey" // You should also modify this salt val SALT = byteArrayOf( 1, 42, -12, -1, 54, 98, -100, -12, 43, 2, -8, -4, 9, 5, -106, -107, -33, 45, -1, 84 ) class SampleDownloaderService : DownloaderService() { override fun getPublicKey(): String = BASE64_PUBLIC_KEY override fun getSALT(): ByteArray = SALT override fun getAlarmReceiverClassName(): String = SampleAlarmReceiver::class.java.name }
Java
public class SampleDownloaderService extends DownloaderService { // You must use the public key belonging to your publisher account public static final String BASE64_PUBLIC_KEY = "YourLVLKey"; // You should also modify this salt public static final byte[] SALT = new byte[] { 1, 42, -12, -1, 54, 98, -100, -12, 43, 2, -8, -4, 9, 5, -106, -107, -33, 45, -1, 84 }; @Override public String getPublicKey() { return BASE64_PUBLIC_KEY; } @Override public byte[] getSALT() { return SALT; } @Override public String getAlarmReceiverClassName() { return SampleAlarmReceiver.class.getName(); } }
Not: BASE64_PUBLIC_KEY
değerini yayıncı hesabınıza ait herkese açık anahtar olarak güncellemeniz gerekir. Anahtarı, Developer Console'daki profil bilgilerinizin altında bulabilirsiniz. Bu, indirmelerinizi test ederken bile gereklidir.
Hizmeti manifest dosyanızda belirtmeyi unutmayın:
<app ...> <service android:name=".SampleDownloaderService" /> ... </app>
Alarm alıcısını uygulama
DownloaderService
, dosya indirme işlemlerinin ilerleme durumunu izlemek ve gerekirse indirme işlemini yeniden başlatmak için uygulamanızda bir BroadcastReceiver
'a Intent
yayınlayan bir RTC_WAKEUP
alarmı planlar. İndirme işleminin durumunu kontrol eden ve gerekirse yeniden başlatan bir API'yi çağırmak için BroadcastReceiver
'yi tanımlamanız gerekir.
DownloaderClientMarshaller.startDownloadServiceIfRequired()
yöntemini çağırmak için onReceive()
yöntemini geçersiz kılmanız yeterlidir.
Örnek:
Kotlin
class SampleAlarmReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { try { DownloaderClientMarshaller.startDownloadServiceIfRequired( context, intent, SampleDownloaderService::class.java ) } catch (e: PackageManager.NameNotFoundException) { e.printStackTrace() } } }
Java
public class SampleAlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { try { DownloaderClientMarshaller.startDownloadServiceIfRequired(context, intent, SampleDownloaderService.class); } catch (NameNotFoundException e) { e.printStackTrace(); } } }
Bu, hizmetinizin getAlarmReceiverClassName()
yönteminde adı döndürmeniz gereken sınıftır (önceki bölüme bakın).
Alıcının manifest dosyanızda belirtilmesi gerekir:
<app ...> <receiver android:name=".SampleAlarmReceiver" /> ... </app>
İndirme işlemini başlatma
Uygulamanızdaki ana etkinlik (başlatıcı simgeniz tarafından başlatılan etkinlik), genişleme dosyalarının cihazda olup olmadığını doğrulamaktan ve yoksa indirme işlemini başlatmaktan sorumludur.
İndirme işlemini İndirme Aracı Kitaplığı'nı kullanarak başlatmak için aşağıdaki işlemleri yapmanız gerekir:
- Dosyaların indirilip indirilmediğini kontrol edin.
İndirme Aracı Kitaplığı, bu sürece yardımcı olmak için
Helper
sınıfında bazı API'ler içerir:getExpansionAPKFileName(Context, c, boolean mainFile, int versionCode)
doesFileExist(Context c, String fileName, long fileSize)
Örneğin, Apk Expansion paketinde sağlanan örnek uygulama, genişletme dosyalarının cihazda mevcut olup olmadığını kontrol etmek için etkinliğin
onCreate()
yönteminde aşağıdaki yöntemi çağırır:Kotlin
fun expansionFilesDelivered(): Boolean { xAPKS.forEach { xf -> Helpers.getExpansionAPKFileName(this, xf.isBase, xf.fileVersion).also { fileName -> if (!Helpers.doesFileExist(this, fileName, xf.fileSize, false)) return false } } return true }
Java
boolean expansionFilesDelivered() { for (XAPKFile xf : xAPKS) { String fileName = Helpers.getExpansionAPKFileName(this, xf.isBase, xf.fileVersion); if (!Helpers.doesFileExist(this, fileName, xf.fileSize, false)) return false; } return true; }
Bu durumda her
XAPKFile
nesnesi, bilinen bir genişletme dosyasının sürüm numarasını ve dosya boyutunu ve ana genişletme dosyası olup olmadığına dair bir boole değeri içerir. (Ayrıntılar için örnek uygulamanınSampleDownloaderActivity
sınıfına bakın.)Bu yöntem yanlış döndürürse uygulamanın indirme işlemini başlatması gerekir.
DownloaderClientMarshaller.startDownloadServiceIfRequired(Context c, PendingIntent notificationClient, Class<?> serviceClass)
statik yöntemini çağırarak indirme işlemini başlatın.Yöntem aşağıdaki parametreleri alır:
context
: UygulamanızınContext
.notificationClient
: Ana etkinliğinizi başlatmak için birPendingIntent
. Bu,DownloaderService
'un indirme işleminin ilerleme durumunu göstermek için oluşturduğuNotification
içinde kullanılır. Kullanıcı bildirimi seçtiğinde sistem, burada sağladığınızPendingIntent
öğesini çağırır ve indirme ilerleme durumunu gösteren etkinliği (genellikle indirmeyi başlatan etkinlik) açar.serviceClass
:DownloaderService
uygulamanız içinClass
nesnesi. Hizmeti başlatmak ve gerekirse indirme işlemini başlatmak için gereklidir.
Yöntem, indirme işleminin gerekli olup olmadığını belirten bir tam sayı döndürür. Olası değerler:
NO_DOWNLOAD_REQUIRED
: Dosyalar zaten mevcutsa veya indirme işlemi devam ediyorsa döndürülür.LVL_CHECK_REQUIRED
: Genişletme dosyası URL'lerini almak için lisans doğrulaması gerekiyorsa döndürülür.DOWNLOAD_REQUIRED
: Genişletme dosyası URL'leri zaten biliniyor ancak indirilmediyse döndürülür.
LVL_CHECK_REQUIRED
veDOWNLOAD_REQUIRED
için davranış temelde aynıdır ve genellikle bunlarla ilgili endişelenmenize gerek yoktur.startDownloadServiceIfRequired()
işlevini çağıran ana etkinliğinizde, yanıtınNO_DOWNLOAD_REQUIRED
olup olmadığını kontrol edebilirsiniz. YanıtNO_DOWNLOAD_REQUIRED
değilse İndirici Kitaplığı indirme işlemini başlatır ve indirme ilerleme durumunu göstermek için etkinlik kullanıcı arayüzünüzü güncellemeniz gerekir (sonraki adıma bakın). YanıtNO_DOWNLOAD_REQUIRED
ise dosyalar kullanılabilir durumdadır ve uygulamanız başlatılabilir.Örnek:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Check if expansion files are available before going any further if (!expansionFilesDelivered()) { val pendingIntent = // Build an Intent to start this activity from the Notification Intent(this, MainActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP }.let { notifierIntent -> PendingIntent.getActivity( this, 0, notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT ) } // Start the download service (if required) val startResult: Int = DownloaderClientMarshaller.startDownloadServiceIfRequired( this, pendingIntent, SampleDownloaderService::class.java ) // If download has started, initialize this activity to show // download progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // This is where you do set up to display the download // progress (next step) ... return } // If the download wasn't necessary, fall through to start the app } startApp() // Expansion files are available, start the app }
Java
@Override public void onCreate(Bundle savedInstanceState) { // Check if expansion files are available before going any further if (!expansionFilesDelivered()) { // Build an Intent to start this activity from the Notification Intent notifierIntent = new Intent(this, MainActivity.getClass()); notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); ... PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT); // Start the download service (if required) int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this, pendingIntent, SampleDownloaderService.class); // If download has started, initialize this activity to show // download progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // This is where you do set up to display the download // progress (next step) ... return; } // If the download wasn't necessary, fall through to start the app } startApp(); // Expansion files are available, start the app }
startDownloadServiceIfRequired()
yöntemiNO_DOWNLOAD_REQUIRED
dışında bir değer döndürdüğündeDownloaderClientMarshaller.CreateStub(IDownloaderClient client, Class<?> downloaderService)
'i çağırarakIStub
örneği oluşturun.IStub
, etkinliğiniz ile indirici hizmeti arasında bir bağlama sağlar. Böylece etkinliğiniz, indirme ilerleme durumuyla ilgili geri çağırma çağrıları alır.CreateStub()
'u çağırarakIStub
'ünüzü örneklemek içinIDownloaderClient
arayüzünün bir uygulamasını veDownloaderService
uygulamanızı ona iletmeniz gerekir. İndirme ilerleme durumunu alma ile ilgili bir sonraki bölümde, indirme durumu değiştiğinde etkinlik kullanıcı arayüzünü güncelleyebilmeniz için genellikleActivity
sınıfınızda uygulamanız gerekenIDownloaderClient
arayüzü ele alınmaktadır.startDownloadServiceIfRequired()
indirme işlemini başlattıktan sonra, etkinliğinizinonCreate()
yöntemi sırasındaIStub
'unuzu örneklemek içinCreateStub()
işlevini çağırmanızı öneririz.Örneğin,
onCreate()
için önceki kod örneğindestartDownloadServiceIfRequired()
sonucuna şu şekilde yanıt verebilirsiniz:Kotlin
// Start the download service (if required) val startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired( this@MainActivity, pendingIntent, SampleDownloaderService::class.java ) // If download has started, initialize activity to show progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // Instantiate a member instance of IStub downloaderClientStub = DownloaderClientMarshaller.CreateStub(this, SampleDownloaderService::class.java) // Inflate layout that shows download progress setContentView(R.layout.downloader_ui) return }
Java
// Start the download service (if required) int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this, pendingIntent, SampleDownloaderService.class); // If download has started, initialize activity to show progress if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) { // Instantiate a member instance of IStub downloaderClientStub = DownloaderClientMarshaller.CreateStub(this, SampleDownloaderService.class); // Inflate layout that shows download progress setContentView(R.layout.downloader_ui); return; }
onCreate()
yöntemi döndükten sonra etkinliğinizonResume()
çağrısı alır. Burada,IStub
üzerindeconnect()
'yi çağırarak uygulamanızınContext
değerini iletmeniz gerekir. Buna karşılık, etkinliğinizinonStop()
geri çağırma işlevindedisconnect()
işlevini çağırmanız gerekir.Kotlin
override fun onResume() { downloaderClientStub?.connect(this) super.onResume() } override fun onStop() { downloaderClientStub?.disconnect(this) super.onStop() }
Java
@Override protected void onResume() { if (null != downloaderClientStub) { downloaderClientStub.connect(this); } super.onResume(); } @Override protected void onStop() { if (null != downloaderClientStub) { downloaderClientStub.disconnect(this); } super.onStop(); }
IStub
üzerindeconnect()
çağrısı yaptığınızda etkinliğinizDownloaderService
'ye bağlanır. Böylece etkinliğiniz,IDownloaderClient
arayüzü üzerinden indirme durumundaki değişikliklerle ilgili geri çağırma alır.
İndirme işleminin ilerleme durumu
İndirme ilerleme durumuyla ilgili güncellemeler almak ve DownloaderService
ile etkileşimde bulunmak için İndirici Kitaplığı'nın IDownloaderClient
arayüzünü uygulamanız gerekir.
Genellikle, indirme işlemini başlatmak için kullandığınız etkinlik, indirme ilerleme durumunu görüntülemek ve hizmete istek göndermek için bu arayüzü uygulamalıdır.
IDownloaderClient
için gerekli arayüz yöntemleri şunlardır:
onServiceConnected(Messenger m)
- Etkinliğinizde
IStub
sınıfını örnekledikten sonra bu yönteme bir çağrı alırsınız. Bu çağrı,DownloaderService
örneğinize bağlı birMessenger
nesnesi iletilir. İndirme işlemlerini duraklatma ve devam ettirme gibi hizmete istek göndermek için hizmete bağlıIDownloaderService
arayüzünü almak üzereDownloaderServiceMarshaller.CreateProxy()
numaralı telefonu aramanız gerekir.Önerilen uygulama aşağıdaki gibi görünür:
Kotlin
private var remoteService: IDownloaderService? = null ... override fun onServiceConnected(m: Messenger) { remoteService = DownloaderServiceMarshaller.CreateProxy(m).apply { downloaderClientStub?.messenger?.also { messenger -> onClientUpdated(messenger) } } }
Java
private IDownloaderService remoteService; ... @Override public void onServiceConnected(Messenger m) { remoteService = DownloaderServiceMarshaller.CreateProxy(m); remoteService.onClientUpdated(downloaderClientStub.getMessenger()); }
IDownloaderService
nesnesi başlatıldıktan sonra indirme hizmetine indirme işlemini duraklatma ve devam ettirme (requestPauseDownload()
verequestContinueDownload()
) gibi komutlar gönderebilirsiniz. onDownloadStateChanged(int newState)
- İndirme hizmetinde indirme durumunda bir değişiklik olduğunda (ör. indirme işleminin başlaması veya tamamlanması) bu işlev çağrılır.
newState
değeri,IDownloaderClient
sınıfınınSTATE_*
sabitlerinden biri tarafından belirtilen birkaç olası değerden biri olacaktır.Kullanıcılarınıza faydalı bir mesaj sunmak için
Helpers.getDownloaderStringResourceIDFromState()
işlevini çağırarak her durum için karşılık gelen bir dize isteyebilirsiniz. Bu işlev, İndirici Kitaplığı ile birlikte paketlenen dizelerden birinin kaynak kimliğini döndürür. Örneğin, "Dolaşımdaysanız indirme duraklatıldı" dizesiSTATE_PAUSED_ROAMING
değerine karşılık gelir. onDownloadProgress(DownloadProgressInfo progress)
- İndirme hizmeti, indirme ilerleme kullanıcı arayüzünü güncelleyebilmeniz için bir
DownloadProgressInfo
nesnesi yayınlamak üzere bunu çağırır. Bu nesne, kalan tahmini süre, mevcut hız, genel ilerleme ve toplam dahil olmak üzere indirme ilerleme durumuyla ilgili çeşitli bilgileri açıklar.
İpucu: İndirme ilerleme durumu kullanıcı arayüzünü güncelleyen bu geri çağırmalara ilişkin örnekler için Apk Expansion paketiyle birlikte sağlanan örnek uygulamadaki SampleDownloaderActivity
bölümüne bakın.
IDownloaderService
arayüzü için yararlı bulabileceğiniz bazı herkese açık yöntemler şunlardır:
requestPauseDownload()
- İndirmeyi duraklatır.
requestContinueDownload()
- Duraklatılmış bir indirme işlemini devam ettirir.
setDownloadFlags(int flags)
- Dosya indirilmesine izin verilen ağ türleri için kullanıcı tercihlerini belirler. Mevcut uygulamada bir işaret (
FLAGS_DOWNLOAD_OVER_CELLULAR
) desteklenir ancak başka işaretler de ekleyebilirsiniz. Bu işaret varsayılan olarak etkin değildir. Bu nedenle, kullanıcının genişleme dosyalarını indirmek için kablosuz bağlantı kullanması gerekir. Hücresel ağ üzerinden indirme işlemlerini etkinleştirmek için bir kullanıcı tercihi sunabilirsiniz. Bu durumda şu numaraları arayabilirsiniz:Kotlin
remoteService = DownloaderServiceMarshaller.CreateProxy(m).apply { ... setDownloadFlags(IDownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR) }
Java
remoteService .setDownloadFlags(IDownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR);
APKExpansionPolicy'yi kullanma
Google Play İndirici Kitaplığı'nı kullanmak yerine kendi indirici hizmetinizi oluşturmaya karar verirseniz yine de Lisans Doğrulama Kitaplığı'nda sağlanan APKExpansionPolicy
öğesini kullanmanız gerekir. APKExpansionPolicy
sınıfı, ServerManagedPolicy
ile neredeyse aynıdır (Google Play Lisans Doğrulama Kitaplığı'nda kullanılabilir) ancak APK genişleme dosyası yanıt ekstraları için ek işlemler içerir.
Not: Önceki bölümde açıklandığı gibi Downloader Library'yi kullanıyorsanız kitaplık, APKExpansionPolicy
ile tüm etkileşimi gerçekleştirir. Bu nedenle, bu sınıfı doğrudan kullanmanız gerekmez.
Sınıf, mevcut genişleme dosyaları hakkında gerekli bilgileri almanıza yardımcı olacak yöntemler içerir:
getExpansionURLCount()
getExpansionURL(int index)
getExpansionFileName(int index)
getExpansionFileSize(int index)
İndirici Kitaplığı'nı kullanmadığınızda APKExpansionPolicy
değerini nasıl kullanacağınız hakkında daha fazla bilgi için Uygulamanıza Lisanslama Ekleme dokümanlarına bakın. Bu dokümanlarda, bu tür bir lisans politikasının nasıl uygulanacağı açıklanmaktadır.
Genişletme dosyasını okuma
APK genişletme dosyalarınız cihaza kaydedildikten sonra dosyalarınızı nasıl okuyacağınız, kullandığınız dosya türüne bağlıdır. Genel bakış bölümünde belirtildiği gibi, genişleme dosyalarınız istediğiniz türde olabilir ancak belirli bir dosya adı biçimi kullanılarak yeniden adlandırılır ve <shared-storage>/Android/obb/<package-name>/
'e kaydedilir.
Dosyalarınızı nasıl okuduğunuzdan bağımsız olarak, her zaman önce harici depolama alanının okunabilir olup olmadığını kontrol etmeniz gerekir. Kullanıcının depolama alanını USB üzerinden bir bilgisayara bağlamış veya SD kartı çıkarmış olması mümkündür.
Not: Uygulamanız başladığında, getExternalStorageState()
işlevini çağırarak harici depolama alanının kullanılabilir ve okunabilir olup olmadığını her zaman kontrol etmeniz gerekir. Bu işlev, harici depolama alanının durumunu temsil eden birkaç olası dize arasından birini döndürür. Uygulamanız tarafından okunabilmesi için döndürülen değer MEDIA_MOUNTED
olmalıdır.
Dosya adlarını alma
Genel bakış bölümünde açıklandığı gibi, APK genişletme dosyalarınız belirli bir dosya adı biçimiyle kaydedilir:
[main|patch].<expansion-version>.<package-name>.obb
Genişletme dosyalarınızın konumunu ve adlarını almak için dosyalarınızın yolunu oluşturmak üzere getExternalStorageDirectory()
ve getPackageName()
yöntemlerini kullanmanız gerekir.
Uygulamanızda, her iki genişletme dosyanızın da tam yolunu içeren bir dizi almak için kullanabileceğiniz yöntem aşağıda verilmiştir:
Kotlin
fun getAPKExpansionFiles(ctx: Context, mainVersion: Int, patchVersion: Int): Array<String> { val packageName = ctx.packageName val ret = mutableListOf<String>() if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) { // Build the full path to the app's expansion files val root = Environment.getExternalStorageDirectory() val expPath = File(root.toString() + EXP_PATH + packageName) // Check that expansion file path exists if (expPath.exists()) { if (mainVersion > 0) { val strMainPath = "$expPath${File.separator}main.$mainVersion.$packageName.obb" val main = File(strMainPath) if (main.isFile) { ret += strMainPath } } if (patchVersion > 0) { val strPatchPath = "$expPath${File.separator}patch.$mainVersion.$packageName.obb" val main = File(strPatchPath) if (main.isFile) { ret += strPatchPath } } } } return ret.toTypedArray() }
Java
// The shared path to all app expansion files private final static String EXP_PATH = "/Android/obb/"; static String[] getAPKExpansionFiles(Context ctx, int mainVersion, int patchVersion) { String packageName = ctx.getPackageName(); Vector<String> ret = new Vector<String>(); if (Environment.getExternalStorageState() .equals(Environment.MEDIA_MOUNTED)) { // Build the full path to the app's expansion files File root = Environment.getExternalStorageDirectory(); File expPath = new File(root.toString() + EXP_PATH + packageName); // Check that expansion file path exists if (expPath.exists()) { if ( mainVersion > 0 ) { String strMainPath = expPath + File.separator + "main." + mainVersion + "." + packageName + ".obb"; File main = new File(strMainPath); if ( main.isFile() ) { ret.add(strMainPath); } } if ( patchVersion > 0 ) { String strPatchPath = expPath + File.separator + "patch." + mainVersion + "." + packageName + ".obb"; File main = new File(strPatchPath); if ( main.isFile() ) { ret.add(strPatchPath); } } } } String[] retArray = new String[ret.size()]; ret.toArray(retArray); return retArray; }
Bu yöntemi, uygulamanızı Context
ve istenen genişletme dosyasının sürümünü göndererek çağırabilirsiniz.
Genişleme dosyası sürüm numarasını belirlemenin birçok yolu vardır. Bunun basit bir yolu, APKExpansionPolicy
sınıfının getExpansionFileName(int index)
yöntemiyle genişleme dosyası adını sorgulayıp indirme işlemi başladığında sürümü bir SharedPreferences
dosyasına kaydetmektir. Ardından, uzantı dosyasına erişmek istediğinizde SharedPreferences
dosyasını okuyarak sürüm kodunu alabilirsiniz.
Paylaşılan depolama alanından veri okuma hakkında daha fazla bilgi için Veri Depolama belgelerine bakın.
APK Genişletme Sıkıştırılmış Kitaplığını Kullanma
Google Market Apk Genişletme paketi, APK Genişletme Zip Kitaplığı (<sdk>/extras/google/google_market_apk_expansion/zip_file/
konumunda) adlı bir kitaplık içerir. Bu, ZIP dosyası olarak kaydedilen genişletme dosyalarınızı okumanıza yardımcı olan isteğe bağlı bir kitaplıktır. Bu kitaplığı kullanarak ZIP uzantı dosyalarınızdaki kaynakları sanal dosya sistemi olarak kolayca okuyabilirsiniz.
APK Genişleme Zip Kitaplığı aşağıdaki sınıfları ve API'leri içerir:
APKExpansionSupport
- Genişletme dosyası adlarına ve ZIP dosyalarına erişmek için bazı yöntemler sağlar:
getAPKExpansionFiles()
- Yukarıdaki yöntemin aynısı. Bu yöntem, her iki uzantı dosyasının da tam dosya yolunu döndürür.
getAPKExpansionZipFile(Context ctx, int mainVersion, int patchVersion)
- Hem ana dosyanın hem de düzeltme dosyasının toplamını temsil eden bir
ZipResourceFile
döndürür. Yani hemmainVersion
hem depatchVersion
'ü belirtirseniz bu, tüm verilere okuma erişimi sağlayan birZipResourceFile
döndürür. Bu durumda, yama dosyasının verileri ana dosyanın üzerine birleştirilir.
ZipResourceFile
- Ortak depolama alanındaki bir ZIP dosyasını temsil eder ve ZIP dosyalarınıza dayalı sanal bir dosya sistemi sağlamak için tüm işlemleri gerçekleştirir.
APKExpansionSupport.getAPKExpansionZipFile()
kullanarak veyaZipResourceFile
ile genişleme dosyanızın yolunu ileterek bir örnek alabilirsiniz. Bu sınıf çeşitli yararlı yöntemler içerir ancak genellikle bunların çoğuna erişmeniz gerekmez. Birkaç önemli yöntem şunlardır:getInputStream(String assetPath)
- ZIP dosyasındaki bir dosyayı okumak için bir
InputStream
sağlar.assetPath
, ZIP dosyası içeriğinin köküne göre istenen dosyanın yolu olmalıdır. getAssetFileDescriptor(String assetPath)
- ZIP dosyasındaki bir dosya için
AssetFileDescriptor
sağlar.assetPath
, ZIP dosyası içeriğinin köküne göre istenen dosyanın yolu olmalıdır. Bu, bazıMediaPlayer
API'leri gibiAssetFileDescriptor
gerektiren belirli Android API'leri için kullanışlıdır.
APEZProvider
- Çoğu uygulamanın bu sınıfı kullanması gerekmez. Bu sınıf, medya dosyalarına
Uri
erişim bekleyen belirli Android API'leri için dosya erişimi sağlamak amacıyla ZIP dosyalarındaki verileri bir içerik sağlayıcıUri
aracılığıyla düzenleyen birContentProvider
tanımlar. Örneğin,VideoView.setVideoURI()
ile bir video oynatmak istiyorsanız bu özellikten yararlanabilirsiniz.
Medya dosyalarının ZIP sıkıştırmasını atlama
Medya dosyalarını depolamak için genişletme dosyalarınızı kullanıyorsanız ZIP dosyası, ofset ve uzunluk kontrolleri sağlayan Android medya oynatma çağrılarını (MediaPlayer.setDataSource()
ve SoundPool.load()
gibi) kullanmanıza yine de olanak tanır. Bunun işe yaraması için ZIP paketlerini oluştururken medya dosyalarında ek sıkıştırma işlemi gerçekleştirmemeniz gerekir. Örneğin, zip
aracını kullanırken sıkıştırılmaması gereken dosya uzantılarını belirtmek için -n
seçeneğini kullanmanız gerekir:
zip -n .mp4;.ogg main_expansion media_files
ZIP dosyasından okuma
APK Genişletme Zip Kitaplığı kullanılırken ZIP'inizdeki bir dosyayı okumak için genellikle aşağıdakiler gerekir:
Kotlin
// Get a ZipResourceFile representing a merger of both the main and patch files val expansionFile = APKExpansionSupport.getAPKExpansionZipFile(appContext, mainVersion, patchVersion) // Get an input stream for a known file inside the expansion file ZIPs expansionFile.getInputStream(pathToFileInsideZip).use { ... }
Java
// Get a ZipResourceFile representing a merger of both the main and patch files ZipResourceFile expansionFile = APKExpansionSupport.getAPKExpansionZipFile(appContext, mainVersion, patchVersion); // Get an input stream for a known file inside the expansion file ZIPs InputStream fileStream = expansionFile.getInputStream(pathToFileInsideZip);
Yukarıdaki kod, her iki dosyanın da tüm dosyalarının birleştirilmiş bir haritasından okuyarak ana genişletme dosyanızda veya yama genişletme dosyanızda bulunan herhangi bir dosyaya erişim sağlar. getAPKExpansionFile()
yöntemini kullanırken uygulamanız android.content.Context
ve hem ana genişletme dosyasının hem de yama genişletme dosyasının sürüm numarasını sağlamanız yeterlidir.
Belirli bir genişletme dosyasından okumak isterseniz ZipResourceFile
kurucusunu, istediğiniz genişletme dosyasının yoluyla birlikte kullanabilirsiniz:
Kotlin
// Get a ZipResourceFile representing a specific expansion file val expansionFile = ZipResourceFile(filePathToMyZip) // Get an input stream for a known file inside the expansion file ZIPs expansionFile.getInputStream(pathToFileInsideZip).use { ... }
Java
// Get a ZipResourceFile representing a specific expansion file ZipResourceFile expansionFile = new ZipResourceFile(filePathToMyZip); // Get an input stream for a known file inside the expansion file ZIPs InputStream fileStream = expansionFile.getInputStream(pathToFileInsideZip);
Genişleme dosyalarınız için bu kitaplığı kullanma hakkında daha fazla bilgi edinmek isterseniz CRC kullanarak indirilen dosyaları doğrulamak için ek kod içeren örnek uygulamanın SampleDownloaderActivity
sınıfına bakın. Bu örneği kendi uygulamanızın temeli olarak kullanırsanız xAPKS
dizisinde genişleme dosyalarınızın bayt boyutunu belirtmeniz gerektiğini unutmayın.
Genişletme dosyalarınızı test etme
Uygulamanızı yayınlamadan önce iki şeyi test etmeniz gerekir: Genişletme dosyalarını okuma ve dosyaları indirme.
Dosya okuma işlemlerini test etme
Uygulamanızı Google Play'e yüklemeden önce, uygulamanızın paylaşılan depolama alanınızdaki dosyaları okuma özelliğini test etmeniz gerekir. Tek yapmanız gereken, dosyaları cihazın paylaşılan depolama alanındaki uygun konuma eklemek ve uygulamanızı başlatmaktır:
- Cihazınızda, Google Play'in dosyalarınızı kaydedeceği paylaşılan depolama alanında uygun dizini oluşturun.
Örneğin, paket adınız
com.example.android
ise paylaşılan depolama alanındaAndroid/obb/com.example.android/
dizinini oluşturmanız gerekir. (Paylaşılan depolama alanını bağlamak ve bu dizini manuel olarak oluşturmak için test cihazınızı bilgisayarınıza takın.) - Genişletme dosyalarını bu dizine manuel olarak ekleyin. Dosyalarınızı, Google Play'in kullanacağı dosya adı biçimine uyacak şekilde yeniden adlandırdığınızdan emin olun.
Örneğin, dosya türünden bağımsız olarak
com.example.android
uygulamasının ana genişletme dosyasımain.0300110.com.example.android.obb
olmalıdır. Sürüm kodu istediğiniz herhangi bir değer olabilir. Şunu unutmayın:- Ana genişletme dosyası her zaman
main
ile başlar ve yama dosyasıpatch
ile başlar. - Paket adı, dosyanın Google Play'de eklendiği APK ile her zaman eşleşir.
- Ana genişletme dosyası her zaman
- Genişletme dosyaları cihaza yüklendikten sonra, genişletme dosyalarınızı test etmek için uygulamanızı yükleyip çalıştırabilirsiniz.
Genişleme dosyalarını işlemeyle ilgili bazı hatırlatmalar:
.obb
genişleme dosyalarını silmeyin veya yeniden adlandırmayın (verileri farklı bir konuma açsanız bile). Bunu yaptığınızda Google Play (veya uygulamanız) genişletme dosyasını tekrar tekrar indirir.obb/
dizininize başka veri kaydetmeyin. Bazı verileri açmanız gerekiyorsagetExternalFilesDir()
tarafından belirtilen konuma kaydedin.
Dosya indirmelerini test etme
Uygulamanız bazen ilk açıldığında genişletme dosyalarını manuel olarak indirmesi gerektiğinden, uygulamanızın URL'leri başarıyla sorgulayabileceğinden, dosyaları indirip cihaza kaydedebileceğinden emin olmak için bu süreci test etmeniz önemlidir.
Uygulamanızın manuel indirme prosedürünü uygulama şeklini test etmek için uygulamanızı dahili test kanalına yayınlayarak yalnızca yetkili test kullanıcılarının kullanımına sunabilirsiniz. Her şey beklendiği gibi giderse uygulamanız, ana etkinlik başlar başlamaz genişletme dosyalarını indirmeye başlar.
Not: Daha önce, yayınlanmamış bir "taslak" sürümü yükleyerek uygulamaları test edebiliyordunuz. Bu işlev artık desteklenmemektedir. Bunun yerine, dahili, kapalı veya açık bir test kanalında yayınlamanız gerekir. Daha fazla bilgi için Taslak Uygulamalar Artık Desteklenmiyor başlıklı makaleyi inceleyin.
Uygulamanızı güncelleme
Google Play'de genişletme dosyalarını kullanmanın en büyük avantajlarından biri, orijinal öğelerin tümünü yeniden indirmeden uygulamanızı güncelleyebilmenizdir. Google Play, her APK ile iki genişletme dosyası sağlamanıza izin verdiğinden ikinci dosyayı güncellemeler ve yeni öğeler sağlayan bir "yama" olarak kullanabilirsiniz. Bu sayede, kullanıcılar için büyük ve pahalı olabilecek ana genişleme dosyasını yeniden indirmeniz gerekmez.
Yama genişletme dosyası teknik olarak ana genişletme dosyasıyla aynıdır ve Android sistemi veya Google Play, ana ve yama genişletme dosyalarınız arasında gerçek yamalama işlemi gerçekleştirmez. Uygulama kodunuz gerekli tüm yamaları kendisi yapmalıdır.
Genişletme dosyalarınız olarak ZIP dosyaları kullanıyorsanız APK Genişletme paketine dahil olan APK Genişletme Zip Kitaplığı, yama dosyanızı ana genişletme dosyasıyla birleştirme olanağı sunar.
Not: Yalnızca yamanın genişletilmiş dosyasında değişiklik yapmanız gerekse bile Google Play'in güncelleme yapabilmesi için APK'yı güncellemeniz gerekir.
Uygulamada kod değişikliği yapmanız gerekmiyorsa manifest dosyasında versionCode
öğesini güncellemeniz yeterlidir.
Play Console'da APK ile ilişkili ana genişletme dosyasını değiştirmediğiniz sürece, uygulamanızı daha önce yüklemiş olan kullanıcılar ana genişletme dosyasını indirmez. Mevcut kullanıcılara yalnızca güncellenmiş APK ve yeni yama genişletme dosyası (önceki ana genişletme dosyası korunur) gönderilir.
Genişleme dosyalarındaki güncellemelerle ilgili göz önünde bulundurulması gereken birkaç nokta aşağıda verilmiştir:
- Uygulamanız için tek seferde yalnızca iki genişletme dosyası olabilir. Bir ana genişletme dosyası ve bir yama genişletme dosyası. Google Play, bir dosyada güncelleme yapılırken önceki sürümü siler (manuel güncellemeler yapılırken uygulamanızın da bunu yapması gerekir).
- Android sistemi, yama genişletme dosyası eklendiğinde uygulamanızı veya ana genişletme dosyanızı yamamaz. Uygulamanızı, yama verilerini destekleyecek şekilde tasarlamanız gerekir. Ancak Apk genişletme paketi, ZIP dosyalarını genişletme dosyası olarak kullanmaya yönelik bir kitaplık içerir. Bu kitaplık, yama dosyasındaki verileri ana genişletme dosyasıyla birleştirir. Böylece, tüm genişletme dosyası verilerini kolayca okuyabilirsiniz.