این صفحه نحوه پیاده سازی AppCard را شرح می دهد.
مرحله 1: تمام واردات را اضافه کنید
برای افزودن واردات:
static_libs: [ … "car-app-card", ],
مرحله 2: SimpleAppCardContentProvider را به مانیفست خود اضافه کنید
حتماً نام بسته خود را جایگزین
android:authorities
(به صورت پررنگ) کنید.<!-- App Card Content Provider that is required to communicate relevant App Cards with the system android.car.permission.BIND_APP_CARD_PROVIDER is an essential permission that will only allow the system to communicate with the AppCardContentProvider The content provider must also be exported and enabled --> <provider android:name=".SimpleAppCardContentProvider" android:authorities="com.example.appcard.sample" android:permission="@string/host_permission" android:exported="true" android:enabled="true"> <intent-filter> <!-- This intent filter will allow the system to find and connect with the application's AppCardContentProvider --> <action android:name="com.android.car.appcard.APP_CARD_PROVIDER" /> </intent-filter> </provider>
مرحله 3: SimpleAppCardContentProvider را به مانیفست اضافه کنید
برای افزودن
SimpleAppCardContentProvider
به مانیفست:class SimpleAppCardContentProvider : AppCardContentProvider() { /** Must return same authority as defined in manifest */ override val authority: String = AUTHORITY /** Setup [AppCardContentProvider] and its constituents */ override fun onCreate(): Boolean { return super.onCreate() } /** Setup an [AppCard] that is being requested */ override fun onAppCardAdded(id: String, ctx: AppCardContext): AppCard { return when (id) { APPCARD_ID -> //TODO: create app card else -> throw IllegalStateException("Unidentified app card ID: $id") } } /** List of supported [AppCard] IDs */ override val appCardIds: List<String> = listOf(APPCARD_ID).toMutableList() /** Clean up when an [AppCard] is removed */ override fun onAppCardRemoved(id: String) { when (id) { APPCARD_ID -> //TODO: create app card } } /** Handle an [AppCardContext] change for a particular [AppCard] ID */ override fun onAppCardContextChanged( id: String, appCardContext: AppCardContext ) { when (id) { APPCARD_ID -> //TODO: update AppCardContext } } companion object { private const val AUTHORITY = "com.example.appcard.sample" private const val APPCARD_ID = "sampleAppCard" } }
مرحله 4: یک AppCard ایجاد کنید
برای ایجاد یک AppCard:
override fun onAppCardAdded(id: String, ctx: AppCardContext): AppCard { return when (id) { APPCARD_ID -> createAppCard(ctx) else -> throw IllegalStateException("Unidentified app card ID: $id") } } private fun createAppCard(appCardContext: AppCardContext): ImageAppCard { return ImageAppCard.newBuilder(APPCARD_ID) .setPrimaryText("Hello") .setSecondaryText("World") .setHeader( Header.newBuilder("header") .setTitle("Code Lab") .build() ) .addButton( Button.newBuilder( "button", Button.ButtonType.PRIMARY, object : OnClickListener { override fun onClick() { //no-op } } ) .setText("Click me!") .build() ) .build() }
به عنوان مثال:
شکل 1. یک AppCard ایجاد کنید.
مرحله 5: کلیک کننده دکمه را فعال کنید
برای فعال کردن کلیکگر:
private var clickCounter = 0
private fun createAppCard(appCardContext: AppCardContext): ImageAppCard {
...
.addButton(
Button.newBuilder(
"button",
Button.ButtonType.PRIMARY,
object : OnClickListener {
override fun onClick() {
clickCounter++
sendAppCardUpdate(createAppCard(appCardContext))
}
}
)
.setText(
if (clickCounter == 0) "Click me!" else "Clicked: $clickCounter"
)
.build()
)
...
}
override fun onAppCardRemoved(id: String) {
when (id) {
APPCARD_ID -> clickCounter = 0
}
}
به عنوان مثال:
شکل 2. کلیک کننده دکمه را فعال کنید.
مرحله 6: تصویر هدر را به روز کنید
برای به روز رسانی تصویر در هدر:
private fun createAppCard(appCardContext: AppCardContext): ImageAppCard { val headerImageSize = appCardContext.imageAppCardContext.getMaxImageSize(Header::class.java) val logo = resToBitmap( android.R.drawable.ic_menu_compass, headerImageSize.width, headerImageSize.height ) ... .setHeader( Header.newBuilder("header") .setTitle("Code Lab") .setImage( Image.newBuilder("image") .setContentScale(Image.ContentScale.FILL_BOUNDS) .setColorFilter(Image.ColorFilter.TINT) .setImageData(logo) .build() ) .build() ) ... } private fun resToBitmap(res: Int, width: Int, height: Int): Bitmap { val drawable = context?.getDrawable(res) return drawableToBitmap(drawable!!, width, height) } private fun drawableToBitmap(d: Drawable, width: Int, height: Int): Bitmap { val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) val canvas = Canvas(bitmap) val left = 0 val top = 0 d.setBounds(left, top, canvas.width, canvas.height) d.draw(canvas) return bitmap } ``` For example:  **Figure 3.** Change the name to the header.
این فرآیند را تکرار کنید تا یک تصویر به هر مؤلفه ای که از آن پشتیبانی می کند اضافه کنید.
مرحله 7: تعاملات بیشتری اضافه کنید
برای ایجاد یک نوار پیشرفت با کنترل ها:
private var progressOn = false private var progressTimer: Timer? = null private var progressCounter = 0 override fun onAppCardRemoved(id: String) { when (id) { APPCARD_ID -> { clickCounter = 0 progressCounter = 0 progressTimer?.cancel() } } } private fun createAppCard(appCardContext: AppCardContext): ImageAppCard { val buttonImageSize = appCardContext.imageAppCardContext.getMaxImageSize(Button::class.java) val progressPlayPauseImage = resToBitmap( if (progressOn) { android.R.drawable.ic_media_pause } else { android.R.drawable.ic_media_play }, buttonImageSize.width, buttonImageSize.height ) ... .setProgressBar( createProgressBar() ) .addButton( Button.newBuilder( "progressButton", Button.ButtonType.NO_BACKGROUND, object : OnClickListener { override fun onClick() { progressOn = !progressOn if (progressOn) { progressTimer = Timer() progressTimer?.scheduleAtFixedRate(object : TimerTask() { override fun run() { progressCounter++ if (progressCounter > 60) progressCounter = 0 sendAppCardComponentUpdate(APPCARD_ID, createProgressBar()) } }, SECONDS_TO_MS, SECONDS_TO_MS) } else { progressTimer?.cancel() progressTimer = null } sendAppCardUpdate(createAppCard(appCardContext)) } } ) .setImage( Image.newBuilder("buttonImage") .setContentScale(Image.ContentScale.FILL_BOUNDS) .setColorFilter(Image.ColorFilter.TINT) .setImageData(progressPlayPauseImage) .build() ) .build() ) ... } private fun createProgressBar(): ProgressBar { return ProgressBar.newBuilder(PROGRESS_BAR_ID, 0, 60) .setProgress(progressCounter) .build() } companion object { ... private const val PROGRESS_BAR_ID = "progress" private const val SECONDS_TO_MS = 1000L }
ما یک دکمه Play یا Pause را به نوار پیشرفت اضافه کردیم که می تواند هر ثانیه به روز شود. با توجه به محدودیتهای اندازه، به setText
روی دکمه کلیکی که برای منعکس کردن تعداد کلیکها اضافه شده است، .setText("$clickCounter")
مراجعه کنید.
![]() شکل 4. یک دکمه اضافه کنید. | ![]() شکل 5. دکمه رندر شده. |
مرحله 8: فعالیت را راه اندازی کنید
به شرطی که برنامه شما با
background-starts#exceptions
مطابقت داشته باشد، میتوانید یک فعالیت را از دکمهonClickListener
اجرا کنید.class SampleRoutingActivity : AppCompatActivity() { override fun onStart() { super.onStart() val intent = Intent(ACTION_LOCATION_SOURCE_SETTINGS).apply { setFlags(FLAG_ACTIVITY_CLEAR_TOP) } startActivity(intent) finish() } }
برای شروع فعالیت، یک دکمه در AppCard اضافه کنید. اگر هیچ کدام وجود ندارد، یک فعالیت مسیریابی به برنامه خود اضافه کنید:
override fun onStart() { super.onStart() val intent = Intent(ACTION_LOCATION_SOURCE_SETTINGS).apply { setFlags(FLAG_ACTIVITY_CLEAR_TOP) } startActivity(intent) finish() } }
هنگامی که کلاس فراخوانی می شود، کاربر به تنظیمات مکان هدایت می شود.
setFlags(FLAG_ACTIVITY_CLEAR_TOP)
برای اطمینان از اینکه کاربر نمی تواند به فعالیت اصلی بازگردد اعمال می شود.برای شروع فعالیت، یک دکمه در AppCard اضافه کنید:
private fun createAppCard(appCardContext: AppCardContext): ImageAppCard { val locationImage = resToBitmap( android.R.drawable.ic_menu_call, buttonImageSize.width, buttonImageSize.height ) ... .addButton( Button.newBuilder( "activityButton", Button.ButtonType.SECONDARY, object : OnClickListener { override fun onClick() { // no-op } } ) .setImage( Image.newBuilder("locationButtonImage") .setContentScale(Image.ContentScale.FILL_BOUNDS) .setColorFilter(Image.ColorFilter.TINT) .setImageData(locationImage) .build() ) .setIntent( RoutingActivityIntent .newBuilder("com.example.appcard.sample.SampleRoutingActivity") .build() ) .build() ) ... }
به دلیل محدودیت فضا، دکمه کلیک در میزبان AppCard حذف شد. AppCard به صورت زیر ظاهر می شود:
شکل 6. AppCard بدون دکمه کلیک.