میاناهای برنامه‌سازی کاربردی Android 4.3

سطح ای‌پی‌آی: ۱۸

‫Android 4.3 (JELLY_BEAN_MR2) به‌روزرسانی‌ای برای نسخه Jelly Bean است که ویژگی‌های جدیدی را برای کاربران و توسعه‌دهندگان نرم‌افزار ارائه می‌دهد. این سند مقدمه‌ای بر مهم‌ترین میاناهای برنامه‌سازی کاربردی جدید ارائه می‌دهد.

به‌عنوان توسعه‌دهنده برنامه، باید تصویر سیستم Android 4.3 و پلاتفرم SDK را در اسرع وقت از مدیر SDK بارگیری کنید. اگر دستگاهی با Android نسخه ۴.۳ ندارید که برنامه‌تان را در آن آزمایش کنید، از تصویر سیستم Android نسخه ۴.۳ برای آزمایش برنامه‌تان در شبیه‌ساز Android استفاده کنید. سپس برنامه‌هایتان را در پلاتفرم Android 4.3 بسازید تا بتوانید از جدیدترین میاناهای برنامه‌سازی کاربردی استفاده کنید.

به‌روزرسانی سطح میانای برنامه‌سازی کاربردی هدف

برای بهینه‌سازی بهتر برنامه‌تان برای دستگاه‌هایی که Android نسخه ۴.۳ را اجرا می‌کنند، باید targetSdkVersion را روی "18" تنظیم کنید، آن را روی ایمیج سیستم Android نسخه ۴.۳ نصب کنید، آن را آزمایش کنید، سپس به‌روزرسانی‌ای با این تغییر منتشر کنید.

می‌توانید از میاناهای برنامه‌سازی کاربردی در Android 4.3 استفاده کنید و درعین‌حال با افزودن شرایطی به کدتان که سطح میانای برنامه‌سازی کاربردی سیستم را قبل‌از اجرای میاناهای برنامه‌سازی کاربردی پشتیبانی‌نشده توسط minSdkVersion شما بررسی می‌کند، از نسخه‌های قدیمی‌تر نیز پشتیبانی کنید. برای کسب اطلاعات بیشتر درباره حفظ سازگاری با نسخه‌های قدیمی، پشتیبانی از نسخه‌های مختلف پلاتفرم را بخوانید.

میاناهای برنامه‌سازی کاربردی مختلفی نیز در کتابخانه پشتیبانی Android دردسترس است که به شما امکان می‌دهد ویژگی‌های جدید را در نسخه‌های قدیمی‌تر پلاتفرم پیاده‌سازی کنید.

برای کسب اطلاعات بیشتر درباره نحوه عملکرد سطح میانای برنامه‌سازی کاربردی، سطح میانای برنامه‌سازی کاربردی چیست؟ را بخوانید.

تغییرات مهم در رفتار

اگر قبلاً برنامه‌ای برای Android منتشر کرده‌اید، توجه داشته باشید که ممکن است برنامه‌تان تحت تأثیر تغییرات Android 4.3 قرار گیرد.

اگر برنامه‌تان از هدف‌های ضمنی استفاده می‌کند...

ممکن است برنامه‌تان در محیط نمایه محدودشده درست کار نکند.

کاربران در محیط نمایه محدودشده ممکن است به همه برنامه‌های استاندارد Android دسترسی نداشته باشند. برای مثال، ممکن است در نمایه محدودشده، مرورگر وب و برنامه دوربین غیرفعال باشد. بنابراین برنامه‌تان نباید درباره اینکه کدام برنامه‌ها دردسترس هستند فرضیه‌ای داشته باشد، زیرا اگر startActivity() را بدون تأیید اینکه آیا برنامه‌ای برای رسیدگی به Intent دردسترس است یا نه فراخوانی کنید، ممکن است برنامه‌تان در نمایه محدودشده ازکار بیفتد.

هنگام استفاده از هدف ضمنی، همیشه باید با فراخوانی resolveActivity() یا queryIntentActivities() تأیید کنید که برنامه‌ای برای رسیدگی به هدف دردسترس است. برای مثال:

کاتلین

val intent = Intent(Intent.ACTION_SEND)
...
if (intent.resolveActivity(packageManager) != null) {
    startActivity(intent)
} else {
    Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show()
}

جاوا

Intent intent = new Intent(Intent.ACTION_SEND);
...
if (intent.resolveActivity(getPackageManager()) != null) {
    startActivity(intent);
} else {
    Toast.makeText(context, R.string.app_not_available, Toast.LENGTH_LONG).show();
}

اگر برنامه‌تان به حساب‌ها وابسته است...

ممکن است برنامه‌تان در محیط نمایه محدودشده درست کار نکند.

کاربران در محیط نمایه محدودشده به‌طور پیش‌فرض به حساب‌های کاربری دسترسی ندارند. اگر برنامه‌تان به Account وابسته باشد، ممکن است برنامه‌تان هنگام استفاده در نمایه محدودشده ازکار بیفتد یا رفتار غیرمنتظره‌ای داشته باشد.

اگر می‌خواهید از استفاده نمایه‌های محدودشده از برنامه‌تان به‌طور کامل جلوگیری کنید، چون برنامه‌تان به اطلاعات حساب حساس وابسته است، ویژگی android:requiredAccountType را در عنصر <application> مانیفست خود مشخص کنید.

اگر می‌خواهید به نمایه‌های محدودشده اجازه دهید به استفاده از برنامه‌تان ادامه دهند، حتی اگر نتوانند حساب خودشان را ایجاد کنند، می‌توانید ویژگی‌های برنامه‌تان را که به حساب نیاز دارند غیرفعال کنید یا به نمایه‌های محدودشده اجازه دهید به حساب‌های ایجادشده توسط کاربر اصلی دسترسی داشته باشند. برای اطلاعات بیشتر، بخش زیر را درباره حساب‌های پشتیبانی در نمایه محدود ببینید.

اگر برنامه‌تان از VideoView استفاده می‌کند...

ممکن است ویدیو شما در Android 4.3 کوچک‌تر نشان داده شود.

در نسخه‌های قبلی Android، ابزاره VideoView مقدار "wrap_content" را برای layout_height و layout_width به‌اشتباه برابر با "match_parent" محاسبه می‌کرد. بنابراین، اگرچه استفاده از "wrap_content" برای ارتفاع یا عرض ممکن است قبلاً چیدمان ویدیو موردنظر شما را ارائه کرده باشد، انجام این کار ممکن است منجر به ویدیویی بسیار کوچک‌تر در Android نسخه ۴.۳ و بالاتر شود. برای رفع مشکل، "wrap_content" را با "match_parent" جایگزین کنید و درستی‌سنجی کنید که ویدیوتان طبق انتظار در Android 4.3 و نسخه‌های قدیمی‌تر نشان داده می‌شود.

نمایه‌های محدودشده

در رایانه‌های لوحی Android، کاربران اکنون می‌توانند نمایه‌های محدودشده براساس کاربر اصلی ایجاد کنند. وقتی کاربران نمایه محدودشده ایجاد می‌کنند، می‌توانند محدودیت‌هایی را فعال کنند، مثلاً اینکه کدام برنامه‌ها برای نمایه دردسترس باشد. مجموعه جدیدی از میاناهای برنامه‌سازی کاربردی در Android 4.3 به شما امکان می‌دهد تنظیمات محدودیت دقیقی برای برنامه‌هایی که توسعه می‌دهید ایجاد کنید. برای مثال، بااستفاده از میاناهای برنامه‌سازی کاربردی جدید، می‌توانید به کاربران اجازه دهید نوع محتوای دردسترس در برنامه‌تان را هنگام اجرا در محیط نمایه محدودشده کنترل کنند.

رابط کاربری برای کاربران برای کنترل محدودیت‌هایی که ایجاد کرده‌اید توسط برنامه «تنظیمات» سیستم مدیریت می‌شود. برای اینکه تنظیمات محدودیت برنامه‌تان برای کاربر نمایش داده شود، باید محدودیت‌هایی را که برنامه‌تان ارائه می‌دهد با ایجاد BroadcastReceiver که هدف ACTION_GET_RESTRICTION_ENTRIES را دریافت می‌کند اعلام کنید. سیستم این هدف را برای پرسمان از همه برنامه‌ها درباره محدودیت‌های دردسترس فراخوانی می‌کند، سپس واسط کاربر را می‌سازد تا به کاربر اصلی اجازه دهد محدودیت‌های هر نمایه محدودشده را مدیریت کند.

در روش onReceive() BroadcastReceiver، باید برای هر محدودیتی که برنامه‌تان ارائه می‌دهد، RestrictionEntry ایجاد کنید. هر RestrictionEntry عنوان محدودیت، شرح، و یکی از انواع داده زیر را تعریف می‌کند:

  • TYPE_BOOLEAN برای محدودیتی که درست یا نادرست است.
  • TYPE_CHOICE برای محدودیتی که چندین انتخاب دارد که مانعه‌الجمع هستند (انتخاب‌های دکمه رادیویی).
  • TYPE_MULTI_SELECT برای محدودیتی که چندین انتخاب دارد که مانعه‌الجمع نیستند (انتخاب‌های چارگوش انتخاب).

سپس همه اشیای RestrictionEntry را در یک ArrayList قرار می‌دهید و آن را به‌عنوان مقدار برای EXTRA_RESTRICTIONS_LIST اضافی در نتیجه گیرنده رویداد ثبت‌شده قرار می‌دهید.

سیستم، واسط کاربر را برای محدودیت‌های برنامه‌تان در برنامه «تنظیمات» ایجاد می‌کند و هر محدودیت را با کلید منحصربه‌فردی که برای هر شیء RestrictionEntry ارائه کرده‌اید ذخیره می‌کند. وقتی کاربر برنامه‌تان را باز می‌کند، می‌توانید با فراخوانی getApplicationRestrictions()، محدودیت‌های فعلی را جستجو کنید. این کار یک Bundle برمی‌گرداند که حاوی جفت‌های کلید-مقدار برای هر محدودیتی است که با اشیاء RestrictionEntry تعریف کرده‌اید.

اگر می‌خواهید محدودیت‌های خاص‌تری ارائه دهید که با مقادیر بولی، تک‌انتخابی، و چندانتخابی قابل‌مدیریت نیستند، می‌توانید فعالیتی ایجاد کنید که در آن کاربر بتواند محدودیت‌ها را مشخص کند و به کاربران اجازه دهد آن فعالیت را از تنظیمات محدودیت باز کنند. در گیرنده رویداد ثبت‌شده، EXTRA_RESTRICTIONS_INTENT اضافی را در نتیجه Bundle اضافه کنید. این مورد اضافی باید Intent را مشخص کند که نشان‌دهنده کلاس Activity برای راه‌اندازی است (از روش putParcelable() برای ارسال EXTRA_RESTRICTIONS_INTENT با هدف استفاده کنید). وقتی کاربر اصلی برای تنظیم محدودیت‌های سفارشی وارد فعالیت شما می‌شود، فعالیت شما باید نتیجه‌ای را برگرداند که حاوی مقادیر محدودیت در یک افزونه بااستفاده از کلید EXTRA_RESTRICTIONS_LIST یا EXTRA_RESTRICTIONS_BUNDLE باشد، بسته به اینکه به‌ترتیب اشیاء RestrictionEntry یا جفت‌های کلید-مقدار را مشخص کنید.

حساب‌های پشتیبانی در نمایه محدودشده

هر حسابی که به کاربر اصلی اضافه شود برای نمایه محدودشده دردسترس است، اما حساب‌ها به‌طور پیش‌فرض ازطریق میاناهای برنامه‌سازی کاربردی AccountManager قابل‌دسترسی نیستند. اگر بخواهید حسابی با AccountManager در نمایه محدودشده اضافه کنید، نتیجه ناموفق دریافت خواهید کرد. به‌دلیل این محدودیت‌ها، سه گزینه زیر را دارید:

  • اجازه دادن به دسترسی به حساب‌های مالک از نمایه محدودشده.

    برای دسترسی به حساب از نمایه محدودشده، باید مشخصه android:restrictedAccountType را به برچسب <application> اضافه کنید:

    <application ...
        android:restrictedAccountType="com.example.account.type" >

    احتیاط: فعال کردن این مشخصه به برنامه شما امکان می‌دهد از نمایه‌های محدودشده به حساب‌های کاربر اصلی دسترسی داشته باشد. بنابراین، فقط درصورتی باید این کار را مجاز کنید که اطلاعات نمایش‌داده‌شده توسط برنامه‌تان اطلاعات شناساننده شخصی (PII) را که حساس تلقی می‌شود آشکار نکند. تنظیمات سیستم به کاربر اصلی اطلاع می‌دهد که برنامه شما به حساب‌هایشان نمایه‌های محدودشده اعطا می‌کند، بنابراین باید برای کاربر واضح باشد که دسترسی به حساب برای عملکرد برنامه‌تان مهم است. درصورت امکان، باید کنترل‌های محدودیت کافی برای کاربر اصلی ارائه دهید که مشخص کند چه مقدار دسترسی به حساب در برنامه‌تان مجاز است.

  • غیرفعال کردن برخی‌از عملکردها درصورت عدم امکان اصلاح حساب‌ها.

    اگر می‌خواهید از حساب‌ها استفاده کنید، اما درواقع برای عملکرد اصلی برنامه‌تان به آن‌ها نیاز ندارید، می‌توانید دردسترس بودن حساب را بررسی کنید و ویژگی‌ها را درصورت دردسترس نبودن غیرفعال کنید. ابتدا باید بررسی کنید که آیا حساب موجودی دردسترس است یا نه. اگر نه، پس پرس‌وجو کنید که آیا امکان ایجاد حساب جدید با فراخوانی getUserRestrictions() وجود دارد یا نه و DISALLOW_MODIFY_ACCOUNTS اضافی را در نتیجه بررسی کنید. اگر true است، باید هر عملکردی را در برنامه‌تان که به دسترسی به حساب‌ها نیاز دارد غیرفعال کنید. برای مثال:

    کاتلین

    val um = context.getSystemService(Context.USER_SERVICE) as UserManager
    val restrictions: Bundle = um.userRestrictions
    if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
        // cannot add accounts, disable some functionality
    }

    جاوا

    UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
    Bundle restrictions = um.getUserRestrictions();
    if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
        // cannot add accounts, disable some functionality
    }

    توجه: در این سناریو، نباید هیچ مشخصه جدیدی را در فایل مانیفست خود اعلام کنید.

  • وقتی نمی‌توانید به حساب‌های خصوصی دسترسی داشته باشید، برنامه‌تان را غیرفعال کنید.

    اگر درعوض مهم است که برنامه‌تان برای نمایه‌های محدودشده دردسترس نباشد چون برنامه‌تان به اطلاعات شخصی حساس در حساب وابسته است (و چون نمایه‌های محدودشده درحال‌حاضر نمی‌توانند حساب جدید اضافه کنند)، مشخصه android:requiredAccountType را به برچسب <application> اضافه کنید:

    <application ...
        android:requiredAccountType="com.example.account.type" >

    برای مثال، برنامه Gmail از این ویژگی برای غیرفعال کردن خودش برای نمایه‌های محدودشده استفاده می‌کند، زیرا ایمیل شخصی مالک نباید برای نمایه‌های محدودشده دردسترس باشد.

  • بی‌سیم و اتصال‌پذیری

    بلوتوث کم‌مصرف (Smart Ready)

    اکنون Android از «بلوتوث کم‌مصرف» (LE) با میاناهای برنامه‌سازی کاربردی جدید در android.bluetooth پشتیبانی می‌کند. با میاناهای برنامه‌سازی کاربردی جدید، می‌توانید برنامه‌های Android بسازید که با لوازم جانبی «بلوتوث کم‌مصرف» مثل نمایشگرهای ضربان قلب و گام‌شمارها ارتباط برقرار می‌کنند.

    ازآنجایی‌که «بلوتوث کم‌مصرف» یک ویژگی سخت‌افزاری است که در همه دستگاه‌های مجهز به Android دردسترس نیست، باید در فایل مانیفست خود یک عنصر <uses-feature> برای "android.hardware.bluetooth_le" اعلام کنید:

    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />

    اگر ازقبل با میاناهای برنامه‌سازی کاربردی «بلوتوث کلاسیک» Android آشنا هستید، توجه داشته باشید که استفاده از میاناهای برنامه‌سازی کاربردی «بلوتوث کم‌مصرف» تفاوت‌هایی دارد. مهم‌تر از همه اینکه اکنون کلاس BluetoothManager وجود دارد که باید برای برخی‌از عملیات‌های سطح بالا از آن استفاده کنید، مثلاً برای دریافت BluetoothAdapter، دریافت فهرست دستگاه‌های متصل، و بررسی وضعیت دستگاه. برای مثال، در اینجا نحوه دریافت BluetoothAdapter آورده شده است:

    کاتلین

    val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
    bluetoothAdapter = bluetoothManager.adapter

    جاوا

    final BluetoothManager bluetoothManager =
            (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    bluetoothAdapter = bluetoothManager.getAdapter();

    برای پیدا کردن دستگاه‌های جانبی «بلوتوث کم‌مصرف»، startLeScan() را در BluetoothAdapter فراخوانی کنید و پیاده‌سازی میانای BluetoothAdapter.LeScanCallback را به آن ارسال کنید. وقتی آداپتور بلوتوث یک دستگاه جانبی «بلوتوث کم‌مصرف» را شناسایی می‌کند، پیاده‌سازی BluetoothAdapter.LeScanCallback شما تماسی با روش onLeScan() دریافت می‌کند. این روش یک شیء BluetoothDevice را دراختیارتان قرار می‌دهد که نشان‌دهنده دستگاه شناسایی‌شده، مقدار RSSI برای دستگاه، و آرایه بایت حاوی سوابق تبلیغاتی دستگاه است.

    اگر می‌خواهید فقط انواع خاصی از دستگاه‌های جانبی را اسکن کنید، می‌توانید به‌جای آن startLeScan() را فراخوانی کنید و آرایه‌ای از اشیاء UUID را که سرویس‌های GATT پشتیبانی‌شده توسط برنامه‌تان را مشخص می‌کنند اضافه کنید.

    توجه: فقط می‌توانید دستگاه‌های «بلوتوث کم‌مصرف» را اسکن کنید یا دستگاه‌های «بلوتوث کلاسیک» را بااستفاده از میاناهای برنامه‌سازی کاربردی قبلی اسکن کنید. نمی‌توانید دستگاه‌های بلوتوث کم‌مصرف و کلاسیک را به‌طور هم‌زمان اسکن کنید.

    سپس برای اتصال به دستگاه جانبی «بلوتوث کم‌مصرف»، connectGatt() را در شیء BluetoothDevice مربوطه فراخوانی کنید و پیاده‌سازی BluetoothGattCallback را به آن منتقل کنید. پیاده‌سازی شما از BluetoothGattCallback تماس‌های برگشتی مربوط به وضعیت اتصال با دستگاه و رویدادهای دیگر را دریافت می‌کند. درطول onConnectionStateChange() فراخوانی برگشتی است که می‌توانید ارتباط با دستگاه را شروع کنید، اگر روش STATE_CONNECTED را به‌عنوان وضعیت جدید رد کند.

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

    حالت فقط اسکن Wi-Fi

    هنگام تلاش برای شناسایی مکان کاربر، Android ممکن است از Wi-Fi برای کمک به تعیین مکان ازطریق اسکن نقاط دسترسی اطراف استفاده کند. بااین‌حال، کاربران اغلب Wi-Fi را خاموش نگه می‌دارند تا در مصرف باتری صرفه‌جویی کنند، که این امر منجر به داده‌های مکان با دقت کمتر می‌شود. Android اکنون شامل حالت فقط اسکن است که به Wi-Fi دستگاه اجازه می‌دهد نقاط دسترسی را اسکن کند تا به دریافت مکان بدون اتصال به نقطه دسترسی کمک کند، بنابراین مصرف باتری را به‌طور قابل‌توجهی کاهش می‌دهد.

    اگر می‌خواهید مکان کاربر را به‌دست آورید اما Wi-Fi درحال‌حاضر خاموش است، می‌توانید از کاربر درخواست کنید با فراخوانی startActivity() با کنش ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE، حالت فقط اسکن Wi-Fi را فعال کند.

    پیکربندی Wi-Fi

    میاناهای برنامه‌سازی کاربردی جدید WifiEnterpriseConfig به سرویس‌های سازمانی اجازه می‌دهد پیکربندی Wi-Fi را برای دستگاه‌های مدیریت‌شده خودکارسازی کنند.

    پاسخ سریع برای تماس‌های ورودی

    از Android 4.0، ویژگی‌ای به‌نام «پاسخ سریع» به کاربران امکان می‌دهد به تماس‌های ورودی با پیامک فوری پاسخ دهند، بدون اینکه لازم باشد به تماس پاسخ دهند یا قفل دستگاه را باز کنند. تاکنون، این پیام‌های سریع همیشه توسط برنامه «پیام‌رسانی» پیش‌فرض مدیریت می‌شدند. اکنون هر برنامه‌ای می‌تواند با ایجاد Service با فیلتر قصد برای ACTION_RESPOND_VIA_MESSAGE، توانایی خود را برای مدیریت این پیام‌ها اعلام کند.

    وقتی کاربر با پاسخ سریع به تماس ورودی پاسخ می‌دهد، برنامه «تلفن» هدف ACTION_RESPOND_VIA_MESSAGE را با URI توصیف‌کننده گیرنده (تماس‌گیرنده) و EXTRA_TEXT اضافی با پیامی که کاربر می‌خواهد ارسال کند ارسال می‌کند. وقتی سرویس شما هدف را دریافت می‌کند، باید پیام را تحویل دهد و فوراً خودش را متوقف کند (برنامه شما نباید فعالیتی را نشان دهد).

    برای دریافت این هدف، باید اجازه SEND_RESPOND_VIA_MESSAGE را اعلام کنید.

    چندرسانه‌ای

    بهبودهای MediaExtractor و MediaCodec

    اکنون Android بااستفاده از میاناهای برنامه‌سازی کاربردی موجود در MediaCodec و MediaExtractor، نوشتن پخش‌کننده‌های «جاری‌سازی تطبیقی پویا ازطریق HTTP»‏ (DASH) را مطابق با استاندارد ISO/IEC 23009-1 برای شما آسان‌تر می‌کند. چارچوب زیربنایی این میاناهای برنامه‌سازی کاربردی برای پشتیبانی از تجزیه فایل‌های MP4 تکه‌تکه‌شده به‌روز شده است، اما برنامه شما همچنان مسئول تجزیه فراداده MPD و ارسال جریان‌های جداگانه به MediaExtractor است.

    اگر می‌خواهید از DASH با محتوای رمزگذاری‌شده استفاده کنید، توجه داشته باشید که روش getSampleCryptoInfo() فراداده MediaCodec.CryptoInfo را برمی‌گرداند که ساختار هر نمونه رسانه رمزگذاری‌شده را توصیف می‌کند. همچنین، روش getPsshInfo() به MediaExtractor اضافه شده است تا بتوانید به فراداده PSSH برای رسانه DASH خود دسترسی داشته باشید. این روش نقشه‌ای از اشیاء UUID را به بایت برمی‌گرداند، به‌طوری‌که UUID طرح رمزنگاری را مشخص می‌کند و بایت‌ها داده‌های خاص آن طرح هستند.

    مدیریت حقوق دیجیتال رسانه

    کلاس جدید MediaDrm با جدا کردن مسائل مربوط به DRM از بازپخش رسانه، راه‌حلی مدولار برای مدیریت حقوق دیجیتال (DRM) با محتوای رسانه‌ای شما ارائه می‌دهد. برای مثال، این جداسازی میانای برنامه‌سازی کاربردی به شما امکان می‌دهد محتوای رمزگذاری‌شده Widevine را بدون نیاز به استفاده از قالب رسانه Widevine بازپخش کنید. این راهکار DRM از «رمزگذاری مشترک DASH» نیز پشتیبانی می‌کند تا بتوانید از طرح‌های DRM مختلفی برای محتوای جاری‌سازی‌تان استفاده کنید.

    می‌توانید از MediaDrm برای دریافت پیام‌های درخواست کلید مبهم و پردازش پیام‌های پاسخ کلید از سرور برای دریافت و تدارک پروانه استفاده کنید. برنامه شما مسئولیت مدیریت ارتباط شبکه با سرورها را برعهده دارد؛ کلاس MediaDrm فقط توانایی تولید و پردازش پیام‌ها را فراهم می‌کند.

    MediaDrm APIها برای استفاده همراه با MediaCodec APIهایی که در Android 4.1 (سطح API ‏۱۶) معرفی شدند درنظر گرفته شده‌اند، ازجمله MediaCodec برای کدبندی و رمزگشایی محتوای شما، MediaCrypto برای مدیریت محتوای رمزگذاری‌شده، و MediaExtractor برای استخراج و دی‌مالتی‌پلکس کردن محتوای شما.

    ابتدا باید اشیاء MediaExtractor و MediaCodec را بسازید. سپس می‌توانید به طرح DRM شناسایی‌کننده UUID، معمولاً از فراداده در محتوا، دسترسی پیدا کنید و از آن برای ساختن نمونه‌ای از شیء MediaDrm با سازنده آن استفاده کنید.

    کدبندی ویدیو از Surface

    Android 4.1 (سطح میانای برنامه‌سازی کاربردی ۱۶) کلاس MediaCodec را برای کدبندی و کدگشایی سطح پایین محتوای رسانه‌ای اضافه کرد. هنگام کدبندی ویدیو، Android 4.1 لازم می‌دانست که رسانه را با آرایه ByteBuffer ارائه دهید، اما Android 4.3 اکنون به شما امکان می‌دهد از Surface به‌عنوان ورودی کدبند استفاده کنید. برای مثال، این کار به شما امکان می‌دهد ورودی را از یک فایل ویدیویی موجود یا بااستفاده از فریم‌های تولیدشده از OpenGL ES کدبندی کنید.

    برای استفاده از Surface به‌عنوان ورودی برای کدبند، ابتدا configure() را برای MediaCodec فراخوانی کنید. سپس createInputSurface() را فراخوانی کنید تا Surface را دریافت کنید که براساس آن می‌توانید رسانه‌تان را جاری‌سازی کنید.

    برای مثال، می‌توانید از Surface داده‌شده به‌عنوان پنجره‌ای برای بافت OpenGL با ارسال آن به eglCreateWindowSurface() استفاده کنید. سپس هنگام رندر کردن سطح، eglSwapBuffers() را فراخوانی کنید تا قاب به MediaCodec منتقل شود.

    برای شروع کدبندی، start() را در MediaCodec فراخوانی کنید. وقتی کارتان تمام شد، برای پایان دادن به کدبندی، signalEndOfInputStream() را فراخوانی کنید و release() را در Surface فراخوانی کنید.

    ادغام رسانه

    کلاس جدید MediaMuxer امکان تسهیم‌سازی بین یک جاری‌سازی صوتی و یک جاری‌سازی ویدیویی را فراهم می‌کند. این میاناهای برنامه‌سازی کاربردی به‌عنوان همتای کلاس MediaExtractor که در Android 4.2 برای جداسازی (demuxing) رسانه اضافه شده است عمل می‌کنند.

    قالب‌های خروجی پشتیبانی‌شده در MediaMuxer.OutputFormat تعریف شده‌اند. درحال‌حاضر، MP4 تنها قالب خروجی پشتیبانی‌شده است و MediaMuxer درحال‌حاضر فقط از یک جاری‌سازی صوتی و/یا یک جاری‌سازی ویدیویی در هر زمان پشتیبانی می‌کند.

    MediaMuxer عمدتاً برای کار با MediaCodec طراحی شده است بنابراین می‌توانید پردازش ویدیو را ازطریق MediaCodec انجام دهید و سپس خروجی را ازطریق MediaMuxer در فایل MP4 ذخیره کنید. همچنین می‌توانید از MediaMuxer در ترکیب با MediaExtractor برای ویرایش رسانه بدون نیاز به کدبندی یا کدگشایی استفاده کنید.

    پیشرفت بازپخش و پاک‌سازی برای RemoteControlClient

    در Android 4.0 (سطح API‏ ۱۴)، RemoteControlClient اضافه شد تا کنترل‌های بازپخش رسانه از مشتریان کنترل از راه دور، مانند کنترل‌های موجود در صفحه قفل، فعال شود. Android 4.3 اکنون این امکان را برای چنین کنترل‌کننده‌هایی فراهم می‌کند تا موقعیت بازپخش و کنترل‌های مربوط به پیمایش بازپخش را نمایش دهند. اگر کنترل از راه دور را برای برنامه رسانه‌تان با RemoteControlClient API فعال کرده‌اید، می‌توانید با پیاده‌سازی دو میانای جدید، امکان جابه‌جایی در پخش را فراهم کنید.

    ابتدا باید پرچم FLAG_KEY_MEDIA_POSITION_UPDATE را با ارسال آن به setTransportControlsFlags() فعال کنید.

    سپس دو میانای جدید زیر را پیاده‌سازی کنید:

    RemoteControlClient.OnGetPlaybackPositionListener
    این شامل فراخوانی برگشتی onGetPlaybackPosition() است که موقعیت فعلی رسانه شما را زمانی که کنترل از راه دور نیاز به به‌روزرسانی پیشرفت در واسط کاربری خود دارد، درخواست می‌کند.
    RemoteControlClient.OnPlaybackPositionUpdateListener
    این شامل فراخوانی برگشتی onPlaybackPositionUpdate() است که وقتی کاربر با رابط کاربری کنترل از راه دور بازپخش را جابه‌جا می‌کند، کد زمان جدید رسانه را به برنامه شما می‌گوید.

    وقتی بازپخش را با موقعیت جدید به‌روز کردید، setPlaybackState() را فراخوانی کنید تا وضعیت، موقعیت، و سرعت بازپخش جدید را نشان دهید.

    با تعریف این میاناهای کاربری، می‌توانید آن‌ها را با فراخوانی setOnGetPlaybackPositionListener() و setPlaybackPositionUpdateListener() برای RemoteControlClient خود تنظیم کنید.

    گرافیک‌

    پشتیبانی از OpenGL ES 3.0

    Android 4.3 میاناهای Java و پشتیبانی بومی برای OpenGL ES 3.0 را اضافه می‌کند. عملکرد جدید کلیدی ارائه‌شده در OpenGL ES 3.0 شامل موارد زیر است:

    • شتاب‌دهی جلوه‌های دیداری پیشرفته
    • فشرده‌سازی بافت ETC2/EAC با کیفیت بالا به‌عنوان ویژگی استاندارد
    • نسخه جدیدی از زبان سایه‌زنی GLSL ES با پشتیبانی از عدد صحیح و ممیز شناور ۳۲ بیتی
    • پرداز کردن بافت پیشرفته
    • استانداردسازی گسترده‌تر اندازه بافت و قالب‌های میان‌گیر رندر

    میانای Java برای OpenGL ES 3.0 در Android با GLES30 ارائه می‌شود. هنگام استفاده از OpenGL ES 3.0، حتماً آن را در فایل مانیفست خود با برچسب <uses-feature> و مشخصه android:glEsVersion اعلام کنید. برای مثال:

    <manifest>
        <uses-feature android:glEsVersion="0x00030000" />
        ...
    </manifest>

    و به‌خاطر داشته باشید که بافتار OpenGL ES را با فراخوانی setEGLContextClientVersion() مشخص کنید، و 3 را به‌عنوان نسخه ارسال کنید.

    برای اطلاعات بیشتر درباره استفاده از OpenGL ES، ازجمله نحوه بررسی نسخه OpenGL ES پشتیبانی‌شده دستگاه در زمان اجرا، به راهنمای API OpenGL ES مراجعه کنید.

    ‫Mipmapping برای drawables

    استفاده از mipmap به‌عنوان منبع برای بیت‌مپ یا drawable روشی ساده برای ارائه تصویر باکیفیت و مقیاس‌های مختلف تصویر است که به‌ویژه اگر انتظار دارید تصویرتان درطول پویانمایی مقیاس‌بندی شود، می‌تواند مفید باشد.

    Android 4.2 (سطح میانای برنامه‌سازی کاربردی ۱۷) پشتیبانی از mipmap را در کلاس Bitmap اضافه کرد—وقتی منبع mipmap را ارائه کرده باشید و setHasMipMap() را فعال کرده باشید، Android تصاویر mip را در Bitmap شما جابه‌جا می‌کند. اکنون در Android 4.3، می‌توانید mipmap را برای شیء BitmapDrawable نیز فعال کنید، با ارائه دارایی mipmap و تنظیم ویژگی android:mipMap در فایل منبع bitmap یا با فراخوانی hasMipMap().

    واسط کاربر

    مشاهده رونهادها

    کلاس جدید ViewOverlay لایه‌ای شفاف روی View ارائه می‌دهد که می‌توانید محتوای دیداری به آن اضافه کنید و بر سلسله‌مراتب چیدمان تأثیر نمی‌گذارد. با تماس با getOverlay() می‌توانید برای هر View، ViewOverlay دریافت کنید. هم‌پوشانی همیشه اندازه و موقعیتی مشابه با نمای میزبان خود دارد (نمایی که از آن ایجاد شده است)، به شما امکان می‌دهد محتوایی را اضافه کنید که در جلوی نمای میزبان ظاهر می‌شود، اما نمی‌تواند حدود آن نمای میزبان را گسترش دهد.

    استفاده از ViewOverlay به‌ویژه زمانی مفید است که می‌خواهید پویانمایی‌هایی مانند لغزاندن یک نما به خارج از ظرف آن یا جابه‌جا کردن موارد در صفحه ایجاد کنید، بدون اینکه بر سلسله‌مراتب نما تأثیر بگذارد. اما چون ناحیه قابل‌استفاده هم‌پوشانی به همان ناحیه نمای میزبانش محدود است، اگر می‌خواهید نمای متحرکی را خارج از موقعیتش در چیدمان پویانمایی کنید، باید از هم‌پوشانی نمای والدی استفاده کنید که حدود چیدمان موردنظر را داشته باشد.

    وقتی رونهادی برای نمای ابزاره‌ای مثل Button ایجاد می‌کنید، می‌توانید با فراخوانی add(Drawable)، اشیای Drawable را به رونهاد اضافه کنید. اگر getOverlay() را برای نمای چیدمان، مثلاً RelativeLayout، فراخوانی کنید، شیء برگردانده‌شده ViewGroupOverlay است. کلاس ViewGroupOverlay زیرکلاسی از ViewOverlay است که به شما امکان می‌دهد با فراخوانی add(View)، اشیاء View را نیز اضافه کنید.

    توجه: همه نماها و موارد قابل‌رسمی که به هم‌پوشانی اضافه می‌کنید فقط بصری هستند. آن‌ها نمی‌توانند رویدادهای ورودی یا تمرکز را دریافت کنند.

    برای مثال، کد زیر با قرار دادن نما در هم‌پوشانی نمای اصلی و سپس اجرای پویانمایی ترجمه روی آن نما، نمای لغزنده به راست را پویانمایی می‌کند:

    کاتلین

    val view: View? = findViewById(R.id.view_to_remove)
    val container: ViewGroup? = view?.parent as ViewGroup
    
    container?.apply {
        overlay.add(view)
        ObjectAnimator.ofFloat(view, "translationX", right.toFloat())
                .start()
    }

    جاوا

    View view = findViewById(R.id.view_to_remove);
    ViewGroup container = (ViewGroup) view.getParent();
    container.getOverlay().add(view);
    ObjectAnimator anim = ObjectAnimator.ofFloat(view, "translationX", container.getRight());
    anim.start();

    چیدمان محدوده‌های نوری

    برای نماهایی که حاوی تصاویر پس‌زمینه nine-patch هستند، اکنون می‌توانید مشخص کنید که باید براساس مرزهای «اپتیکال» تصویر پس‌زمینه با نماهای مجاور تراز شوند، نه براساس مرزهای «برش» نما.

    برای مثال، شکل‌های ۱ و ۲ هرکدام چیدمان یکسانی را نشان می‌دهند، اما نسخه در شکل ۱ از مرزهای برش (رفتار پیش‌فرض) استفاده می‌کند، درحالی‌که شکل ۲ از مرزهای نوری استفاده می‌کند. چون تصاویر nine-patch استفاده‌شده برای دکمه و قاب عکس شامل حاشیه داخلی در اطراف لبه‌ها هستند، هنگام استفاده از مرزهای برش، به‌نظر نمی‌رسد که با یکدیگر یا نوشتار تراز باشند.

    توجه: در نماگرفت شکل‌های ۱ و ۲، تنظیم توسعه‌دهنده «نمایش مرزهای چیدمان» فعال است. برای هر نما، خطوط قرمز نشان‌دهنده مرزهای نوری، خطوط آبی نشان‌دهنده مرزهای برش، و رنگ صورتی نشان‌دهنده حاشیه‌ها است.

    شکل ۱. چیدمان بااستفاده از مرزهای کلیپ (پیش‌فرض).

    شکل ۲. چیدمان بااستفاده از مرزهای نوری.

    برای تراز کردن نماها براساس حدود نوری آن‌ها، مشخصه android:layoutMode را در یکی از چیدمان‌های ولی روی "opticalBounds" تنظیم کنید. برای مثال:

    <LinearLayout android:layoutMode="opticalBounds" ... >

    شکل ۳. نمای بزرگ‌شده از دکمه Holo با نه وصله با مرزهای نوری.

    برای اینکه این کار انجام شود، تصاویر nine-patch اعمال‌شده در پس‌زمینه نماهایتان باید مرزهای نوری را بااستفاده از خطوط قرمز در امتداد پایین و سمت راست فایل nine-patch مشخص کنند (همان‌طور که در شکل ۳ نشان داده شده است). خطوط قرمز نشان‌دهنده منطقه‌ای است که باید از مرزهای کلیپ کم شود تا مرزهای نوری تصویر باقی بماند.

    وقتی مرزهای نوری را برای ViewGroup در چیدمانتان فعال می‌کنید، همه نماهای فرزند حالت چیدمان مرزهای نوری را به ارث می‌برند، مگراینکه آن را برای گروهی با تنظیم android:layoutMode روی "clipBounds" لغو کنید. همه عناصر چیدمان همچنین از مرزهای نوری نماهای فرزند خود پیروی می‌کنند و مرزهای خود را براساس مرزهای نوری نماهای درون خود تطبیق می‌دهند. بااین‌حال، عناصر چیدمان (زیرکلاس‌های ViewGroup) درحال‌حاضر از مرزهای نوری برای تصاویر nine-patch اعمال‌شده در پس‌زمینه خودشان پشتیبانی نمی‌کنند.

    اگر با زیرکلاس‌بندی View، ViewGroup، یا هر زیرکلاس دیگری از آن‌ها نمای سفارشی ایجاد کنید، نمای شما این رفتارهای مرز نوری را به ارث خواهد برد.

    توجه: همه ابزاره‌های پشتیبانی‌شده توسط زمینه Holo با مرزهای نوری به‌روزرسانی شده‌اند، ازجمله Button، Spinner، EditText، و غیره. بنابراین اگر برنامه‌تان از طرح زمینه Holo استفاده می‌کند (Theme.Holo،‏ Theme.Holo.Light، و غیره)، می‌توانید با تنظیم مشخصه android:layoutMode روی "opticalBounds" فوراً از آن بهره‌مند شوید.

    برای مشخص کردن مرزهای نوری برای تصاویر nine-patch خودتان با ابزار Draw 9-patch، هنگام کلیک کردن روی پیکسل‌های حاشیه، کلید Control را نگه دارید.

    پویانمایی برای مقادیر Rect

    اکنون می‌توانید با RectEvaluator جدید بین دو مقدار Rect پویانمایی کنید. این کلاس جدید پیاده‌سازی TypeEvaluator است که می‌توانید به ValueAnimator.setEvaluator() منتقل کنید.

    شنونده فوکوس و پیوست پنجره

    قبلاً اگر می‌خواستید بدانید چه زمانی نمای شما به پنجره متصل/جدا شده است یا چه زمانی تمرکز آن تغییر کرده است، باید کلاس View را لغو می‌کردید تا به‌ترتیب onAttachedToWindow() و onDetachedFromWindow()، یا onWindowFocusChanged() را پیاده‌سازی کنید.

    اکنون، برای دریافت رویدادهای متصل کردن و جدا کردن، می‌توانید به‌جای آن ViewTreeObserver.OnWindowAttachListener را پیاده‌سازی کنید و آن را در نمایی با addOnWindowAttachListener() تنظیم کنید. و برای دریافت رویدادهای تمرکز، می‌توانید ViewTreeObserver.OnWindowFocusChangeListener را پیاده‌سازی کنید و آن را در نمایی با addOnWindowFocusChangeListener() تنظیم کنید.

    پشتیبانی از اسکن بیش‌ازحد تلویزیون

    برای اطمینان از اینکه برنامه‌تان کل صفحه را در هر تلویزیونی پر می‌کند، اکنون می‌توانید اسکن بیش‌ازحد را برای چیدمان برنامه‌تان فعال کنید. حالت Overscan با پرچم FLAG_LAYOUT_IN_OVERSCAN تعیین می‌شود که می‌توانید آن را با زمینه‌های پلاتفرم مانند Theme_DeviceDefault_NoActionBar_Overscan یا با فعال کردن سبک windowOverscan در زمینه سفارشی فعال کنید.

    جهت صفحه‌نمایش

    مشخصه screenOrientation برچسب <activity> اکنون از مقادیر بیشتری برای رعایت اولویت کاربر برای چرخش خودکار پشتیبانی می‌کند:

    "userLandscape"
    رفتاری مشابه "sensorLandscape" دارد، به‌جز زمانی که کاربر چرخش خودکار را غیرفعال کند که دراین‌صورت در جهت افقی عادی قفل می‌شود و وارونه نمی‌شود.
    "userPortrait"
    رفتاری مشابه "sensorPortrait" دارد، با این تفاوت که اگر کاربر چرخش خودکار را غیرفعال کند، در جهت عمودی عادی قفل می‌شود و وارونه نخواهد شد.
    "fullUser"
    رفتاری مشابه "fullSensor" دارد و امکان چرخش در هر چهار جهت را فراهم می‌کند، به‌جز زمانی که کاربر چرخش خودکار را غیرفعال کند که دراین‌صورت در جهت دلخواه کاربر قفل می‌شود.

    علاوه‌براین، اکنون می‌توانید "locked" را نیز اعلام کنید تا جهت برنامه شما را در جهت فعلی صفحه‌نمایش قفل کند.

    پویانمایی‌های چرخش

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

    توجه: این پویانمایی‌ها فقط درصورتی دردسترس است که فعالیتتان را برای استفاده از حالت «تمام‌صفحه» تنظیم کرده باشید، که می‌توانید آن را با زمینه‌هایی مثل Theme.Holo.NoActionBar.Fullscreen فعال کنید.

    برای مثال، در اینجا نحوه فعال کردن پویانمایی «محو تدریجی متقاطع» آورده شده است:

    کاتلین

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        val params: WindowManager.LayoutParams = window.attributes
        params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE
        window.attributes = params
        ...
    }

    جاوا

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        WindowManager.LayoutParams params = getWindow().getAttributes();
        params.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
        getWindow().setAttributes(params);
        ...
    }

    درونداد کاربر

    انواع حسگر جدید

    حسگر جدید TYPE_GAME_ROTATION_VECTOR به شما امکان می‌دهد چرخش‌های دستگاه را بدون نگرانی درباره تداخل‌های مغناطیسی تشخیص دهید. برخلاف حسگر TYPE_ROTATION_VECTOR، TYPE_GAME_ROTATION_VECTOR براساس شمال مغناطیسی نیست.

    حسگرهای جدید TYPE_GYROSCOPE_UNCALIBRATED و TYPE_MAGNETIC_FIELD_UNCALIBRATED داده‌های خام حسگر را بدون درنظر گرفتن برآوردهای سوگیری ارائه می‌دهند. یعنی حسگرهای TYPE_GYROSCOPE و TYPE_MAGNETIC_FIELD موجود داده‌های حسگری را ارائه می‌دهند که به‌ترتیب انحراف تخمینی ناشی از رانش ژیروسکوپ و آهن سخت را در دستگاه درنظر می‌گیرد. درحالی‌که نسخه‌های جدید «کالیبره‌نشده» این حسگرها درعوض داده‌های خام حسگر را ارائه می‌دهند و مقادیر سوگیری تخمینی را به‌طور جداگانه ارائه می‌دهند. این حسگرها به شما امکان می‌دهند با بهبود سوگیری تخمینی با داده‌های خارجی، کالیبراسیون سفارشی خودتان را برای داده‌های حسگر ارائه دهید.

    شنونده اعلان

    Android 4.3 کلاس سرویس جدیدی به نام NotificationListenerService اضافه می‌کند که به برنامه شما اجازه می‌دهد اطلاعات مربوط به اعلان‌های جدید را هنگام ارسال توسط سیستم دریافت کند.

    اگر برنامه‌تان درحال‌حاضر از میاناهای برنامه‌سازی کاربردی خدمات دسترس‌پذیری برای دسترسی به اعلان‌های سیستم استفاده می‌کند، باید برنامه‌تان را به‌روز کنید تا به‌جای آن از این میاناهای برنامه‌سازی کاربردی استفاده کند.

    فراهم‌ساز مخاطبین

    پرس‌وجو برای «قابل تماس»

    پرس‌وجوی جدید «ارائه‌دهنده مخاطبین»، Contactables.CONTENT_URI، روشی کارآمد برای دریافت یک Cursor ارائه می‌دهد که حاوی همه نشانی‌های ایمیل و شماره تلفن‌های متعلق به همه مخاطبین منطبق با پرس‌وجوی مشخص‌شده است.

    پرس‌وجو برای دلتاهای مخاطبین

    میاناهای برنامه‌سازی کاربردی جدیدی به «ارائه‌کننده مخاطبین» اضافه شده است که به شما امکان می‌دهد تغییرات اخیر در داده‌های مخاطبین را به‌طور مؤثر جستجو کنید. قبلاً وقتی چیزی در داده‌های مخاطبین تغییر می‌کرد، برنامه شما می‌توانست مطلع شود، اما دقیقاً نمی‌دانستید چه چیزی تغییر کرده است و باید همه مخاطبین را بازیابی می‌کردید و سپس آن‌ها را تکرار می‌کردید تا تغییر را پیدا کنید.

    برای ردیابی تغییرات در درج‌ها و به‌روزرسانی‌ها، اکنون می‌توانید پارامتر CONTACT_LAST_UPDATED_TIMESTAMP را با انتخاب خود اضافه کنید تا فقط مخاطبینی را که از آخرین باری که از ارائه‌دهنده پرس‌وجو کرده‌اید تغییر کرده‌اند، پرس‌وجو کنید.

    برای ردیابی مخاطبین حذف‌شده، جدول جدید ContactsContract.DeletedContacts گزارشی از مخاطبین حذف‌شده ارائه می‌دهد (اما هر مخاطب حذف‌شده برای مدت محدودی در این جدول نگهداری می‌شود). مشابه CONTACT_LAST_UPDATED_TIMESTAMP، می‌توانید از پارامتر انتخاب جدید CONTACT_DELETED_TIMESTAMP استفاده کنید تا ببینید کدام مخاطبین از آخرین باری که از ارائه‌دهنده پرس‌وجو کرده‌اید حذف شده‌اند. این جدول همچنین حاوی ثابت DAYS_KEPT_MILLISECONDS است که تعداد روزهایی (به میلی‌ثانیه) را که گزارش نگهداری می‌شود دربردارد.

    علاوه‌براین، اکنون وقتی کاربر فضای ذخیره‌سازی مخاطبین را ازطریق منو تنظیمات سیستم پاک می‌کند، «ارائه‌دهنده مخاطبین» کنش CONTACTS_DATABASE_CREATED را پخش می‌کند و به‌طور مؤثری پایگاه داده «ارائه‌دهنده مخاطبین» را بازسازی می‌کند. هدف از این کار این است که به برنامه‌ها اطلاع داده شود که باید همه اطلاعات مخاطب را که ذخیره کرده‌اند حذف کنند و آن را با پُرسمان جدیدی بارگیری مجدد کنند.

    برای کد نمونه‌ای که از این میاناهای برنامه‌سازی کاربردی برای بررسی تغییرات مخاطبین استفاده می‌کند، به نمونه ApiDemos موجود در بارگیری نمونه‌های کیت توسعه نرم‌افزار مراجعه کنید.

    بومی‌سازی

    پشتیبانی بهبودیافته برای نوشتار دوجهته

    نسخه‌های قبلی Android از زبان‌ها و چیدمان راست‌به‌چپ (RTL) پشتیبانی می‌کنند، اما گاهی اوقات نوشتار با جهت مختلط را به‌درستی مدیریت نمی‌کنند. بنابراین Android 4.3 میاناهای برنامه‌سازی کاربردی BidiFormatter را اضافه می‌کند که به شما کمک می‌کند نوشتار را با محتوای جهت مخالف به‌درستی قالب‌بندی کنید بدون اینکه هیچ بخشی از آن مخدوش شود.

    برای مثال، وقتی می‌خواهید جمله‌ای با متغیر رشته‌ای ایجاد کنید، مثل «منظورتان 15 Bay Street, Laurel, CA بود؟»، معمولاً منبع رشته بومی‌سازی‌شده و متغیر را به String.format() ارسال می‌کنید:

    کاتلین

    val suggestion = String.format(resources.getString(R.string.did_you_mean), address)

    جاوا

    Resources res = getResources();
    String suggestion = String.format(res.getString(R.string.did_you_mean), address);

    اما اگر زبان عبری باشد، رشته قالب‌بندی‌شده به‌صورت زیر خواهد بود:

    האם התכוונת ל 15 Bay Street, Laurel, CA?

    این اشتباه است چون «۱۵» باید در سمت چپ «Bay Street» باشد. راه حل این است که از BidiFormatter و روش unicodeWrap() آن استفاده کنید. برای مثال، کد بالا به این صورت می‌شود:

    کاتلین

    val bidiFormatter = BidiFormatter.getInstance()
    val suggestion = String.format(
            resources.getString(R.string.did_you_mean),
            bidiFormatter.unicodeWrap(address)
    )

    جاوا

    Resources res = getResources();
    BidiFormatter bidiFormatter = BidiFormatter.getInstance();
    String suggestion = String.format(res.getString(R.string.did_you_mean),
            bidiFormatter.unicodeWrap(address));

    به‌طور پیش‌فرض، unicodeWrap() از اکتشافی تخمین جهت‌داری اول-قوی استفاده می‌کند که اگر اولین سیگنال جهت نوشتار نشان‌دهنده جهت مناسب برای کل محتوا نباشد، ممکن است اشتباه کند. درصورت لزوم، می‌توانید با ارسال یکی از ثابت‌های TextDirectionHeuristic از TextDirectionHeuristics به unicodeWrap()، اکتشافی متفاوتی را مشخص کنید.

    توجه: این میاناهای برنامه‌سازی کاربردی جدید برای نسخه‌های قبلی Android نیز ازطریق کتابخانه پشتیبانی Android با کلاس BidiFormatter و میاناهای برنامه‌سازی کاربردی مرتبط دردسترس است.

    خدمات دسترس‌پذیری

    مدیریت رویدادهای کلیدی

    اکنون AccessibilityService می‌تواند برای رویدادهای ورودی کلید با روش فراخوانی onKeyEvent()، فراخوانی دریافت کند. این به سرویس دسترس‌پذیری شما اجازه می‌دهد ورودی دستگاه‌های ورودی کلیدمحور مانند صفحه‌کلید را مدیریت کند و آن رویدادها را به کنش‌های ویژه‌ای ترجمه کند که قبلاً ممکن بود فقط با ورودی لمسی یا پد جهت‌نمای دستگاه امکان‌پذیر باشد.

    انتخاب نوشتار و کپی/جای‌گذاری

    AccessibilityNodeInfo اکنون میاناهای برنامه‌سازی کاربردی‌ای ارائه می‌دهد که به AccessibilityService اجازه می‌دهد نوشتار را در گره انتخاب، برش، کپی، و جای‌گذاری کند.

    برای مشخص کردن انتخاب نوشتار برای برش یا کپی، سرویس دسترس‌پذیری شما می‌تواند از کنش جدید ACTION_SET_SELECTION استفاده کند و موقعیت شروع و پایان انتخاب را با ACTION_ARGUMENT_SELECTION_START_INT و ACTION_ARGUMENT_SELECTION_END_INT منتقل کند. یا می‌توانید با دستکاری موقعیت مکان‌نما بااستفاده از کنش موجود، ACTION_NEXT_AT_MOVEMENT_GRANULARITY (قبلاً فقط برای جابه‌جا کردن موقعیت مکان‌نما بود)، و افزودن آرگومان ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN، نوشتار را انتخاب کنید.

    سپس می‌توانید با ACTION_CUT، ACTION_COPY ببرید یا کپی کنید، سپس بعداً با ACTION_PASTE جای‌گذاری کنید.

    توجه: این میاناهای برنامه‌سازی کاربردی جدید برای نسخه‌های قبلی Android نیز ازطریق کتابخانه پشتیبانی Android، با کلاس AccessibilityNodeInfoCompat، دردسترس است.

    اعلام ویژگی‌های دسترس‌پذیری

    از Android 4.3 به بعد، سرویس دسترس‌پذیری باید قابلیت‌های دسترس‌پذیری را در فایل فراداده خود اعلام کند تا بتواند از ویژگی‌های دسترس‌پذیری خاصی استفاده کند. اگر این قابلیت در فایل فراداده درخواست نشده باشد، این ویژگی بدون عملیات خواهد بود. برای اعلام قابلیت‌های دسترس‌پذیری سرویس خود، باید از ویژگی‌های XML استفاده کنید که با ثابت‌های مختلف «قابلیت» در کلاس AccessibilityServiceInfo مطابقت دارند.

    برای مثال، اگر سرویسی قابلیت flagRequestFilterKeyEvents را درخواست نکند، رویدادهای کلیدی را دریافت نخواهد کرد.

    آزمایش و اشکال‌زدایی

    آزمایش خودکارسازی‌شده میانای کاربر

    کلاس جدید UiAutomation میاناهای برنامه‌سازی کاربردی‌ای ارائه می‌دهد که به شما امکان می‌دهد کنش‌های کاربر را برای خودکارسازی آزمایش شبیه‌سازی کنید. بااستفاده از میاناهای برنامه‌سازی کاربردی AccessibilityService پلاتفرم، میاناهای برنامه‌سازی کاربردی UiAutomation به شما امکان می‌دهند محتوای صفحه را بازرسی کنید و رویدادهای لمسی و صفحه‌کلید دلخواه را تزریق کنید.

    برای دریافت نمونه‌ای از UiAutomation، با Instrumentation.getUiAutomation() تماس بگیرید. برای اینکه این کار انجام شود، باید گزینه -w را با فرمان instrument هنگام اجرای InstrumentationTestCase از adb shell ارائه دهید.

    با نمونه UiAutomation، می‌توانید رویدادهای دلخواه را برای آزمایش کردن برنامه‌تان اجرا کنید. برای این کار، executeAndWaitForEvent() را فراخوانی کنید، Runnable را برای اجرا به آن ارسال کنید، دوره مهلت زمانی برای عملیات را مشخص کنید، و میانای UiAutomation.AccessibilityEventFilter را پیاده‌سازی کنید. در پیاده‌سازی UiAutomation.AccessibilityEventFilter است که تماسی دریافت می‌کنید که به شما امکان می‌دهد رویدادهای موردعلاقه‌تان را فیلتر کنید و موفقیت یا شکست یک چارچوب تست خاص را تعیین کنید.

    برای مشاهده همه رویدادها درطول آزمایش، پیاده‌سازی UiAutomation.OnAccessibilityEventListener را ایجاد کنید و آن را به setOnAccessibilityEventListener() منتقل کنید. سپس میانای شنونده شما هربار که رویدادی رخ می‌دهد، تماسی با onAccessibilityEvent() دریافت می‌کند و شیء AccessibilityEvent را که رویداد را توصیف می‌کند دریافت می‌کند.

    انواع مختلفی از عملیات دیگر وجود دارد که UiAutomation APIها در سطح بسیار پایینی ارائه می‌دهند تا توسعه ابزارهای آزمایش واسط کاربر مانند uiautomator را تشویق کنند. برای مثال، UiAutomation می‌تواند کارهای زیر را نیز انجام دهد:

    • تزریق رویدادهای ورودی
    • تغییر جهت صفحه‌نمایش
    • گرفتن عکس صفحه‌نمایش

    و مهم‌تر از همه برای ابزارهای آزمایش واسط کاربر، میاناهای برنامه‌سازی کاربردی UiAutomation برخلاف میاناهای برنامه‌سازی کاربردی در Instrumentation، در مرزهای برنامه کار می‌کنند.

    رویدادهای Systrace برای برنامه‌ها

    Android 4.3 کلاس Trace را با دو روش ثابت beginSection() و endSection() اضافه می‌کند، که به شما امکان می‌دهد بلوک‌های کد را برای گنجاندن در گزارش systrace تعریف کنید. با ایجاد بخش‌هایی از کد قابل‌ردیابی در برنامه‌تان، گزارش‌های systrace تجزیه‌وتحلیل بسیار دقیق‌تری از محل وقوع کندی در برنامه‌تان به شما ارائه می‌دهند.

    برای کسب اطلاعات درباره استفاده از ابزار Systrace، مقاله تجزیه‌وتحلیل نمایش و عملکرد با Systrace را بخوانید.

    امنیت

    فروشگاه کلید Android برای کلیدهای خصوصی برنامه

    Android اکنون یک «ارائه‌دهنده امنیتی Java» سفارشی در تسهیلات KeyStore ارائه می‌دهد که «فروشگاه کلید Android» نام دارد و به شما امکان می‌دهد کلیدهای خصوصی‌ای را تولید و ذخیره کنید که فقط توسط برنامه شما دیده و استفاده می‌شوند. برای بار کردن «فروشگاه کلید Android»، "AndroidKeyStore" را به KeyStore.getInstance() ارسال کنید.

    برای مدیریت اطلاعات کاربری خصوصی برنامه‌تان در Android Key Store، کلید جدیدی با KeyPairGenerator با KeyPairGeneratorSpec تولید کنید. ابتدا با فراخوانی getInstance()، نمونه‌ای از KeyPairGenerator را دریافت کنید. سپس initialize() را فراخوانی کنید و نمونه‌ای از KeyPairGeneratorSpec را به آن ارسال کنید که می‌توانید بااستفاده از KeyPairGeneratorSpec.Builder آن را دریافت کنید. درنهایت، با تماس با generateKeyPair()، KeyPair خود را دریافت کنید.

    بخش ذخیره اعتبارنامه‌های سخت‌افزاری

    Android اکنون از فضای ذخیره‌سازی با پشتیبانی سخت‌افزاری برای اطلاعات اعتباری KeyChain شما نیز پشتیبانی می‌کند و با غیرقابل‌استخراج کردن کلیدها، امنیت بیشتری را فراهم می‌کند. یعنی وقتی کلیدها در محل ذخیره کلید با پشتوانه سخت‌افزاری (Secure Element،‏ TPM، یا TrustZone) قرار می‌گیرند، می‌توان از آن‌ها برای عملیات رمزنگاری استفاده کرد اما نمی‌توان محتوای کلید خصوصی را صادر کرد. حتی هسته سیستم‌عامل نمی‌تواند به این مواد کلید دسترسی پیدا کند. اگرچه همه دستگاه‌های مجهز به Android از ذخیره‌سازی در سخت‌افزار پشتیبانی نمی‌کنند، می‌توانید با فراخوانی KeyChain.IsBoundKeyAlgorithm() در زمان اجرا بررسی کنید که آیا فضای ذخیره‌سازی با پشتیبانی سخت‌افزاری دردسترس است یا نه.

    اظهارنامه‌های مانیفست

    ویژگی‌های الزامی قابل‌اعلام

    اکنون مقادیر زیر در عنصر <uses-feature> پشتیبانی می‌شود تا بتوانید مطمئن شوید برنامه‌تان فقط در دستگاه‌هایی نصب می‌شود که ویژگی‌های موردنیاز برنامه‌تان را ارائه می‌دهند.

    FEATURE_APP_WIDGETS
    اعلام می‌کند که برنامه شما ابزاره برنامه ارائه می‌دهد و باید فقط در دستگاه‌هایی نصب شود که دارای «صفحه اصلی» یا مکان مشابهی باشند که کاربران بتوانند ابزاره‌های برنامه را در آن جاسازی کنند. مثال:
    <uses-feature android:name="android.software.app_widgets" android:required="true" />
    FEATURE_HOME_SCREEN
    اعلام می‌کند که برنامه شما به‌عنوان جایگزین «صفحه اصلی» عمل می‌کند و باید فقط در دستگاه‌هایی نصب شود که از برنامه‌های «صفحه اصلی» شخص ثالث پشتیبانی می‌کنند. مثال:
    <uses-feature android:name="android.software.home_screen" android:required="true" />
    FEATURE_INPUT_METHODS
    اعلام می‌کند که برنامه شما روش ورودی سفارشی (صفحه‌کلید ساخته‌شده با InputMethodService) ارائه می‌دهد و باید فقط در دستگاه‌هایی نصب شود که از روش‌های ورودی طرف سوم پشتیبانی می‌کنند. مثال:
    <uses-feature android:name="android.software.input_methods" android:required="true" />
    FEATURE_BLUETOOTH_LE
    اعلام می‌کند که برنامه شما از میاناهای برنامه‌سازی کاربردی «بلوتوث کم‌مصرف» استفاده می‌کند و باید فقط در دستگاه‌هایی نصب شود که می‌توانند ازطریق «بلوتوث کم‌مصرف» با دستگاه‌های دیگر ارتباط برقرار کنند. مثال:
    <uses-feature android:name="android.software.bluetooth_le" android:required="true" />

    اجازه‌های کاربر

    اکنون مقادیر زیر در <uses-permission> پشتیبانی می‌شود تا اجازه‌هایی را که برنامه‌تان برای دسترسی به برخی‌از میاناهای برنامه‌سازی کاربردی نیاز دارد اعلام کنید.

    BIND_NOTIFICATION_LISTENER_SERVICE
    برای استفاده از میاناهای برنامه‌سازی کاربردی NotificationListenerService جدید لازم است.
    SEND_RESPOND_VIA_MESSAGE
    برای دریافت هدف ACTION_RESPOND_VIA_MESSAGE الزامی است.

    برای مشاهده جزئیات همه تغییرات میانای برنامه‌سازی کاربردی در Android 4.3، گزارش تفاوت‌های میانای برنامه‌سازی کاربردی را ببینید.