ویژگی ها و API ها

اندروید ۱۷ ویژگی‌ها و APIهای جدید و فوق‌العاده‌ای را برای توسعه‌دهندگان معرفی می‌کند. بخش‌های زیر این ویژگی‌ها را خلاصه می‌کنند تا به شما در شروع کار با APIهای مرتبط کمک کنند.

برای مشاهده لیست کاملی از APIهای جدید، اصلاح‌شده و حذف‌شده، گزارش تفاوت API را مطالعه کنید. برای جزئیات بیشتر در مورد APIهای جدید، به مرجع API اندروید مراجعه کنید - APIهای جدید برای مشاهده، هایلایت شده‌اند.

همچنین باید حوزه‌هایی را که تغییرات پلتفرم ممکن است بر برنامه‌های شما تأثیر بگذارد، بررسی کنید. برای اطلاعات بیشتر، به صفحات زیر مراجعه کنید:

عملکرد اصلی

اندروید ۱۷ ویژگی‌های جدید زیر را که مربوط به قابلیت‌های اصلی اندروید هستند، اضافه می‌کند.

تریگرهای جدید ProfilingManager

Android 17 向 ProfilingManager 添加了多个新的系统触发器,可帮助您收集深入的数据来调试性能问题。

新增的触发条件包括:

如需了解如何设置系统触发器,请参阅有关基于触发器的分析以及如何检索和分析分析数据的文档

APIهای JobDebugInfo

Android 17 引入了新的 JobDebugInfo API,可帮助开发者调试 其 JobScheduler 作业,包括作业为何未运行、运行了多长时间以及 其他汇总信息。

扩展后的 JobDebugInfo API 的第一个方法是 getPendingJobReasonStats(),该方法会返回一个映射,其中包含作业处于 待执行状态的原因及其各自的累计待执行 时长。此方法将 getPendingJobReasonsHistory()getPendingJobReasons() 方法结合在一起,让您能够了解预定 作业为何未按预期运行,但通过在单个方法中提供时长和作业原因,简化了信息检索。

例如,对于指定的 jobId,该方法可能会返回 PENDING_JOB_REASON_CONSTRAINT_CHARGING 和 60000 毫秒的时长,表明 作业因未满足充电限制而处于待执行状态 60000 毫秒。

حریم خصوصی

اندروید ۱۷ شامل ویژگی‌های جدید زیر برای بهبود حریم خصوصی کاربران است.

انتخابگر مخاطبین اندروید

Android 联系人选择器是一个标准化的可浏览界面,供用户与您的应用分享联系人。该选择器可在搭载 Android 17 或更高版本的设备上使用,可提供一种注重隐私保护的替代方案,以取代范围广泛的 READ_CONTACTS 权限。您的应用不会请求访问用户的整个地址簿,而是指定所需的数据字段(例如电话号码或电子邮件地址),然后用户选择要分享的特定联系人。这只会授予您的应用对所选数据的读取权限,从而确保精细控制,同时提供一致的用户体验,并具有内置的搜索、个人资料切换和多选功能,而无需构建或维护界面。

如需了解详情,请参阅联系人选择器文档

امنیت

اندروید ۱۷ ویژگی‌های جدید زیر را برای بهبود امنیت دستگاه و برنامه‌ها اضافه می‌کند.

حالت حفاظت پیشرفته اندروید (AAPM)

حالت حفاظت پیشرفته اندروید (Android Advanced Protection Mode) مجموعه‌ای قدرتمند و جدید از ویژگی‌های امنیتی را در اختیار کاربران اندروید قرار می‌دهد که گامی مهم در جهت محافظت از کاربران - به‌ویژه کاربران در معرض خطر بیشتر - در برابر حملات پیچیده است. AAPM که به عنوان یک ویژگی اختیاری طراحی شده است، با یک تنظیم پیکربندی واحد فعال می‌شود که کاربران می‌توانند در هر زمان آن را فعال کنند تا مجموعه‌ای از حفاظت‌های امنیتی دلخواه را اعمال کنند.

این تنظیمات اصلی شامل مسدود کردن نصب برنامه‌ها از منابع ناشناخته (سایدلودینگ)، محدود کردن سیگنال‌دهی داده‌های USB و اجباری کردن اسکن Google Play Protect است که به طور قابل توجهی سطح حمله دستگاه را کاهش می‌دهد. توسعه‌دهندگان می‌توانند با استفاده از AdvancedProtectionManager API با این ویژگی ادغام شوند تا وضعیت حالت را تشخیص دهند و برنامه‌ها را قادر سازند تا به طور خودکار یک وضعیت امنیتی سخت‌گیرانه را اتخاذ کنند یا عملکردهای پرخطر را هنگامی که کاربر انتخاب کرده است، محدود کنند.

اتصال

اندروید ۱۷ ویژگی‌های زیر را برای بهبود اتصال دستگاه و برنامه اضافه می‌کند.

شبکه‌های ماهواره‌ای محدود

بهینه‌سازی‌هایی را پیاده‌سازی می‌کند تا برنامه‌ها بتوانند به طور مؤثر در شبکه‌های ماهواره‌ای با پهنای باند کم عمل کنند.

تجربه کاربری و رابط کاربری سیستم

اندروید ۱۷ شامل تغییرات زیر برای بهبود تجربه کاربری است.

تحویل دستی

Handoff یک ویژگی و API جدید است که به اندروید ۱۷ می‌آید و توسعه‌دهندگان برنامه می‌توانند با آن ادغام شوند تا پیوستگی بین دستگاهی را برای کاربران خود فراهم کنند. این قابلیت به کاربر اجازه می‌دهد تا یک فعالیت برنامه را در یک دستگاه اندروید شروع کرده و آن را به دستگاه اندروید دیگری منتقل کند. Handoff در پس‌زمینه دستگاه کاربر اجرا می‌شود و فعالیت‌های موجود از سایر دستگاه‌های مجاور کاربر را از طریق نقاط ورودی مختلف، مانند لانچر و نوار وظیفه، در دستگاه گیرنده نمایش می‌دهد.

برنامه‌ها می‌توانند Handoff را برای اجرای همان برنامه بومی اندروید، در صورتی که روی دستگاه گیرنده نصب و در دسترس باشد، تعیین کنند. در این جریان برنامه به برنامه، کاربر به فعالیت تعیین‌شده عمیقاً متصل است. از طرف دیگر، Handoff برنامه به وب می‌تواند به عنوان یک گزینه جایگزین ارائه شود یا مستقیماً با Handoff URL پیاده‌سازی شود.

پشتیبانی از Handoff بر اساس هر فعالیت پیاده‌سازی می‌شود. برای فعال کردن Handoff، متد setHandoffEnabled() را برای فعالیت فراخوانی کنید. ممکن است لازم باشد داده‌های اضافی همراه با handoff ارسال شوند تا activity بازسازی‌شده روی دستگاه گیرنده بتواند وضعیت مناسب را بازیابی کند. تابع فراخوانی onHandoffActivityRequested() را پیاده‌سازی کنید تا یک شیء HandoffActivityData را برگرداند که حاوی جزئیاتی است که مشخص می‌کند Handoff چگونه باید activity را روی دستگاه گیرنده مدیریت و بازسازی کند.

به‌روزرسانی زنده - API رنگ معنایی

在 Android 17 中,实时更新启动了语义着色 API,以支持具有普遍意义的颜色。

以下类支持语义着色:

填色游戏

  • 绿色:与安全相关。 此颜色应在以下情况下使用:让别人知道您处于安全状态。
  • 橙色:用于表示警告和标记物理危险。当用户需要注意设置更好的保护设置时,应使用此颜色。
  • 红色:通常表示危险,停止。它应在需要紧急引起人们注意的情况下呈现。
  • 蓝色:中性颜色,适用于信息性内容,应与其他内容区分开来。

以下示例展示了如何将语义样式应用于通知中的文本:

  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)

رابط برنامه‌نویسی کاربردی UWB Downlink-TDoA برای اندروید ۱۷

فاصله‌یابی با اختلاف زمان رسیدن سیگنال‌های دریافتی (DL-TDoA) به دستگاه اجازه می‌دهد تا موقعیت خود را نسبت به چندین لنگر با اندازه‌گیری زمان رسیدن نسبی سیگنال‌ها تعیین کند.

قطعه کد زیر نحوه مقداردهی اولیه مدیر محدوده ، تأیید قابلیت‌های دستگاه و شروع یک جلسه DL-TDoA را نشان می‌دهد:

کاتلین

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.CapabilitiesCallback {
            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 = intArrayOf(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
    }
}

جاوا

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.CapabilitiesCallback() {
            @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());
        int[] rangingRoundIndexes = new int[] {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)

قطعه کد زیر نمونه‌ای از داده‌های پیکربندی DL-TDoA OOB برای Wi-Fi و BLE را ارائه می‌دهد:

جاوا

// 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() استفاده کنید:

کاتلین

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()

جاوا

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();