Kurtarma sistemi, cihaza özel kod eklemek için birçok kanca içerir. Böylece OTA Güncellemeler, cihazın Android sistemi dışında bazı bölümlerini de (ör. ana bant) güncelleyebilir veya radyo işlemcisi).
Aşağıdaki bölümler ve örneklerde, Search Ads 360 tarafından üretilen tardis yoyodyne tedarikçi firmasıyla iletişime geçebilirsiniz.
Bölüm haritası
Android 2.3 sürümünden itibaren platform, eMMc flash cihazları ve kullanıyor. Ayrıca, Bellek Teknolojisi Cihazı (MTD) flash cihazları ve yaffs2 dosya sistemini kullanır.
Bölüm harita dosyası TARGET_RECOVERY_FSTAB tarafından belirtilir; hem ve paket oluşturma araçlarını ele alacağız. Harita dosyasının adını BoardConfig.mk içinde TARGET_RECOVERY_FSTAB.
Örnek bir bölüm haritası dosyası aşağıdaki gibi görünebilir:
device/yoyodyne/tardis/recovery.fstab
# mount point fstype device [device2] [options (3.0+ only)] /sdcard vfat /dev/block/mmcblk0p1 /dev/block/mmcblk0 /cache yaffs2 cache /misc mtd misc /boot mtd boot /recovery emmc /dev/block/platform/s3c-sdhci.0/by-name/recovery /system ext4 /dev/block/platform/s3c-sdhci.0/by-name/system length=-4096 /data ext4 /dev/block/platform/s3c-sdhci.0/by-name/userdata
İsteğe bağlı olan /sdcard
hariç, bu
örnek tanımlanmalıdır (cihazlar ekstra bölümler de ekleyebilir). Desteklenen beş araç vardır
dosya sistemi türleri:
- yaaf2
- .
Bir MTD flash cihazın üzerindeki yaffs2 dosya sistemi. "cihaz" ÇMY bölümünün adı olmalıdır
Ayrıca
/proc/mtd
içinde de görünmelidir. - mtd
- .
Önyükleme ve kurtarma gibi önyüklenebilir bölümler için kullanılan ham MTD bölümü. YTB değil
ancak ekleme noktası, bölmeyi bulmak için anahtar olarak kullanılır. "cihaz"
/proc/mtd
bölgesindeki ÇMY bölümünün adı olmalıdır. - uzantı4
- . EMMc flash cihazının üzerindeki bir ext4 dosya sistemi. "cihaz" blok cihazın yolu olmalıdır.
- EMM
- . Önyükleme ve kurtarma gibi önyüklenebilir bölümler için kullanılan ham eMMc blok cihazı. Şuna benzer: mtd türü, eMMc aslında hiçbir zaman eklenmez ancak ekleme noktası dizesi, tabloda görebilirsiniz.
- Vfat
- .
Blok cihazların üzerindeki (genellikle SD kart gibi harici depolama alanları için) bir FAT dosya sistemidir. İlgili içeriği oluşturmak için kullanılan
blok cihaz ise cihaz2, herhangi bir engel olduğunda sistemin eklemeye çalıştığı ikinci blok cihazdır
birincil cihazın eklenmesi başarısız olur (SD kartlarla uyumluluk için,
bölümü tablosuyla biçimlendirilir).
Tüm bölümler kök dizine eklenmelidir (ör. ekleme noktası değeri eğik çizgiyle başlamalı ve başka eğik çizgi içermemelidir). Bu kısıtlama yalnızca ekleme için geçerlidir kurtarmadaki dosya sistemleri; ana sistem bunları istediğiniz yere monte edebilir. Dizinler
/boot
,/recovery
ve/misc
ham tür olmalıdır (mtd veya emmc),/system
,/data
, dizinlerde ise/cache
ve/sdcard
(varsa) dosya sistemi türleri olmalıdır (yaffs2, ext4 veya vfat).
Android 3.0'dan başlayarak kurtarma.fstab dosyası isteğe bağlı ek bir alan kazanmaktadır. seçenekleri. Şu anda tanımlanan tek seçenek length 'tir. bölümün uzunluğunu belirtin. Bu uzunluk, bölüm yeniden biçimlendirilirken kullanılır (ör. veri silme/fabrika ayarlarına sıfırlama işlemi sırasında kullanıcı verisi bölümü için veya sistem bölümü yükleme sırasında). Uzunluk değeri negatifse biçim, uzunluk değerinin gerçek bölüm boyutuna eklenerek alınır. Örneğin, Örneğin, "length=-16384"ü ayarlamak bu bölümün son 16k'lık kısmı oluşturulmayacaktır yeniden biçimlendirildiğinde üzerine yazılır. Bu özellik, verilerin şifrelenmesi gibi özellikleri destekler. Kullanıcı verisi bölümü (şifreleme meta verileri, , üzerine yazılmamalıdır).
Not: device2 ve options alanları isteğe bağlıdır. belirsizliğinden kaynaklanır. Satırdaki dördüncü alandaki giriş "/" ile başlıyorsa karakteri bulunuyorsa device2 girişi olarak kabul edilir; giriş "/" ile başlamıyorsa karakteri bulunuyorsa seçenekler alanı olarak kabul edilir.
Açılış animasyonu
Cihaz üreticileri, Android cihaz bir Android cihaz oluşturulduğunda gösterilen animasyonu başlatılıyor. Bunu yapmak için spesifikasyonları bootanimation biçiminde oluşturun.
Örneğin, Android Things cihazlar sıkıştırılmış dosyayı Android Things konsolu'na yükleyebilir ve böylece resimlerin karar verebilirsiniz.
Not: Bu resimler, Android marka kurallarına uygun olmalıdır. Marka kurallarında ise bu dokümanın Android bölümüne İş Ortağı Pazarlaması Pekiştirici.
Kurtarma kullanıcı arayüzü
Mevcut farklı donanımlara (fiziksel düğmeler, LED'ler, ekranlar vb.) sahip cihazları desteklemek için: kurtarma arayüzünü durumu gösterecek ve manuel olarak çalıştırılan özellikleri kontrol edin.
Amacınız birkaç C++ nesnesi içeren küçük bir statik kitaplık
işlev görebilir. Dosya
bootable/recovery/default_device.cpp
, varsayılan olarak kullanılır ve iyi bir
bu dosyanın cihazınız için bir sürümünü yazarken kopyalanacak başlangıç noktası.
Not: Burada Komut Yok yazan bir mesaj görebilirsiniz. Değiştirmek için metin, sesi artırma düğmesine basarken güç düğmesini basılı tutun. Cihazlarınızda yoksa metni değiştirmek için herhangi bir düğmeye uzun basın.
device/yoyodyne/tardis/recovery/recovery_ui.cpp
#include <linux/input.h> #include "common.h" #include "device.h" #include "screen_ui.h"
Başlık ve öğe işlevleri
Cihaz sınıfı, gizli modda görünen başlıkları ve öğeleri döndürmek için işlevler gerektirir. kurtarma menüsünü açın. Başlıklar menünün nasıl kullanılacağını açıklar (yani vurgulanan öğe).
static const char* HEADERS[] = { "Volume up/down to move highlight;", "power button to select.", "", NULL }; static const char* ITEMS[] = {"reboot system now", "apply update from ADB", "wipe data/factory reset", "wipe cache partition", NULL };
Not: Uzun satırlar kısaltılır (sarmalanmaz). Bu nedenle, satırlarınızın göz önünde bulundurun.
CheckKey'i Özelleştir
Ardından, cihazınızda RecoveryUI uygulamasını tanımlayın. Bu örnekte,
tardis cihazının ekranı olduğundan Yerleşik
ScreenRecoveryUI uygulama (şuranın talimatlarına bakın:
ekransız cihazlarda kullanılabilir.) Projenin gidişatı boyunca
ScreenRecoveryUI; CheckKey()
,
eşzamansız anahtar işleme:
class TardisUI : public ScreenRecoveryUI { public: virtual KeyAction CheckKey(int key) { if (key == KEY_HOME) { return TOGGLE; } return ENQUEUE; } };
KEY sabit değerleri
KEY_* sabitleri, linux/input.h
içinde tanımlanır. CheckKey()
kurtarma işleminin geri kalanında ne olduğundan bağımsız olarak çağrılır: menü kapatıldığında,
açık olduğundan, paket yüklemesi, kullanıcı verilerinin silinmesi vb. sırasında
sabit değerler:
- DEĞİŞTİR. Menü ve/veya metin görünümünü açın ya da kapatın
- YENİDEN BAŞLAT. Cihazı hemen yeniden başlatın
- YOKSAY. Bu tuşa basmayı yoksay
- SORUN. Eşzamanlı olarak (yani kurtarma işlemi tarafından) kullanılması için bu tuşa basın menü sistemi (ekran etkinse)
CheckKey()
, bir key-down etkinliğinin ardından bir key-up etkinliği her izlendiğinde çağrılır.
aynı tuşa sahiptir. (A-aşağı B-aşağı B-up A-up olaylarının dizisi yalnızca
CheckKey(B)
aranıyor.) CheckKey()
sesli arama yapabilir
IsKeyPressed()
tuşlarına basarak diğer tuşların basılı tutulup tutulmadığını kontrol edin. (Yukarıdaki
önemli etkinlik dizisi, CheckKey(B)
tarafından IsKeyPressed(A)
çağrıldıysa
doğru döndürürdü.)
CheckKey()
, sınıfında durumu koruyabilir; yararlı olabileceğini
anlamına gelir. Bu örnekte biraz daha karmaşık bir kurulum gösterilmektedir: Ekran
güç düğmesini basılı tutup sesi artırma tuşuna bastığınızda cihaz hemen yeniden başlatılabilir.
Güç düğmesine art arda beş kez basma (başka tuşlar olmadan):
class TardisUI : public ScreenRecoveryUI { private: int consecutive_power_keys; public: TardisUI() : consecutive_power_keys(0) {} virtual KeyAction CheckKey(int key) { if (IsKeyPressed(KEY_POWER) && key == KEY_VOLUMEUP) { return TOGGLE; } if (key == KEY_POWER) { ++consecutive_power_keys; if (consecutive_power_keys >= 5) { return REBOOT; } } else { consecutive_power_keys = 0; } return ENQUEUE; } };
Ekran Kurtarma Kullanıcı Arayüzü
Kendi resimlerinizi (hata simgesi, yükleme animasyonu, ilerleme çubukları)
ScreenRecoveryUI, hızı kontrol etmek için animation_fps
değişkenini ayarlayabilirsiniz.
animasyonların saniyedeki kare sayısı (FPS) değeri.
Not: Mevcut interlace-frames.py
komut dosyası, şu işlemleri yapmanıza olanak tanır:
animation_fps
bilgilerini resmin kendisinde depolama. Önceki sürümlerinde
Android, animation_fps
adlı cihazı kendiniz ayarlamanız gerekiyordu.
animation_fps
değişkenini ayarlamak için,
ScreenRecoveryUI::Init()
işlevi alt sınıfınızda. Değeri ayarlayın, ardından
Başlatma işlemini tamamlamak için parent Init()
işlevi. Varsayılan değer (20 FPS)
varsayılan kurtarma görüntülerine karşılık gelir; sağlamanız gerekmez.
Init()
işlevi. Resimlerle ilgili ayrıntılar için şuraya bakın:
Kurtarma Kullanıcı Arayüzü Görüntüleri.
Cihaz sınıfı
RecoveryUI uygulama işlemi gerçekleştirdikten sonra, cihaz sınıfınızı tanımlayın (diğer bir deyişle
yerleşik Cihaz sınıfı). UI sınıfınızın tek bir örneğini oluşturur ve
GetUI()
işlevinden:
class TardisDevice : public Device { private: TardisUI* ui; public: TardisDevice() : ui(new TardisUI) { } RecoveryUI* GetUI() { return ui; }
Kurtarma İşlemini Başlat
StartRecovery()
yöntemi, kurtarma işleminin başlangıcında, kullanıcı arayüzü aşağıdaki işlemleri gerçekleştirdikten sonra çağrılır:
ve bağımsız değişkenler ayrıştırıldıktan sonra, ancak herhangi bir işlem yapılmadan önce
alır. Varsayılan uygulama herhangi bir işlem yapmaz. Bu nedenle,
alt sınıflara eklemeniz gerekir:
void StartRecovery() { // ... do something tardis-specific here, if needed .... }
Kurtarma menüsünü sağlama ve yönetme
Sistem, başlık satırlarının ve öğelerin listesini almak için iki yöntem çağırır. Burada uygulandığında, dosyanın üstünde tanımlanan statik dizileri döndürür:
const char* const* GetMenuHeaders() { return HEADERS; } const char* const* GetMenuItems() { return ITEMS; }
Tutamaç Menü Tuşu
Sonra, tuşa basmayı ve aynı anda devam etmeyi gerektiren bir HandleMenuKey()
işlevi sağlayın
ve hangi işlemin yapılacağına karar verir:
int HandleMenuKey(int key, int visible) { if (visible) { switch (key) { case KEY_VOLUMEDOWN: return kHighlightDown; case KEY_VOLUMEUP: return kHighlightUp; case KEY_POWER: return kInvokeItem; } } return kNoAction; }
Yöntem, web sitesi tarafından önceden işlenmiş ve
CheckKey()
yöntemi) ve menü/metin günlüğünün mevcut durumu
görünürlük. Döndürülen değer tam sayıdır. Değer 0 veya daha büyükse
bir menü öğesinin konumu (hemen çağrılan bir menü öğesinin konumu) (bkz.
InvokeMenuItem()
yöntemini kullanın). Aksi durumda aşağıdakilerden biri olabilir:
önceden tanımlanmış sabit değerler:
- kVurgula'yı seçin. Menü vurgusunu önceki öğeye taşı
- kVurgula'yı seçin. Menü vurgusunu sonraki öğeye taşı
- kInvokeItem. Vurgulanan öğeyi çağır
- kNoAction değerleridir. Bu tuşa basıldığında hiçbir işlem yapma
Görünür bağımsız değişkenden anlaşıldığı gibi, HandleMenuKey()
çağrılmış olsa bile menü
görünür değil. CheckKey()
etiketinin aksine, kurtarma işlemi sırasında çağrılanmaz
verileri temizleme veya paket yükleme gibi bir işlem (yalnızca kurtarma işlemi boştayken çağrılır)
giriş yapmayı bekliyorum.
İztopu mekanizmaları
Cihazınızda iztopu benzeri bir giriş mekanizması varsa (EV_REL türünde giriş etkinlikleri oluşturur)
ve REL_Y kodunu içerir) kurtarma işlemi, KEY_UP ve KEY_DOWN tuşlarına basıldığında,
Trackball benzeri bir giriş cihazı, Y eksenindeki hareketi bildirir. Tek yapmanız gereken KEY_UP haritasını çıkarmak ve
KEY_DOWN etkinlik menü işlemlerine geçin. Bu eşleme yalnızca
CheckKey()
nedeniyle, iztopu hareketlerini yeniden başlatmak veya işlem için tetikleyici olarak
ekranı aç/kapat.
Değiştirici tuşlar
Değiştirici olarak basılı tutulan tuşların olup olmadığını kontrol etmek için IsKeyPressed()
yöntemini çağırın
oluşturmanız gerekir. Örneğin, bazı cihazlarda kurtarma sırasında Alt-W tuşlarına bastığınızda
veri silme işlemini gerçekleştirmenizi sağlar. Aşağıdaki gibi uygulayabilirsiniz:
int HandleMenuKey(int key, int visible) { if (ui->IsKeyPressed(KEY_LEFTALT) && key == KEY_W) { return 2; // position of the "wipe data" item in the menu } ... }
Not: visible (görünür) değeri yanlışsa özel değerin döndürülmesi bir anlam ifade etmez kullanıcı yapamayacağından menüyü manipüle eden değerler (vurgulamayı taşıma, vurgulanan öğeyi çağırma) o öne çıkanı görün. Ancak isterseniz değerleri döndürebilirsiniz.
Menü Öğesini Çağır
Daha sonra, dizideki tam sayı konumlarını eşleyen bir InvokeMenuItem()
yöntemi sağlayın.
GetMenuItems()
tarafından işlemlere iade edilen öğe sayısı. Öğe dizisindeki
tardis örneği, şunu kullanın:
BuiltinAction InvokeMenuItem(int menu_position) { switch (menu_position) { case 0: return REBOOT; case 1: return APPLY_ADB_SIDELOAD; case 2: return WIPE_DATA; case 3: return WIPE_CACHE; default: return NO_ACTION; } }
Bu yöntem, InternalinAction enum üyelerinin herhangi bir üyesini döndürerek sisteme bu sıralamayı almasını söyleyebilir. eyleme (veya sistemin hiçbir şey yapmamasını istiyorsanız NO_ACTION üyesine) dokunun. Burası, sistemde bulunanların dışında ek kurtarma işlevleri sağlar: çağrıldığında, menü öğesi çağrıldığında buradan yürütün ve NO_ACTION değerini döndürür. Böylece, sistem başka bir şey yapmaz.
BuildinAction aşağıdaki değerleri içerir:
- NO_ACTION. Hiçbir işlem yapmamayı tercih edebilirsiniz.
- YENİDEN BAŞLAT. Kurtarma işleminden çıkın ve cihazı normal bir şekilde yeniden başlatın.
- APPLY_EXT, APPLY_CACHE, APPLY_ADB_SIDELOAD. Çeşitli uygulamalardan bir güncelleme paketi yükleyin yer. Ayrıntılar için Başka cihazdan yükleme başlıklı makaleye bakın.
- WIPE_CACHE Yalnızca önbellek bölümünü yeniden biçimlendirin. Onay gerekmez, çünkü göreceli olarak zararsızdır.
- WIPE_DATA Kullanıcı verilerini ve önbellek bölümlerini (fabrika verileri olarak da bilinir) yeniden biçimlendirme sıfırlandı. Devam etmeden önce kullanıcıdan bu işlemi onaylaması istenir.
Son yöntem olan WipeData()
isteğe bağlıdır ve veri silme işleminde çağrılır
başlatıldığında (menü üzerinden kurtarma sırasında ya da kullanıcı,
ana sistemden fabrika verilerine sıfırlama işlemi). Bu yöntem, kullanıcı verilerinden ve önbellekten önce çağrılır
tüm bölümler temizlenir. Cihazınız, kullanıcı verilerini bu ikisi dışında bir yerde saklıyorsa
bölümleri buradan silmelisiniz. Başarılı olduğunu belirtmek için 0, başka bir değeri belirtmek için
değeri yoktur, ancak şu anda döndürülen değer yok sayılır. Kullanıcı verileri ve önbellek
başarılı veya başarısız olmanız fark etmeksizin tüm bölümler silinir.
int WipeData() { // ... do something tardis-specific here, if needed .... return 0; }
Cihaz yap
Son olarak,
Cihaz sınıfınızın bir örneğini oluşturan ve döndüren make_device()
işlevi:
class TardisDevice : public Device { // ... all the above methods ... }; Device* make_device() { return new TardisDevice(); }
Kurulum ve cihaz kurtarma bağlantısı
Kurtarma_ui.cpp dosyasını tamamladıktan sonra dosyayı oluşturun ve cihazınızdaki kurtarma bölümüne bağlayın. İçinde Android.mk, yalnızca bu C++ dosyasını içeren bir statik kitaplık oluşturun:
device/yoyodyne/tardis/recovery/Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := eng LOCAL_C_INCLUDES += bootable/recovery LOCAL_SRC_FILES := recovery_ui.cpp # should match TARGET_RECOVERY_UI_LIB set in BoardConfig.mk LOCAL_MODULE := librecovery_ui_tardis include $(BUILD_STATIC_LIBRARY)
Ardından, bu cihazın kart yapılandırmasında TARGET_RECOVERY_UI_LIB.
device/yoyodyne/tardis/BoardConfig.mk [...] # device-specific extensions to the recovery UI TARGET_RECOVERY_UI_LIB := librecovery_ui_tardis
Kurtarma kullanıcı arayüzü görüntüleri
Kurtarma kullanıcı arayüzü görüntülerden oluşur. İdeal olarak, kullanıcılar hiçbir zaman kullanıcı arayüzüyle etkileşimde bulunmaz: Normal güncelleme sırasında telefon, kurtarma işlemine başlar, yüklemenin ilerleme çubuğunu ve kullanıcı herhangi bir giriş yapmadan yeni sistemde yeniden başlatılır. Sistem durumunda Güncelleme sorunu üzerinde çalışıyorsa kullanıcının yapabileceği tek işlem müşteri hizmetlerini aramaktır.
Yalnızca görüntü içeren bir arayüz, yerelleştirme ihtiyacını ortadan kaldırır. Ancak, Android 5.0'dan itibaren güncelleme, resimle birlikte bir metin dizesi (ör. "Sistem güncellemesi yükleniyor...") gösterebilir. Ayrıntılar için Yerelleştirilmiş kurtarma metni başlıklı makaleye göz atın.
Android 5.0 ve sonraki sürümler
Android 5.0 ve sonraki sürümler kurtarma kullanıcı arayüzünde iki ana görüntü kullanılır: hata görüntüsü ve yükleme animasyonu gösterilir.
Yükleme animasyonu, farklı çerçevelere sahip tek bir PNG resmi
satır ile aralıklı animasyon (Bu nedenle Şekil 2 sıkıştırılmış görünür). Örneğin,
200x200 yedi karelik animasyon, 200x1400 boyutunda tek bir resim oluşturun. Bu resim, ilk karenin 0, 7. satır,
14, 21, ...; ikinci kare 1, 8, 15, 22. satırlardadır. vb. Birleştirilmiş resim,
animasyon karesi sayısını ve saniyedeki kare sayısını gösteren metin parçası
(FPS) tuşlarına basın. bootable/recovery/interlace-frames.py
aracı, bir dizi giriş çerçevesi alır
ve bunları kurtarma tarafından kullanılan gerekli birleşik görüntüye dönüştürür.
Varsayılan resimler farklı yoğunluklarda kullanılabilir ve
bootable/recovery/res-$DENSITY/images
(ör.
bootable/recovery/res-hdpi/images
) bilgileri gösterilir. Yükleme sırasında statik görüntü kullanmak için
sadece icon_installing.png resmini sağlamanız ve
animasyonunu 0 değerine ayarlayın (hata simgesi animasyonlu değildir; her zaman statik bir resimdir).
Android 4.x ve önceki sürümler
Android 4.x ve önceki sürümlerin kurtarma arayüzünde hata görüntüsü (yukarıda gösterilmiştir) ve yükleme animasyonu ve çeşitli yer paylaşımlı resimler:
Yükleme sırasında, ekrandaki ekran icon_installing.png çerçevelerden birini uygun ofsette bu çerçevenin üstüne çizin. Burada kırmızı renk kutusu, bindirmenin taban resmin üzerine yerleştirildiği yeri vurgulamak için üste bindirilir:
Sonraki kareler, yalnızca bir sonraki bindirme resminin, zaten oradadır; Temel resim yeniden çizilmez.
Animasyondaki kare sayısı, istenen hız ve yer paylaşımının x ve y ofsetleri
ile ilgili diğer tüm özellikler ScreenRecoveryUI sınıfının üye değişkenleri tarafından ayarlanır. Bunu kullanırken
özel resimler kullanmak içinInit()
değerleri değiştirmek için alt sınıfını kullanın (ayrıntılar için bkz.
ScreenRecoveryUI). Komut dosyası
bootable/recovery/make-overlay.py
, bir dizi resim çerçevesinin dönüştürülmesine yardımcı olabilir
"ana resim + yer paylaşımlı resimler"e kurtarma için gereken formu
ofsetleri kontrol edin.
Varsayılan resimler bootable/recovery/res/images
konumunda bulunur. Statik resim kullanmak için
Yükleme sırasında, yalnızca icon_installing.png resmini sağlamanız ve
kareleri 0 değerine ayarlayın (hata simgesi animasyonlu değildir; her zaman statik bir resimdir).
Yerelleştirilmiş kurtarma metni
Android 5.x'te bir metin dizesi (ör. "Sistem güncellemesi yükleniyor...") ve görüntüsüdür. Ana sistem kurtarma işlemine önyüklendiğinde, kullanıcının mevcut yerel ayarını bir komut satırı seçeneğinden yararlanabilirsiniz. Görüntülenmesi için her mesajın kurtarılması işlemi sırasında ikinci bir her yerel ayarda söz konusu mesaj için önceden işlenmiş metin dizelerine sahip birleşik resim.
Kurtarma metni dizelerinin örnek resmi:
Kurtarma metninde aşağıdaki mesajlar gösterilebilir:
- Sistem güncellemesi yükleniyor...
- Hata!
- Siliniyor... (veri silme/fabrika ayarlarına sıfırlama sırasında)
- Komut yok (kullanıcı, kurtarma işlemini manuel olarak başlattığında)
bootable/recovery/tools/recovery_l10n/
uygulamasındaki Android uygulaması yerelleştirmeler oluşturur
bileşik görüntü oluşturur. Bu uygulamayı kullanmayla ilgili ayrıntılar için şuraya bakın:
yorum sayısı
bootable/recovery/tools/recovery_l10n/src/com/android/recovery_l10n/Main.java
Kullanıcı, kurtarma işlemini manuel olarak başlattığında yerel ayar kullanılamayabilir ve metin görüntülenir. Kurtarma işlemi için kısa mesajları kritik hale getirmeyin.
Not: Günlük mesajlarını görüntüleyen ve kullanıcının şunları yapmasına olanak tanıyan gizli arayüz: Menüden belirli işlemler yalnızca İngilizce dilinde kullanılabilir.
İlerleme çubukları
İlerleme çubukları ana resmin (veya animasyonun) altında görünebilir. İlerleme çubuğunu, aynı boyutta olması gereken iki giriş resmini birleştirir:
Dolgu resminin sol ucu, boş bir resim seçin. İkisi arasındaki sınırın konumu resimler ilerlemeyi gösterecek şekilde değiştirilir. Örneğin, yukarıdaki giriş resmi çiftleriyle, göster:
Bu resimleri (bu sayfadaki
örnek) device/yoyodyne/tardis/recovery/res/images
, Dosya adları, yukarıda listelenenlerle eşleşmelidir; bir dosya söz konusu dizinde bulunduğunda,
derleme sistemi, karşılık gelen varsayılan görüntü yerine bunu kullanır. Yalnızca RGB veya PNG'ler
8 bit renk derinliğine sahip RGBA biçimi desteklenir.
Not: Android 5.x sürümünde, yerel ayar, kurtarma olarak biliniyorsa ve sağdan sola (RTL) yazılan dillerde (Arapça, İbranice vb.) ilerleme çubuğu, sağdan sola çıktı.
Ekranı olmayan cihazlar
Her Android cihazın ekranı yoktur. Cihazınız gözetimsiz bir cihazsa veya sadece ses özellikli arayüzü kullanıyorsanız kurtarma kullanıcı arayüzünü daha kapsamlı şekilde özelleştirmeniz gerekebilir. Bunun yerine doğrudan RecoveryUI üst sınıfının alt sınıfını oluşturun.
RecoveryUI, "ekranı aç/kapat" gibi daha düşük düzeyli kullanıcı arayüzü işlemlerini işleme yöntemlerine sahiptir.
"İlerleme çubuğunu güncelle" "menüyü göster", "menü seçimini değiştir", vb. kullanabilirsiniz.
cihazınıza uygun bir arayüz sağlamak için bunları kullanın. Belki cihazınızda
durumu belirtmek için farklı renkler veya yanıp sönme desenleri kullanabilir ya da CANNOT TRANSLATE
ses'e dokunun. (Belki de bir menüyü veya "metin görüntüleme" modunu hiç desteklemek istemiyorsunuzdur; bunu
CheckKey()
ve
Ekranı hiçbir zaman açmayan veya bir menü seçmeyen HandleMenuKey()
uygulamaları
öğe. Bu durumda, sağlamanız gereken RecoveryUI yöntemlerinin çoğu boş olabilir
bulabilirsiniz.)
Hangi yöntemlerin olduğunu görmek için RecoveryUI beyanı için bootable/recovery/ui.h
sayfasına bakın
siz de duyabilirsiniz. RecoveryUI soyuttur. Bazı yöntemler tamamen sanaldır ve
alt sınıfları içerir, ancak anahtar girişlerinin işlenmesini sağlayacak kodu içerir. Bu ayarı geçersiz kılabilir,
Ayrıca, cihazınızda anahtar yoksa veya bunları farklı şekilde işlemek isterseniz de yararlanabilirsiniz.
Güncelleyici
Güncelleme paketinin yüklenmesinde cihaza özel kod kullanmak için güncelleyici komut dosyanız içinden çağrılabilecek kendi uzantı işlevlerine sahip olmanız gerekir. İşte bir örnek işlevini yerine getirin:
device/yoyodyne/tardis/recovery/recovery_updater.c
#include <stdlib.h> #include <string.h> #include "edify/expr.h"
Her uzantı işlevi aynı imzaya sahiptir. Bağımsız değişkenler,
işlevi, bir State*
çerezi, gelen bağımsız değişkenlerin sayısı ve
bağımsız değişkenleri temsil eden Expr*
işaretçi dizisi. Döndürülen değer:
yeni tahsis edilen Value*
.
Value* ReprogramTardisFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 2) { return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc); }
İşleviniz çağrıldığında bağımsız değişkenleriniz değerlendirilmemiştir.
mantık, hangisinin kaç kez değerlendirileceğini belirler. Böylece, uzantıları
işlevlerinden yararlanabilirsiniz. Değerlendirmek için Call Evaluate()
bir Expr*
bağımsız değişkeni, Value*
döndürüyor. Eğer Evaluate()
ise
NULL değerini döndürürse elinizdeki tüm kaynakları serbest bırakmalı ve hemen NULL değerini döndürmelisiniz (bu
edify yığınını iptal eder). Aksi takdirde, döndürülen Değerin sahipliğini alırsınız ve
en sonunda telefon etmekten
FreeValue()
var.
Fonksiyonun iki bağımsız değişkene ihtiyacı olduğunu varsayalım: dize değerli bir anahtar ve blob değerli bir image olarak değiştirin. Şuna benzer bağımsız değişkenleri okuyabilirsiniz:
Value* key = EvaluateValue(state, argv[0]); if (key == NULL) { return NULL; } if (key->type != VAL_STRING) { ErrorAbort(state, "first arg to %s() must be string", name); FreeValue(key); return NULL; } Value* image = EvaluateValue(state, argv[1]); if (image == NULL) { FreeValue(key); // must always free Value objects return NULL; } if (image->type != VAL_BLOB) { ErrorAbort(state, "second arg to %s() must be blob", name); FreeValue(key); FreeValue(image) return NULL; }
NULL kontrolü yapmak ve önceden değerlendirilen bağımsız değişkenleri serbest bırakmak birden fazla öğe için yorucu olabilir
bağımsız değişkenlerdir. ReadValueArgs()
işlevi bu işlemi kolaylaştırabilir. Kod yerine
şunu yazmış olabilirdiniz:
Value* key; Value* image; if (ReadValueArgs(state, argv, 2, &key, &image) != 0) { return NULL; // ReadValueArgs() will have set the error message } if (key->type != VAL_STRING || image->type != VAL_BLOB) { ErrorAbort(state, "arguments to %s() have wrong type", name); FreeValue(key); FreeValue(image) return NULL; }
ReadValueArgs()
, yazım denetimi yapmaz. Bu nedenle, işlemi burada yapmanız gerekir; bu daha
bunu bir if ifadesiyle yapmak (bunun pahasına daha düşük bir
hata mesajı gösterir. Ancak değerlendirmeyi ReadValueArgs()
halleder
her bağımsız değişkeni serbest bırakır ve önceden değerlendirilen tüm bağımsız değişkenleri özgür kılar (ayrıca, her bir bağımsız değişkeni
hata mesajı) belirir. URL parametrelerinin Google tarafından nasıl ele alınmasını istediğinizi belirtmek için
Değişken sayıları değerlendirmek için ReadValueVarArgs()
kolaylık işlevi
bağımsız değişkenler (Value*
dizisi döndürür).
Bağımsız değişkenleri değerlendirdikten sonra işlevin çalışmasını yapın:
// key->data is a NUL-terminated string // image->data and image->size define a block of binary data // // ... some device-specific magic here to // reprogram the tardis using those two values ...
Döndürülen değer bir Value*
nesnesi olmalıdır; bu nesnenin sahipliği
yardımcı olur. Arayan, bu bağlantıyla gösterilen tüm verilerin sahipliğini alır
Value*
- özellikle veri üyesi.
Bu durumda, işlemin başarılı olduğunu belirtmek için doğru veya yanlış bir değer döndürmek istersiniz. Şunu unutmayın:
bu kurala göre boş dize false, diğer tüm dizeler true olur. Siz
arayan, her ikisini de free()
. Şu numaradan FreeValue()
adlı kişiyi aramayı unutmayın:
nesnelerden kaçının!
FreeValue(key); FreeValue(image); Value* result = malloc(sizeof(Value)); result->type = VAL_STRING; result->data = strdup(successful ? "t" : ""); result->size = strlen(result->data); return result; }
StringValue()
kolaylık işlevi, bir dizeyi yeni bir Değer nesnesine sarmalar.
Yukarıdaki kodu daha kısa ve öz bir şekilde yazmak için kullanın:
FreeValue(key); FreeValue(image); return StringValue(strdup(successful ? "t" : "")); }
İşlevleri edify yorumlayıcısına bağlamak için
Register_foo
burada foo, aşağıdakileri içeren statik kitaplığın adıdır:
bu kodu girin. Her bir uzantı işlevini kaydetmek için RegisterFunction()
öğesini çağırın. Ölçüt
kurallara göre hareket etmenizi sağlamak için cihaza özel işlevleri device.whatever
olarak adlandırın.
gelecekteki yerleşik işlevlerle çakışmalar olabilir.
void Register_librecovery_updater_tardis() { RegisterFunction("tardis.reprogram", ReprogramTardisFn); }
Artık Makefile'ı kodunuzla statik bir kitaplık oluşturacak şekilde yapılandırabilirsiniz. (Bu aynı önceki bölümde kurtarma kullanıcı arayüzünü özelleştirmek için kullanılan makefile; cihazınızda her ikisi de burada tanımlanan statik kitaplıklar.)
device/yoyodyne/tardis/recovery/Android.mk
include $(CLEAR_VARS) LOCAL_SRC_FILES := recovery_updater.c LOCAL_C_INCLUDES += bootable/recovery
Statik kitaplığın adı,
Register_libname
işlevi içeriyor.
LOCAL_MODULE := librecovery_updater_tardis include $(BUILD_STATIC_LIBRARY)
Son olarak, kitaplığınızı getirmek için kurtarma derlemesini yapılandırın. Kitaplığınızı şuraya ekleyin:
TARGET_RECOVERY_UPDATER_LIBS (birden fazla kitaplık içerebilir; hepsi kaydedilir).
Kodunuz, uzantı içermeyen diğer statik kitaplıklara bağlıysa (ör.
Register_libname
işlevleri yoksa) bunları aşağıdaki listede listeleyebilirsiniz:
TARGET_RECOVERY_UPDATER_Extra_LIBS aracılığıyla bu kişileri güncelleyiciye bağlamalısınız.
(mevcut değil) kayıt işlevi. Örneğin, cihazınıza özel kodunuz
zlib kullanıyorsanız buraya libz eklersiniz.
device/yoyodyne/tardis/BoardConfig.mk
[...] # add device-specific extensions to the updater binary TARGET_RECOVERY_UPDATER_LIBS += librecovery_updater_tardis TARGET_RECOVERY_UPDATER_EXTRA_LIBS +=
OTA paketinizdeki güncelleyici komut dosyaları artık işlevinizi diğerleri gibi çağırabilir. Yeniden programlamak için
tardis cihazınıza yüklüyorsanız, güncelleme komut dosyası şunları içerebilir:
tardis.reprogram("the-key", package_extract_file("tardis-image.dat"))
Bu kullanım
yerleşik package_extract_file()
işlevinin tek bağımsız değişkenli sürümünü
Bu işlem, güncelleme paketinden çıkarılan bir dosyanın içeriğini, oluşturulması için bir blob olarak döndürür
ikinci bağımsız değişkeni yeni uzantı işlevine aktarır.
OTA paketi oluşturma
Son bileşen OTA paket oluşturma araçlarının OTA paketi oluşturma araçlarınızın özel veriler oluşturabilir ve uzantı işlevlerinize yönelik çağrılar içeren güncelleyici komut dosyaları oluşturabilirsiniz.
Öncelikle derleme sisteminin cihaza özel bir veri blobu hakkında bilgi edinmesini sağlayın. Verilerinizi varsayma
dosya device/yoyodyne/tardis/tardis.dat
içindeyse aşağıdakileri beyan edin:
cihazın AndroidBoard.mk'si:
device/yoyodyne/tardis/AndroidBoard.mk
[...] $(call add-radio-file,tardis.dat)
Bunun yerine Android.mk'ye de yerleştirebilirsiniz ancak bu durumda cihaz tarafından korunması gerekir. ağaçtaki tüm Android.mk dosyaları yüklendiğinden emin olun. geliştirmenizi sağlar. (Ağaçınızda birden çok cihaz varsa tardis.dat dosyasının yalnızca tardis cihazını kurmam gerekiyor.)
device/yoyodyne/tardis/Android.mk
[...] # an alternative to specifying it in AndroidBoard.mk ifeq (($TARGET_DEVICE),tardis) $(call add-radio-file,tardis.dat) endif
Bunlara tarihsel nedenlerden dolayı radyo dosyaları denir; alakalı olduğu durumlar olabilir.
cihazın radyosu (varsa). Bunlar, derleme sisteminin kopyaladığı opak veri blob'larıdır
OTA oluşturma araçları tarafından kullanılan target-files .zip dosyası. Bir derleme yaptığınızda, tardis.dat
target-files.zip içinde RADIO/tardis.dat
olarak depolanır. Şu numarayı arayabilirsiniz:
add-radio-file
tıklayarak istediğiniz kadar dosya ekleyebilirsiniz.
Python modülü
Sürüm araçlarını genişletmek için araçlarla birlikte bir Python modülü (releasetools.py olarak adlandırılmalıdır) (varsa) arayabilir. Örnek:
device/yoyodyne/tardis/releasetools.py
import common def FullOTA_InstallEnd(info): # copy the data into the package. tardis_dat = info.input_zip.read("RADIO/tardis.dat") common.ZipWriteStr(info.output_zip, "tardis.dat", tardis_dat) # emit the script code to install this data on the device info.script.AppendExtra( """tardis.reprogram("the-key", package_extract_file("tardis.dat"));""")
Artımlı bir OTA paketi oluşturma durumunu ayrı bir işlev ele alır. Bunun için Örneğin, tardis'i yalnızca tardis.dat dosyası değiştiğinde yeniden programlamanız gerektiğini varsayalım. motive eder.
def IncrementalOTA_InstallEnd(info): # copy the data into the package. source_tardis_dat = info.source_zip.read("RADIO/tardis.dat") target_tardis_dat = info.target_zip.read("RADIO/tardis.dat") if source_tardis_dat == target_tardis_dat: # tardis.dat is unchanged from previous build; no # need to reprogram it return # include the new tardis.dat in the OTA package common.ZipWriteStr(info.output_zip, "tardis.dat", target_tardis_dat) # emit the script code to install this data on the device info.script.AppendExtra( """tardis.reprogram("the-key", package_extract_file("tardis.dat"));""")
Modül işlevleri
Modülde aşağıdaki işlevleri sağlayabilirsiniz (yalnızca ihtiyacınız olanları uygulayın).
FullOTA_Assertions()
- . Tam OTA oluşturma sürecinin başlangıcında çağrılır. Burası onay göndermek için iyi bir yerdir cihazın mevcut durumu hakkında bilgilendirilmeyi sağlar. olanak tanır.
FullOTA_InstallBegin()
- . Cihaz durumu hakkındaki tüm onaylar geçtikten sonra, ancak herhangi bir değişiklikten önce çağrıldı emin olun. Güncellemeden önce çalıştırılması gereken cihaza özel güncellemeler için Cihazda başka bir şey değiştirildi.
FullOTA_InstallEnd()
- . Komut dosyası oluşturma işleminin sonunda, önyüklemeyi güncellemek için komut dosyası komutlarından sonra çağrılır: sistem bölümleri yayınlanmıştır. İsterseniz güncellemeleri alın.
IncrementalOTA_Assertions()
- .
FullOTA_Assertions()
öğesine benzer, ancak artımlılık oluşturulurken çağrılır güncelleme paketi. IncrementalOTA_VerifyBegin()
- . Cihaz durumu hakkındaki tüm onaylar geçtikten sonra, ancak herhangi bir değişiklik yapılmadan önce çağrılır emin olun. Her şeyden önce çalışması gereken cihaza özgü güncellemeler için komutlar oluşturabilirsiniz cihazdaki diğer değişiklikler değiştirildi.
IncrementalOTA_VerifyEnd()
- . Doğrulama aşamasının sonunda çağrılır. Doğrulama işlemi komut dosyası tarafından dosyası, beklenen başlangıç içeriğine sahip olacaktır. Bu noktada, cihaz değiştirildi. Ayrıca cihaza özgü ek bilgiler için de doğrulamaları gerekir.
IncrementalOTA_InstallBegin()
- . Yama uygulanacak dosyaların beklenen özelliğe sahip olduğu doğrulandıktan sonra çağrılır before durumundan önce, ancak herhangi bir değişiklik yapılmadan önce). Şunlar için komut gönderebilirsiniz: Cihazda herhangi bir şey değiştirilmeden önce çalışması gereken cihaza özel güncellemeler.
IncrementalOTA_InstallEnd()
- . Tam OTA paketi eşdeğerine benzer şekilde, bu komut dosyasının sonunda çağrılır güncelleme işlemi başlatıldıktan ve sistem bölümlerinin güncellenmesi için komut dosyası komutlarından sonra yayınlanır. Cihaza özel güncellemeler için ek komutlar da kullanabilirsiniz.
Not: Cihazın güç kesintisi olursa OTA kurulumu şuradan yeniden başlatılabilir: başlar. Bu komutların zaten çalıştırıldığı cihazlarla başa çıkmaya hazırlıklı olun. bir kısmını ifade eder.
İşlevleri bilgi nesnelerine iletme
İşlevleri, kullanışlı çeşitli öğeler içeren tek bir bilgi nesnesine iletin:
-
bilgi.input_zip. (Yalnızca tam OTA'lar) Şu öğe için
zipfile.ZipFile
nesnesi: target-files .zip dosyasını girin. -
info.source_zip olarak ayarlayın. (Yalnızca artımlı OTA) için
zipfile.ZipFile
nesnesi kaynak target-files .zip (derleme, artımlı paket, yükleniyor). -
info.target_zip değerini alır. (Yalnızca artımlı OTA) için
zipfile.ZipFile
nesnesi hedef target-files .zip (artımlı paketin cihaza koyduğu derleme) dosyası. -
info.çıktı_zip dosyası şeklinde görünür. Paket oluşturuluyor; bir
zipfile.ZipFile
nesnesi açıldı tercih edebilirsiniz. Bir dosyasını pakete ekleyin. -
info.script olarak da bilinir. Komut ekleyebileceğiniz komut dosyası nesnesi. Telefonla arama
Komut dosyasına metin çıktısı almak için
info.script.AppendExtra(script_text)
. Çıkış metninin noktalı virgülle sona erdiğinden, yayınlanan komutlarla karşılaşmadığından emin olun daha fazla bilgi edineceksiniz.
Bilgi nesnesiyle ilgili ayrıntılar için şuraya bakın: ZIP arşivleri için Python Software Foundation belgeleri.
Modül konumunu belirtin
BoardConfig.mk dosyanızda cihazınızın versiontools.py komut dosyasının konumunu belirtin:
device/yoyodyne/tardis/BoardConfig.mk
[...] TARGET_RELEASETOOLS_EXTENSIONS := device/yoyodyne/tardis
TARGET_RELEASETOOLS_EXTENSIONS ayarlanmazsa varsayılan olarak
$(TARGET_DEVICE_DIR)/../common
dizini (device/yoyodyne/common
) ekleyebilirsiniz. En iyisi, versiontools.py komut dosyasının konumunu açık bir şekilde tanımlamaktır.
Tardis cihazını oluştururken publishtools.py komut dosyası target-files dosyasına eklenir.
.zip dosyası (META/releasetools.py
) olur.
Sürüm araçlarını (img_from_target_files
veya
ota_from_target_files
) içeriyorsa, target-files.zip dosyasındaki versiontools .py komut dosyasını
Android kaynak ağacındakine göre tercih edilir. Ayrıca reklamları
cihaza özel uzantıların yolunu -s
(veya
--device_specific
) seçeneğinin yanındaki kutuyu işaretleyin. Bu şekilde şunları yapabilirsiniz:
hataları düzeltin, sürüm araçları uzantılarında değişiklik yapın ve bu değişiklikleri eski
target-files'te olduğu gibi.
Artık ota_from_target_files
çalıştırıldığında
target_files .zip dosyasından cihaza özel modüldür ve OTA oluştururken bu modülü kullanır
paketler:
./build/make/tools/releasetools/ota_from_target_files \
-i PREVIOUS-tardis-target_files.zip \
dist_output/tardis-target_files.zip \
incremental_ota_update.zip
Alternatif olarak,
ota_from_target_files
./build/make/tools/releasetools/ota_from_target_files \
-s device/yoyodyne/tardis \
-i PREVIOUS-tardis-target_files.zip \
dist_output/tardis-target_files.zip \
incremental_ota_update.zip
Not: Seçeneklerin tam listesi için şu sayfaya bakın:
ota_from_target_files
yorum
build/make/tools/releasetools/ota_from_target_files
.
Başka cihazdan yükleme mekanizması
Kurtarma işlemi, bir güncelleme paketini yüklemeden manuel olarak yüklemek için bir başka cihazdan yükleme mekanizmasına sahiptir. ana sistem tarafından kablosuz olarak indirebilirsiniz. Başka cihazdan yükleme, hata ayıklamak veya hata ayıklamak ana sistemin başlatılamadığı cihazlarda gerçekleşen değişiklikleri görebilirsiniz.
Daha önce başka cihazdan yükleme işlemi, paketlerin SD kartından yüklenerek yapılıyordu; inç paket, başlatılmayan bir cihazda ise paket, başka bir uygulama sonra da cihaza takılı SD kart bulunur. Android cihazları kullanmaya başlamak için çıkarılabilir harici depolama birimi, kurtarma işlemi başka cihazdan yükleme için iki ek mekanizmayı destekler: paketleri önbellek bölümünden yükleme ve adb kullanarak USB üzerinden yükleme.
Her bir cihazdan yükleme mekanizmasını çağırmak için cihazınızın Device::InvokeMenuItem()
yöntemi
aşağıdaki BuildinAction değerlerini döndürebilir:
-
APPLY_EXT. Harici depolama alanından bir güncelleme paketi yükleyin (
/sdcard
dizin). kurtarma.fstab dosyanız,/sdcard
ekleme noktasını tanımlamalıdır. Bu/data
sembolik bir bağlantısı olan SD karta (veya bazı durumlarda) benzer bir mekanizma)/data
genellikle kurtarılamaz çünkü şifrelenmiş olabilir. Kurtarma kullanıcı arayüzünde/sdcard
konumundaki .zip dosyalarından oluşan bir menü ve kullanıcının bir seçim yapmasına olanak tanır. -
APPLY_CACHE.
/sdcard
üzerinden paket yüklemeye benzer. Tek fark,/cache
dizini (kurtarma için her zaman kullanılabilen) kullanılıyor . Normal sistemde,/cache
yalnızca ayrıcalıklı kullanıcılar tarafından yazılabilir. Cihaz önyüklenebilir değilse/cache
dizini (bu da bu mekanizmayı sınırlı bir fayda sağlar). -
APPLY_ADB_SIDELOAD. Kullanıcının USB kablosuyla cihaza paket göndermesine ve
adb geliştirme aracıdır. Bu mekanizma çağrıldığında kurtarma kendi mini'sini başlatır
adbd arka plan programının bir sürümünü kullanır. Bu mini
sürümü yalnızca tek bir komutu destekliyor:
adb sideload filename
. Adlandırılmış dosya ana makineden cihaza gönderilir ve daha sonra bu dosya doğrulanır ve yerel depolamada olduğu gibi yükler.
Dikkat edilmesi gereken birkaç nokta:
- Yalnızca USB aktarımı desteklenir.
-
Kurtarma işleminiz adbd'yi normal bir şekilde çalıştırırsa (genellikle userdebug ve eng derlemeleri için geçerlidir)
cihaz adb başka cihazdan yükleme modundayken kapatılmalı ve adb olduğunda yeniden başlatılacaktır.
sideload, paket alma işlemi tamamlandı. Adb başka cihazdan yükleme modundayken başka hiçbir adb komutu yok
sideload
işten (logcat
,reboot
,push
,pull
,shell
vb. tümü başarısız). -
Cihazda adb başka cihazdan yükleme modundan çıkamazsınız. İptal etmek için
Paket olarak
/dev/null
(veya geçerli paket olmayan herhangi bir şey) ve bu durumda cihaz bunu doğrulayamaz ve yükleme işlemini durduracaktır. RecoveryUI uygulamanınCheckKey()
yöntemi tuşlara basıldığında çağrılmaya devam eder. Bu yüzden, cihazı yeniden başlatan ve adb başka cihazdan yükleme modunda çalışan bir tuş sırası sağlayabilirsiniz.