Android stüdyo modülü için ayrı apk. Android Studio her modül için APK yükler

Android Studio v 0.3.2'de Gradle ile oluşturulmuş bir projem var. Projemin diğer iki modüle (kütüphane) bağımlılığı var. Proje yapısı build.gradle dosyaları kullanılarak iyi tanımlanmıştır. Sorun şu ki... Android cihazda bir proje çalıştırdığımda cihazıma 3 tane yüklüyorum. Bunlardan biri ana proje (tek doğru olan) ve diğer ikisi ithal modüller (bu ikisini kurmak istemiyorum). Bunu nasıl başarabilirim? Veya neyi yanlış yapıyorum?

Proje yapısı:

  • MyLibModül
  • Ana Proje
  • MainProject->kütüphaneler-> MyOtherModule

Nerede MyLibModül ana projeyle aynı yolda çünkü bu modüle başka bir projede de ihtiyacım var.

Sadece açık olmak gerekirse: hepsi toplantı proje sırayla, tüm bağımlılıklar sorun değil ama neden cihazımda 3 APK alıyorum?

Bütün bir gün boyunca bu problemle uğraştıktan sonra bu garip davranışın sebebini buldum. Sorun kütüphane modülünün tezahüründeydi. Android stüdyosuna geçmeden önce Eclipse kullanıyordum. Ve kütüphane proje bildiriminde testActivity'yi ilan ettim. Tüm manifest test eylemlerinin kitaplık modüllerimden kaldırılması sorunu çözdü. Android Studio artık yalnızca MainProject APK'sını yüklüyor.

Bazı kodlar: MyLibModule bildirimi:

Şuna değiştirildi:

…. MyOtherModule için de aynı şey geçerli.

NOT. Boş düğüm uygulamalar derleme hatalarını önlemek için bildirimde kalmalıdır.

Kitaplığınızı çalıştırmaktan amaç filtresini kaldırın

Şuna değiştirildi:

Bunun nedeni kütüphanelerinizin build.gradle dosyalarınızda kütüphaneler olarak değil uygulamalar olarak tanımlanmış olmasıdır. Şu satıra bakın:

Eklentiyi uygula: "android"

Ve şununla değiştirin:

Eklentiyi uygula: "android-library"

Uygulamaya özel olan her şey kitaplık derleme dosyasında belirtilemeyeceğinden, derleme dosyasında başka değişiklikler yapmanız gerekebilir. Daha fazla bilgi için http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Library-projects adresine bakın.

Eklentiler ve modüler uygulamalardan bahsettiğimizde öncelikle sıradan kullanıcı yazılımlarını kastediyoruz. Ancak modüler tasarım, rootkit'leri ve arka kapıları geliştirirken de aynı derecede faydalı olabilir. Bu tür bir yazılımı güncellemek için geleneksel yöntemleri kullanmak çok zahmetlidir ve her zaman mümkün değildir, ancak bir modülün fark edilmeyecek şekilde yüklenmesi yeni işlevsellik ağ üzerinden - bu hoş bir şey. Ve anahtar işlevleri modüllere taşırsanız ve bunları yüklemeden hemen sonra silerseniz, ters çeviricinin ömrünü ciddi şekilde mahvedebilirsiniz.

Tanıtmak yerine

Klasik Java'da java.lang.ClassLoader adında bir sınıf vardır. Görevi, uygulamanın yürütülmesi sırasında belirtilen sınıfın bayt kodunu (.class uzantılı bir dosya) sanal makineye yüklemektir. Daha sonra bu sınıftan bir nesne oluşturabilir ve yansımayı kullanarak onun yöntemlerini çağırabilirsiniz. Bu, genişletilebilir işlevselliğe sahip uygulamalar yazmak veya daha basit bir ifadeyle eklenti desteği sağlamak için kullanılabilecek dinamik olarak kod yükleme yöntemidir.

Android'de değil sanal makine Java'nın ClassLoader sınıfı yoktur, ancak tam olarak aynı işlevi yerine getiren analogu DexClassLoader vardır, ancak Dalvik bayt koduyla (ve sırasıyla .class yerine .dex dosyalarıyla) ilişkilidir. Ve gerekli jar dosyasını CLASSPATH'e yerleştirmenin daha kolay olduğu ve dinamik yüklemeyle uğraşmanın daha kolay olduğu masaüstü Java'nın aksine, Android'de bu yaklaşım gerçekten birçok avantaj sağlar; bunlardan en önemlisi, uygulamanın işlevselliğinin genişletilebilmesi ve kullanıcı tarafından fark edilmeden ve ona hiçbir şey sorulmadan güncellenir. Uygulamanız herhangi bir zamanda sunucudan sınıf içeren bir dosyayı indirebilir, yükleyebilir ve ardından dosyayı silebilir.

Ayrıca sınıflar doğrudan APK paketinde saklanabilir ve uygulama başlatıldığında indirilebilir. Buradaki fayda, yüklenen sınıfların kodunun uygulamanın kendi kodundan ayrılacak ve yanlış APK'da yer alacak olmasıdır; Kullanmayı sevenleri tersine çeviren apktool gibi araçlar görülmeyecek. Öte yandan, normal bir ters çevirici neyin ne olduğunu hızlı bir şekilde anlayacağından, bu oldukça kusursuzdur.

Her ne olursa olsun, dinamik sınıf yükleme tamamen "beyaz" olmayan uygulamalar yazarken çok yararlı bir şeydir; bu nedenle herhangi bir güvenlik uzmanı bu mekanizmanın nasıl çalıştığını ve Truva atlarında nasıl kullanıldığını bilmelidir.

En basit örnek

// Sınıfımızı içeren jar arşivinin yolu String modFile = "/sdcard/myapp/module.jar"; // Özel uygulama dizininin yolu String appDir = getApplicationInfo().dataDir; // Dosyayı diskten yükleyin DexClassLoader classLoader = new DexClassLoader(modFile, appDir, null, getClass().getClassLoader()); // Sınıfı yükleyin, bir nesne oluşturun ve yansımayı kullanarak run() yöntemini çağırmayı deneyin try ( Class c = classLoader.loadClass("com.example.modules.simple.Module"); Method m = c.getMethod(" run", null); m.invoke(c.newInstance(), null); catch (Exception e) ( e.printStackTrace(); )

Genel olarak, burada her şey basit: kod, sınıfımızla birlikte /sdcard/myapp/module.jar jar arşivini yükler, buradan com.example.modules.simple.Module sınıfını yükler, bir nesne oluşturur ve run() öğesini çağırır. yöntem. Üç noktaya dikkat edin:

  • DexClassLoader hem "sadece" .dex dosyalarını hem de jar arşivlerini yükleyebilir; sıkıştırma ve dijital imza kullanma yeteneği nedeniyle ikincisi tercih edilir;
  • DexClassLoader yapıcısının ikinci argümanı, optimize edilmiş bayt kodunu (odex) depolamak için kullandığı dizindir; basitlik sağlamak amacıyla uygulamanın kendisinin özel dizinini belirtiriz;
  • loadClass yöntemi, loadClass yöntemine argüman olarak her zaman paket adının yanı sıra sınıf adresini de içermelidir.

Bu kodu işlevsellik açısından test etmek için basit bir modül oluşturalım:

Paket com.example.modules.simple.Module; android.util.Log'u içe aktar; public class Modül ( public void run() ( Log.d("Module", "Ben hayattayım!!!"); ) )

Android Studio'da yeni bir proje oluşturmak için acele etmeyin; bu kodu Notepad'e yazıp doğrudan komut satırından bir jar arşivinde derleyebilirsiniz:

Javac -classpath /path/to/SDK/platforms/android-23/android.jar Module.java /path/to/SDK/build-tools/23.0.3/dx --dex --output=module.jar Modülü. sınıf

Platformlar/android-23 ve build-tools/23.0.3 dizinlerinin mevcut olduğundan emin olun, sizin durumunuzda adları farklı olabilir.

Her şey yolunda giderse çıktı olarak bir module.jar dosyası alacaksınız. Geriye kalan tek şey, önyükleyici kodunu uygulamaya eklemek, module.jar'ı hafıza kartına koymak, uygulamayı oluşturup çalıştırmaktır.

Aşağı yansıma

Düşünmek iyi bir şeydir ama bu durumda sadece engel oluyor. Onun yardımıyla argümansız bir yöntemi çağırmak zor değil, ancak uygulamamızın birçok parametre alan birçok yöntemle zengin bir modül API'sine sahip olmasını istiyorsak daha kullanışlı bir şey bulmamız gerekiyor. Örneğin, her modülün uygulayacağı önceden tanımlanmış bir arayüz kullanın.

Bu yaklaşımı yukarıdaki örneğe uyguladığımızda aşağıdaki üç dosyayı elde ederiz:

  1. API açıklamasını içeren ModuleInterface.java dosyası: package com.example.modules; genel arayüz ModuleInterface ( public void run(); )
  2. Modülümüzün uygulanmasını içeren Module.java dosyası: package com.example.modules.simple.Module; android.util.Log'u içe aktar; public class Module, ModuleInterface'i uygular ( public void run() ( Log.d("Module", "I am hayatta!!!"); ) )
  3. Yeni modül yükleyici (uygulamanıza yerleştirin): String modFile = "/sdcard/myapp/module.jar"; String appDir = getApplicationInfo().dataDir; DexClassLoader classLoader = new DexClassLoader(modFile, appDir, null, getClass().getClassLoader()); // Sınıfı yükleyin ve ModuleInterface ModuleInterface modülü ile bir nesne oluşturun; deneyin ( Sınıfclass = classLoader.loadClass("com.example.modules.simple.Module"); modül = (ModuleInterface) class.newInstance(); ) catch (Exception e) ( e.printStackTrace(); ) module.run()

Hepsi bu. Artık modülle normal bir nesneyle çalışır gibi çalışabiliriz. Üstelik arayüz ile uyumsuz olan modülleri (sınıfları) sistem kendisi yükleme aşamasında reddedecektir, dolayısıyla modülün ihtiyacımız olan yöntemi içerip içermediğini kendimize sormamıza gerek kalmaz.

Çok sayıda modül olduğunda

Bir modülü ayırdık ama ya çok sayıda varsa? Bu modülleri nasıl takip edebilir ve aralarında kaybolmazsınız? Aslında çok basit; bunun için bir hashmap kullanabilirsiniz. Önyükleyiciyi tekrar değiştirelim:

Devamı yalnızca üyelere açıktır

Seçenek 1. Sitedeki tüm materyalleri okumak için "site" topluluğuna katılın

Belirtilen süre içinde topluluğa üye olmak, TÜM Hacker materyallerine erişmenizi sağlayacak, kişisel kümülatif indiriminizi artıracak ve biriktirmenize olanak tanıyacaktır. profesyonel derecelendirme Xakep Skoru!

Son zamanlarda Google G/Ç 2018 birçok yeniliğin yanı sıra yeni bir başvuru formatının da eklendiğini duyurdu.

Bu format denir Android uygulaması Paket ve uygulamanızı oluşturmanın geliştirilmiş bir yolunu temsil eder. Onun yardımıyla, kodda herhangi bir değişiklik yapmaya gerek kalmadan uygulamanın boyutunu kolayca optimize edebilirsiniz. Android App Bundle, derlenmiş tüm kodu ve kaynakları içerir ve ardından belirli bir cihazın ihtiyaç duymadığı şeyleri filtreler.

Önemli! Açık şu an Android App Bundle yalnızca Android Studio'nun önizleme sürümünde çalışır. En son sürüm Android Studio 3.2 Kanarya mevcut .

Android biçimi Uygulama Paketi

Android App Bundle bir dosyadır (uzantısına sahip) .aab), Google'a yüklenir. Her paket, tüm uygulama modülleri ve desteklenen cihaz yapılandırmaları için derlenmiş kod ve kaynakları içerir.

Basitçe söylemek gerekirse paketler, uygulama kodunu ve kaynakları modüller halinde düzenleyen imzalı ZIP dosyalarıdır.

Bu modüllerden Google Oyun kullanıcılara sağlanan temel APK'lar, dinamik özellik APK'ları, yapılandırma APK'ları ve (bölünmüş APK'ları desteklemeyen cihazlar için) çoklu APK'lar gibi çeşitli APK'lar oluşturur. Kataloglar renklendirildi Mavi renk, Google Play'in her modül için yapılandırma APK'sını oluşturmak için kullandığı kodu ve kaynakları temsil eder.

Not: her benzersiz uygulama için bir paket oluşturulmalı veya Uygulama Kimliği. Yani, farklı APK'lar oluşturmak için uygulamanızda birden fazla ürün çeşidi kullanıyorsanız ve bu dalların her biri benzersiz bir uygulama kimliği kullanıyorsa her dal için ayrı bir paket oluşturmanız gerekecektir.

Her modülün kodu ve kaynakları standart APK'lara benzer şekilde düzenlenmiştir; bu, bu modüllerin her birinin ayrı bir APK olarak oluşturulabilmesi nedeniyle mantıklıdır. Aşağıda daha fazlasını görebilirsiniz Detaylı Açıklama bazı dosyalar ve Android dizinleri Uygulama Paketi:

  • temel/, özellik1/, özellik2/. Bu dizinlerin her biri bir uygulama modülünü temsil eder. Temel uygulama modülü her zaman temel paket dizininde bulunur. Her birine özel bir ad verilen ek özelliklere sahip dizinler ayrı ayrı bulunur.
  • Dosyalar Protokol Arabelleği (.pb). Bu dosyalar, uygulama mağazalarındaki paketin içeriğini tanımlamaya yardımcı olan meta veriler içerir. Örneğin, BundleConfig.pb Paketin kök dizininde bulunan, paketin kendisi hakkında bilgi sağlar; örneğin hangi sürüm? inşa araçları montaj için kullanılır. Gibi diğer dosyalar başvuru.pb Ve yerli.pb, belirli kod ve kaynakların nasıl kullanılması gerektiğini açıklayın çeşitli konfigürasyonlar cihazlar. Google Play bu bilgileri kullanıcının cihazı için optimize edilmiş bir APK oluşturmak için kullanır.
  • belirgin/. APK'lardan farklı olarak paketler, her modülün AndroidManifest.xml dosyasını ayrı bir dizinde saklar.
  • deks/. APK'lardan farklı olarak paketler, her modülün DEX dosyalarını ayrı bir dizinde saklar.
  • kök/. Bu dizin daha sonra dizine taşınan dosyaları saklar kök bu dizini içeren bir modül içeren herhangi bir APK. Örneğin, dizin taban/kök/ bir paket, uygulama tarafından yüklenen Java kaynaklarını içerebilir. Class.getResources(). Bu dosyalar daha sonra uygulamanın kök APK dizinine ve Google Play'in oluşturduğu her bir çoklu APK'ya taşınır. Bu dizindeki yollar da korunur, yani alt dizinler de kökle birlikte taşınır.
    Not: Bu dizinin içeriği APK'nın kökündeki diğer dosya ve dizinlerle çakışırsa Play Console paketin indirilmesini reddeder. Örneğin, root/lib/ dizinini ekleyemezsiniz çünkü bu, APK'da zaten bulunan lib dizini ile çakışacaktır.
  • res/, lib/, varlıklar/. Bu dizinler standart APK'da kullanılanlarla aynıdır. Bir uygulamayı indirdiğinizde, Google Play yalnızca bu dizinlerdeki ve paketlerdeki hedef cihazın yapılandırmasıyla eşleşen dosyaları kontrol eder.

Şununla Uygulama Paketi Oluşturun: Android'i kullanma Stüdyo

Android Studio'yu kullanarak paket oluşturmak, APK oluşturmaya çok benzer. Montaj için menüden seçim yapmanız yeterli Derle - Paket(ler)/APK(lar) Oluştur > Paket(ler) Oluştur ve IDE seçilen derleme seçeneği için bir paket oluşturacak ve onu dizine yerleştirecektir //derleme/çıktılar/paket/.

Uygulamanın hata ayıklama sürümü için bir paket oluşturulursa Android Studio, hata ayıklama imzalama anahtarını kullanarak paketi otomatik olarak imzalayacaktır. Bir paketi Google Play'e yüklemek için paketin imzalanması gerekir.

Android Studio imzalı paketi oluşturmayı tamamladıktan sonra paket açılabilir ve analiz edilebilir. Paket analizi, içerikleri kontrol etmenize olanak tanır ve benzer şekilde çalışır APK Analizörü.

İçin Uygulama oluşturma Bundle IDE, open ile aynı aracı kullanır kaynak kodu, isminde paket aracı Google Play bunu daha sonra paketi imzalı APK'lara dönüştürmek için kullanır.

Bir paketi Google Play konsoluna yüklemeden önce imzalamanız gerekir. İmzalı bir App Bundle oluşturmak için şu adımları uygulamanız gerekir:


Android Studio imzalı paketi oluşturmayı tamamladıktan sonra, bildirimde uygun seçenek seçilerek paket bulunabilir ve analiz edilebilir. İmza anahtarını dışa aktarmayı seçtiyseniz sağdaki aşağı oka tıklayarak hızlı bir şekilde bu anahtara gidebilirsiniz. alt köşe genişletmek için bildirimi tost edin ve ardından seçin Dışa Aktarılan Anahtar Dosyasını Göster.

Google Play Console'a Uygulama Paketi Yükleme

Paket oluşturulduktan sonra uygulamayı incelemek, test etmek veya yayınlamak için Google Play'e yüklenebilir. Çalışmaya başlamadan önce aşağıdaki koşulların karşılanması gerekir:

  1. Programa kaydolun Google Play Uygulama İmzalama.
  2. Uygulama dinamik özellik modülleri içeriyorsa Google Play konsolunun dahili test kanalı aracılığıyla indirilebilir ve test edilebilir. Ancak uygulamanızı yayınlamak için şu anda beta aşamasında olan Dinamik Özellik programını kabul etmeniz gerekir.
  3. Google Play, en büyük uygulama indirme işlemlerini destekler 100 MB.

Explorer Kullanarak APK Analizi

Paket indirildiğinde Google Play, uygulama tarafından desteklenen tüm cihaz yapılandırmaları için otomatik olarak bölünmüş APK'lar ve çoklu APK'lar oluşturur. Play Console'da, Google Play tarafından oluşturulan tüm APK çeşitlerini görüntülemek için App Bundle Explorer'ı kullanabilirsiniz; desteklenen cihazlar ve APK boyutunda tasarruf gibi veri analizi; Test için oluşturulan APK indiriliyor.

Uygulama güncellemesi

Uygulamayı Play Console'a yükledikten sonra uygulamayı güncellemek için sürüm kodunu yükseltmeniz ve yeni bir paket oluşturup yüklemeniz yeterlidir. Google Play daha sonra yeni sürüm koduyla güncellenmiş APK'lar oluşturacak ve gerektiğinde bunları sağlayacaktır.

Çözüm

Android App Bundle'ı kullanmak, APK uygulamalarını optimize etmek için büyük avantajlar sağlar. Bu yöntemi kullanarak uygulamalarımızdan biri olan “Wi-Fi Ağ Şifre Yöneticisi”ni standart APK'sını bir App Bundle ile değiştirerek güncelledik. Yani boyut APK dosyaları tam bir megabayt azaldı, bu çok iyi bir sonuç.

Buna ek olarak, Google şu anda App Bundle'a, temel APK'yı gerekirse indirilecek parçalara bölebileceğiniz Dinamik özellik modüllerine bir eklemeyi test ediyor, şu ana kadar bu teknoloji beta aşamasındadır.

Belki şu anda paketlerin tek dezavantajı Android Studio'nun önizleme sürümünü kullanma ihtiyacıdır, ancak bu sorun geçicidir.

İçinde bir modül oluşturmak için Android Stüdyosu seçmek

Dosya > Yeni > Yeni Modül

Daha sonra 2 seçenek var. "Saf" bir Java kitaplığı oluşturmayı planlıyorsanız, şunu belirtin: Java Kütüphanesi sonuç olarak böyle bir kütüphanenin kodu derlenecek KAVANOZ dosya. Bu uygundur, çünkü onu yalnızca Android uygulamaları. Android'e özgü şeyler kullanacaksanız ve Android.* paketlerinden sınıflara ihtiyacınız varsa, o zaman şunu oluşturun: Android Kitaplığı derlendiğinde derlenir AAR dosya. Bu durumda son seçeneğe ihtiyacınız olacak.

ÖNEMLİ: Uygulamanın minSDKVersion'ı (modüllerin build.gradle dosyaları), kütüphane modülünde belirtilene eşit veya bundan büyük olmalıdır. Belirtilen buildToolsVersion, Android SDK'ya yüklenmelidir. Her kütüphane modülü kendi kaynak sınıfını (*.R.class) oluşturur. Bir projeye Android kitaplıkları eklendiğinde ve proje oluşturulduğunda kaynakları birleştirilir ve bu da çatışmalara yol açabilir. Bu nedenle, belgeler aşağıdaki kuralları tanımlar:

  • Uygulama kaynağı kimliği kitaplıktaki kaynak kimliğiyle eşleşiyorsa uygulama kaynağı kullanılır
  • Kaynak kimliği eşleşiyorsa farklı kütüphaneler, daha sonra bağımlılıklar listesinde ilk olarak listelenen kütüphane kaynağı kullanılır (yukarıdaki bağımlılıklar bloğunda bulunur)
  • Yukarıda açıklanan çelişkileri önlemek için, her modül için benzersiz (veya uygulamanın tamamı için benzersiz) olacak bir önek veya diğer tutarlı kaynak adlandırma şemasının kullanılması önerilir.

Android kitaplıklarını bağlama

Android kitaplıkları bağımlılıklar olarak dahil edilir (kitaplık AndroidStudio'da ayrı bir proje olarak oluşturulduysa). Ayrıca 2 seçenek vardır:

1. Veya derlenmiş AAR (veya JAR) dosyasını ekleyin:

Dosya > Yeni Modül - .JAR/.AAR Paketini İçe Aktar > Sonraki - ARR (veya JAR) dosyasının yolunu girin > Son

2. Veya kütüphaneyi kaynaktan içe aktarın:

Dosya > Yeni > Modülü İçe Aktar - kitaplık kaynaklarının bulunduğu dizinin yolunu girin > Son

ÖNEMLİ: Android kitaplığı adının eklendiğinden emin olun ayarlar.gradle

":app", ":core", ":personal", ":client"'i ekleyin

ve dosyanın bağımlılıklar bloğunda göründü build.gradle uygulamalar

Bağımlılıklar ( projeyi derle(":core") projeyi derle(":kişisel") projeyi derle(":istemci") )

Android kitaplıkları kaynakları, diğer JAR kitaplıklarını ve kendilerine ait kaynakları içerebilir. AndroidManifest.xml.

Derlenmiş Android kütüphanesinin yapısı

Derlenmiş Android kitaplığı ortak bir şey zip arşivi Aşağıdaki gerekli dosya ve dizinleri içeren .arr uzantılı:

  • /AndroidManifest.xml
  • /sınıflar.jar
  • /res/
  • /R.txt

ve isteğe bağlı:

  • /varlıklar/
  • /lib'ler/ isim.kavanoz
  • /jni/ abi_name/isim.yani (nerede abi_name desteklenen Android ABI'lerinden biri)
  • /proguard.txt
  • /lint.jar