Android 17, geliştiriciler için harika yeni özellikler ve API'ler sunuyor. Aşağıdaki bölümlerde, ilgili API'leri kullanmaya başlamanıza yardımcı olmak için bu özellikler özetlenmiştir.
Yeni, değiştirilmiş ve kaldırılmış API'lerin ayrıntılı listesi için API farklılıkları raporunu inceleyin. Yeni API'lerle ilgili ayrıntılar için Android API referansını ziyaret edin. Yeni API'ler görünürlük için vurgulanmıştır.
Platform değişikliklerinin uygulamalarınızı etkileyebileceği alanları da incelemeniz gerekir. Daha fazla bilgi için aşağıdaki sayfalara göz atın:
- Uygulamalar Android 17'yi hedeflediğinde etkileyen davranış değişiklikleri
targetSdkVersiondeğerinden bağımsız olarak tüm uygulamaları etkileyen davranış değişiklikleri.
Temel işlevler
Android 17, temel Android işlevleriyle ilgili aşağıdaki yeni özellikleri ekler.
Yeni ProfilingManager tetikleyicileri
Android 17, performans sorunlarında hata ayıklamak için ayrıntılı veriler toplamanıza yardımcı olmak amacıyla ProfilingManager'a çeşitli yeni sistem tetikleyicileri ekler.
Yeni tetikleyiciler:
TRIGGER_TYPE_COLD_START: Tetikleyici, uygulamanın baştan başlatılması sırasında gerçekleşir. Yanıt hem çağrı yığını örneği hem de sistem izi içerir.TRIGGER_TYPE_OOM: Bir uygulamaOutOfMemoryErroroluşturduğunda ve buna yanıt olarak Java Heap Dump sağladığında tetikleyici gerçekleşir.TRIGGER_TYPE_KILL_EXCESSIVE_CPU_USAGE: Tetikleyici, bir uygulama anormal ve aşırı CPU kullanımı nedeniyle kapatıldığında gerçekleşir ve yanıt olarak bir çağrı yığını örneği sağlar.TRIGGER_TYPE_ANOMALY: Aşırı bağlayıcı çağrıları ve aşırı bellek kullanımı gibi sistem performansı anormalliklerini tespit edin.
Sistem tetikleyicisinin nasıl ayarlanacağını öğrenmek için tetikleyici tabanlı profilleme ve profilleme verilerini alma ve analiz etme ile ilgili dokümanlara bakın.
Uygulama anormallikleri için profilleme tetikleyicisi
Android 17, kaynak yoğun davranışları ve olası uyumluluk gerilemelerini izleyen cihaz üzerinde anormallik algılama hizmetini kullanıma sunar. ProfilingManager ile entegre olan bu hizmet, uygulamanızın sistem tarafından algılanan belirli etkinlikler tarafından tetiklenen profil oluşturma yapılarını almasına olanak tanır.
Aşırı bağlayıcı çağrıları ve aşırı bellek kullanımı gibi sistem performansı sorunlarını tespit etmek için TRIGGER_TYPE_ANOMALY tetikleyicisini kullanın. Bir uygulama, işletim sistemi tarafından tanımlanan bellek sınırlarını ihlal ettiğinde anomali tetikleyici, geliştiricilerin bellek sorunlarını belirleyip düzeltmesine yardımcı olmak için uygulamaya özel yığın dökümleri almasına olanak tanır. Ayrıca, aşırı bağlayıcı spam'i için anomali tetikleyici, bağlayıcı işlemlerinde yığın örnekleme profili sağlar.
Bu API geri çağırması, sistem tarafından uygulanan yaptırımlardan önce gerçekleşir. Örneğin, uygulamanın bellek sınırlarını aşması nedeniyle sistem tarafından sonlandırılmasından önce geliştiricilerin hata ayıklama verilerini toplamasına yardımcı olabilir.
val profilingManager =
applicationContext.getSystemService(ProfilingManager::class.java)
val triggers = ArrayList<ProfilingTrigger>()
triggers.add(ProfilingTrigger.Builder(ProfilingTrigger.TRIGGER_TYPE_ANOMALY))
val mainExecutor: Executor = Executors.newSingleThreadExecutor()
val resultCallback = Consumer<ProfilingResult> { profilingResult ->
if (profilingResult.errorCode != ProfilingResult.ERROR_NONE) {
// upload profile result to server for further analysis
setupProfileUploadWorker(profilingResult.resultFilePath)
}
profilingManager.registerForAllProfilingResults(mainExecutor,
resultCallback)
profilingManager.addProfilingTriggers(triggers)
}
JobDebugInfo API'leri
Android 17, geliştiricilerin JobScheduler işlerinde hata ayıklamasına yardımcı olmak için yeni JobDebugInfo API'ler sunuyor. Bu API'ler, işlerin neden çalışmadığı, ne kadar süreyle çalıştığı ve diğer toplu bilgiler hakkında bilgi veriyor.
Genişletilmiş JobDebugInfo API'lerinin ilk yöntemi olan getPendingJobReasonStats(), işin neden bekleyen yürütme durumunda olduğuna dair nedenlerin haritasını ve ilgili kümülatif bekleme sürelerini döndürür. Bu yöntem, planlanmış bir işin neden beklendiği gibi çalışmadığına dair bilgi edinmenizi sağlamak için getPendingJobReasonsHistory() ve getPendingJobReasons() yöntemlerini birleştirir. Ancak hem süreyi hem de iş nedenini tek bir yöntemde kullanılabilir hale getirerek bilgi almayı kolaylaştırır.
Örneğin, belirtilen bir jobId için yöntem, PENDING_JOB_REASON_CONSTRAINT_CHARGING ve 60.000 ms süresini döndürebilir. Bu, şarj kısıtlaması karşılanmadığı için işin 60.000 ms boyunca beklemede olduğunu gösterir.
Boşta kalma sırasında izin verilen alarmlar için dinleyici desteğiyle uyandırma kilitlerini azaltma
Android 17, PendingIntent yerine OnAlarmListener kabul eden yeni bir AlarmManager.setExactAndAllowWhileIdle varyantını kullanıma sunar. Bu yeni geri çağırmaya dayalı mekanizma, şu anda soket bağlantılarını koruyan mesajlaşma uygulamaları gibi periyodik görevleri gerçekleştirmek için sürekli uyandırma kilitlerine dayanan uygulamalar için idealdir.
Gizlilik
Android 17, kullanıcı gizliliğini iyileştirmek için aşağıdaki yeni özellikleri içerir.
Encrypted Client Hello (ECH) platform desteği
Android 17 引入了对加密客户端 Hello (ECH) 的平台支持,这是对网络通信的一项重大隐私增强功能。ECH 是一项 TLS 1.3 扩展,可在初始 TLS 握手期间加密服务器名称指示 (SNI)。这种加密有助于保护用户隐私,因为它可以让网络中介更难识别应用连接到的特定网域。
该平台现在包含网络库实现 ECH 所需的 API。这包括 DnsResolver 中的新功能,用于查询包含 ECH 配置的 HTTPS DNS 记录;以及 Conscrypt 的 SSLEngine 和 SSLSocket 中的新方法,用于在连接到网域时传入这些配置来启用 ECH。开发者可以通过网络安全配置文件中的新 <domainEncryption> 元素来配置 ECH 偏好设置,例如机会性地启用 ECH 或强制使用 ECH,这些设置可全局应用,也可按网域应用。
预计 HttpEngine、WebView 和 OkHttp 等热门联网库将在未来的更新中集成这些平台 API,从而使应用能够更轻松地采用 ECH 并增强用户隐私保护。
如需了解详情,请参阅加密的客户端 Hello 文档。
Android kişi seçici
Android Kişi Seçici, kullanıcıların kişilerle uygulamanız arasında paylaşım yapması için standartlaştırılmış ve göz atılabilir bir arayüzdür. Android 17 (API düzeyi 37) veya sonraki sürümlerin yüklü olduğu cihazlarda kullanılabilen seçici, geniş kapsamlı READ_CONTACTS iznine gizliliği korumaya yönelik bir alternatif sunar. Uygulamanız, kullanıcının tüm adres defterine erişim isteğinde bulunmak yerine ihtiyaç duyduğu veri alanlarını (ör. telefon numaraları veya e-posta adresleri) belirtir ve kullanıcı, paylaşılacak belirli kişileri seçer. Bu sayede uygulamanız yalnızca seçilen verilere okuma erişimi kazanır. Böylece, kullanıcı arayüzünü oluşturmaya veya bakımını yapmaya gerek kalmadan yerleşik arama, profil değiştirme ve çoklu seçim özellikleriyle tutarlı bir kullanıcı deneyimi sunarken ayrıntılı kontrol sağlanır.
Daha fazla bilgi için Kişi seçici dokümanlarına bakın.
Güvenlik
Android 17, cihaz ve uygulama güvenliğini artırmak için aşağıdaki yeni özellikleri ekler.
Android Gelişmiş Koruma Modu (AAPM)
Android Gelişmiş Koruma Modu, Android kullanıcılarına güçlü bir yeni güvenlik özellikleri paketi sunarak kullanıcıları, özellikle de daha yüksek risk altındaki kullanıcıları gelişmiş saldırılardan koruma konusunda önemli bir adım atıyor. İsteğe bağlı bir özellik olarak tasarlanan AAPM, kullanıcıların istediği zaman etkinleştirerek güvenlik korumaları uygulayabileceği tek bir yapılandırma ayarıyla etkinleştirilir.
Bu temel yapılandırmalar arasında bilinmeyen kaynaklardan uygulama yüklenmesini engelleme (yan yükleme), USB veri sinyalini kısıtlama ve Google Play Protect taramasını zorunlu kılma yer alır. Bu yapılandırmalar, cihazın saldırı yüzey alanını önemli ölçüde azaltır.
Geliştiriciler, modun durumunu algılamak için AdvancedProtectionManager API'sini kullanarak bu özellikle entegrasyon yapabilir. Böylece, kullanıcı modu etkinleştirdiğinde uygulamalar otomatik olarak daha sıkı bir güvenlik duruşu benimseyebilir veya yüksek riskli işlevleri kısıtlayabilir.
PQC APK İmzalama
Android 现在支持混合 APK 签名方案,以保护应用的签名身份免受利用量子计算的攻击的潜在威胁。此功能引入了一种新的 APK 签名方案,可让您将经典签名密钥(例如 RSA 或 EC)与新的后量子加密 (PQC) 算法 (ML-DSA) 配对。
这种混合方法可确保您的应用在未来免受量子攻击,同时与依赖于经典签名验证的旧版 Android 和设备保持完全的向后兼容性。
对开发者的影响
- 使用 Play 应用签名的应用:如果您使用 Play 应用签名,可以等待 Google Play 为您提供使用 Google Play 生成的 PQC 密钥升级混合签名的选项,从而确保您的应用受到保护,而无需手动管理密钥。
- 使用自行管理的密钥的应用:自行管理签名密钥的开发者可以利用更新后的 Android build 工具(例如 apksigner)轮换到混合身份,将 PQC 密钥与新的经典密钥相结合。(您必须创建新的经典密钥,无法重复使用旧密钥。)
Bağlantı
Android 17, cihaz ve uygulama bağlantısını iyileştirmek için aşağıdaki özellikleri ekler.
Kısıtlanmış uydu ağları
实现优化,使应用能够在低带宽卫星网络上有效运行。
Kullanıcı deneyimi ve sistem arayüzü
Android 17, kullanıcı deneyimini iyileştirmek için aşağıdaki değişiklikleri içerir.
Özel Asistan ses akışı
Android 17, USAGE_ASSISTANT ile oynatma için Asistan uygulamalarına özel bir Asistan ses akışı sunar. Bu değişiklik, Asistan sesini standart medya akışından ayırarak kullanıcılara her iki ses düzeyi üzerinde de ayrı ayrı kontrol imkanı sunar. Bu sayede, Asistan yanıtlarının duyulabilirliğini korurken medya oynatmayı sessize alma veya tam tersi gibi senaryolar mümkün olur.
Yeni MODE_ASSISTANT_CONVERSATION ses moduna erişimi olan asistan uygulamaları, ses kontrolünün tutarlılığını daha da artırabilir. Asistan uygulamaları, etkin bir Asistan oturumu hakkında sisteme ipucu vermek için bu modu kullanabilir. Böylece Asistan akışının, etkin USAGE_ASSISTANT oynatma dışında veya bağlı Bluetooth çevre birimleriyle kontrol edilmesi sağlanır.
Handoff
切换是 Android 17 中新增的一项功能和 API,应用开发者可以将其集成到应用中,以便为用户提供跨设备连续性。它允许用户在一个 Android 设备上启动应用 activity,然后将其转移到另一个 Android 设备。Handoff 在用户设备的后台运行,并通过各种入口点(例如接收设备上的启动器和任务栏)显示用户附近其他设备上的可用活动。
应用可以指定 Handoff 来启动相同的原生 Android 应用(如果该应用已安装在接收设备上且可供使用)。在此应用到应用流程中,用户通过深层链接跳转到指定 activity。或者,应用到网站切换功能可以作为后备选项提供,也可以通过网址切换功能直接实现。
切换支持是按 activity 实现的。如需启用 Handoff,请针对 activity 调用 setHandoffEnabled() 方法。可能需要随切换传递其他数据,以便接收设备上重新创建的 activity 可以恢复适当的状态。实现 onHandoffActivityDataRequested() 回调以返回 HandoffActivityData 对象,该对象包含用于指定 Handoff 应如何处理并在接收设备上重新创建 activity 的详细信息。
Canlı güncelleme - Anlamsal renk API'si
在 Android 17 中,实时更新启动了语义着色 API,以支持具有通用含义的颜色。
以下类支持语义着色:
NotificationNotification.MetricNotification.ProgressStyle.PointNotification.ProgressStyle.Segment
填色游戏
- 绿色:与安全相关。此颜色应在以下情况下使用:让别人知道您处于安全状态。
- 橙色:用于表示警告和标记物理危险。在用户需要注意以设置更好的保护设置的情况下,应使用此颜色。
- 红色:通常表示危险、停止。它应在需要人们紧急关注的情况下显示。
- 蓝色:中性颜色,适用于信息性内容,应与其他内容区分开来。
以下示例展示了如何将语义样式应用于通知中的文本:
val ssb = SpannableStringBuilder()
.append("Colors: ")
.append("NONE", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_UNSPECIFIED), 0)
.append(", ")
.append("INFO", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_INFO), 0)
.append(", ")
.append("SAFE", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_SAFE), 0)
.append(", ")
.append("CAUTION", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_CAUTION), 0)
.append(", ")
.append("DANGER", Notification.createSemanticStyleAnnotation(SEMANTIC_STYLE_DANGER), 0)
Notification.Builder(context, channelId)
.setSmallIcon(R.drawable.ic_icon)
.setContentTitle("Hello World!")
.setContentText(ssb)
.setOngoing(true)
.setRequestPromotedOngoing(true)
Android 17 için UWB Downlink-TDoA API'si
下行链路到达时间差 (DL-TDoA) 测距技术可让设备通过测量信号的相对到达时间来确定其相对于多个锚点的位置。
以下代码段演示了如何初始化 Ranging Manager、验证设备功能并启动 DL-TDoA 会话:
Kotlin
class RangingApp {
fun initDlTdoa(context: Context) {
// Initialize the Ranging Manager
val rangingManager = context.getSystemService(RangingManager::class.java)
// Register for device capabilities
val capabilitiesCallback = object : RangingManager.RangingCapabilitiesCallback {
override fun onRangingCapabilities(capabilities: RangingCapabilities) {
// Make sure Dl-TDoA is supported before starting the session
if (capabilities.uwbCapabilities != null && capabilities.uwbCapabilities!!.isDlTdoaSupported) {
startDlTDoASession(context)
}
}
}
rangingManager.registerCapabilitiesCallback(Executors.newSingleThreadExecutor(), capabilitiesCallback)
}
fun startDlTDoASession(context: Context) {
// Initialize the Ranging Manager
val rangingManager = context.getSystemService(RangingManager::class.java)
// Create session and configure parameters
val executor = Executors.newSingleThreadExecutor()
val rangingSession = rangingManager.createRangingSession(executor, RangingSessionCallback())
val rangingRoundIndexes = byteArrayOf(0)
val config: ByteArray = byteArrayOf() // OOB config data
val params = DlTdoaRangingParams.createFromFiraConfigPacket(config, rangingRoundIndexes)
val rangingDevice = RangingDevice.Builder().build()
val rawTagDevice = RawRangingDevice.Builder()
.setRangingDevice(rangingDevice)
.setDlTdoaRangingParams(params)
.build()
val dtTagConfig = RawDtTagRangingConfig.Builder(rawTagDevice).build()
val preference = RangingPreference.Builder(DEVICE_ROLE_DT_TAG, dtTagConfig)
.setSessionConfig(SessionConfig.Builder().build())
.build()
// Start the ranging session
rangingSession.start(preference)
}
}
private class RangingSessionCallback : RangingSession.Callback {
override fun onDlTdoaResults(peer: RangingDevice, measurement: DlTdoaMeasurement) {
// Process measurement results here
}
}
Java
public class RangingApp {
public void initDlTdoa(Context context) {
// Initialize the Ranging Manager
RangingManager rangingManager = context.getSystemService(RangingManager.class);
// Register for device capabilities
RangingManager.CapabilitiesCallback capabilitiesCallback = new RangingManager.RangingCapabilitiesCallback() {
@Override
public void onRangingCapabilities(RangingCapabilities capabilities) {
// Make sure Dl-TDoA is supported before starting the session
if (capabilities.getUwbCapabilities() != null && capabilities.getUwbCapabilities().isDlTdoaSupported()) {
startDlTDoASession(context);
}
}
};
rangingManager.registerCapabilitiesCallback(Executors.newSingleThreadExecutor(), capabilitiesCallback);
}
public void startDlTDoASession(Context context) {
RangingManager rangingManager = context.getSystemService(RangingManager.class);
// Create session and configure parameters
Executor executor = Executors.newSingleThreadExecutor();
RangingSession rangingSession = rangingManager.createRangingSession(executor, new RangingSessionCallback());
byte[] rangingRoundIndexes = new byte[] {0};
byte[] config = new byte[0]; // OOB config data
DlTdoaRangingParams params = DlTdoaRangingParams.createFromFiraConfigPacket(config, rangingRoundIndexes);
RangingDevice rangingDevice = new RangingDevice.Builder().build();
RawRangingDevice rawTagDevice = new RawRangingDevice.Builder()
.setRangingDevice(rangingDevice)
.setDlTdoaRangingParams(params)
.build();
RawDtTagRangingConfig dtTagConfig = new RawDtTagRangingConfig.Builder(rawTagDevice).build();
RangingPreference preference = new RangingPreference.Builder(DEVICE_ROLE_DT_TAG, dtTagConfig)
.setSessionConfig(new SessionConfig.Builder().build())
.build();
// Start the ranging session
rangingSession.start(preference);
}
private static class RangingSessionCallback implements RangingSession.Callback {
@Override
public void onDlTdoaResults(RangingDevice peer, DlTdoaMeasurement measurement) {
// Process measurement results here
}
}
}
带外 (OOB) 配置
以下代码段提供了 Wi-Fi 和 BLE 的 DL-TDoA OOB 配置数据示例:
Java
// Wifi Configuration
byte[] wifiConfig = {
(byte) 0xDD, (byte) 0x2D, (byte) 0x5A, (byte) 0x18, (byte) 0xFF, // Header
(byte) 0x5F, (byte) 0x19, // FiRa Sub-Element
(byte) 0x02, (byte) 0x00, // Profile ID
(byte) 0x06, (byte) 0x02, (byte) 0x20, (byte) 0x08, // MAC Address
(byte) 0x14, (byte) 0x01, (byte) 0x0C, // Preamble Index
(byte) 0x27, (byte) 0x02, (byte) 0x08, (byte) 0x07, // Vendor ID
(byte) 0x28, (byte) 0x06, (byte) 0xCA, (byte) 0xC8, (byte) 0xA6, (byte) 0xF7, (byte) 0x6F, (byte) 0x08, // Static STS IV
(byte) 0x08, (byte) 0x02, (byte) 0x60, (byte) 0x09, // Slot Duration
(byte) 0x1B, (byte) 0x01, (byte) 0x0A, // Slots per RR
(byte) 0x09, (byte) 0x04, (byte) 0xE8, (byte) 0x03, (byte) 0x00, (byte) 0x00, // Duration
(byte) 0x9F, (byte) 0x04, (byte) 0x67, (byte) 0x45, (byte) 0x23, (byte) 0x01 // Session ID
};
// BLE Configuration
byte[] bleConfig = {
(byte) 0x2D, (byte) 0x16, (byte) 0xF4, (byte) 0xFF, // Header
(byte) 0x5F, (byte) 0x19, // FiRa Sub-Element
(byte) 0x02, (byte) 0x00, // Profile ID
(byte) 0x06, (byte) 0x02, (byte) 0x20, (byte) 0x08, // MAC Address
(byte) 0x14, (byte) 0x01, (byte) 0x0C, // Preamble Index
(byte) 0x27, (byte) 0x02, (byte) 0x08, (byte) 0x07, // Vendor ID
(byte) 0x28, (byte) 0x06, (byte) 0xCA, (byte) 0xC8, (byte) 0xA6, (byte) 0xF7, (byte) 0x6F, (byte) 0x08, // Static STS IV
(byte) 0x08, (byte) 0x02, (byte) 0x60, (byte) 0x09, // Slot Duration
(byte) 0x1B, (byte) 0x01, (byte) 0x0A, // Slots per RR
(byte) 0x09, (byte) 0x04, (byte) 0xE8, (byte) 0x03, (byte) 0x00, (byte) 0x00, // Duration
(byte) 0x9F, (byte) 0x04, (byte) 0x67, (byte) 0x45, (byte) 0x23, (byte) 0x01 // Session ID
};
如果您无法使用 OOB 配置(因为缺少该配置),或者需要更改不在 OOB 配置中的默认值,则可以使用 DlTdoaRangingParams.Builder 构建参数,如以下代码段所示。您可以使用以下参数代替 DlTdoaRangingParams.createFromFiraConfigPacket():
Kotlin
val dlTdoaParams = DlTdoaRangingParams.Builder(1)
.setComplexChannel(UwbComplexChannel.Builder()
.setChannel(9).setPreambleIndex(10).build())
.setDeviceAddress(deviceAddress)
.setSessionKeyInfo(byteArrayOf(0x01, 0x02, 0x03, 0x04))
.setRangingIntervalMillis(240)
.setSlotDuration(UwbRangingParams.DURATION_2_MS)
.setSlotsPerRangingRound(20)
.setRangingRoundIndexes(byteArrayOf(0x01, 0x05))
.build()
Java
DlTdoaRangingParams dlTdoaParams = new DlTdoaRangingParams.Builder(1)
.setComplexChannel(new UwbComplexChannel.Builder()
.setChannel(9).setPreambleIndex(10).build())
.setDeviceAddress(deviceAddress)
.setSessionKeyInfo(new byte[]{0x01, 0x02, 0x03, 0x04})
.setRangingIntervalMillis(240)
.setSlotDuration(UwbRangingParams.DURATION_2_MS)
.setSlotsPerRangingRound(20)
.setRangingRoundIndexes(new byte[]{0x01, 0x05})
.build();