อุปกรณ์ที่ใช้ Android 7.0 (API ระดับ 24) ขึ้นไปรองรับ multi-window ซึ่งช่วยให้ผู้ใช้ ย้ายข้อมูลจากแอปหนึ่งไปยังอีกแอปหนึ่งโดยการลากและวาง
แอปต้นทางที่การดำเนินการเริ่มขึ้นจะให้ข้อมูล แอปเป้าหมายที่การดำเนินการสิ้นสุดลงจะได้รับข้อมูล
เมื่อผู้ใช้เริ่มลากเนื้อหา แอปแหล่งที่มาควรตั้งค่า
DRAG_FLAG_GLOBAL
แจ้งว่าเป็น
ระบุว่าผู้ใช้สามารถลากข้อมูลไปยังแอปอื่นได้
เนื่องจากข้อมูลจะข้ามขอบเขตของแอป แอปจึงแชร์การเข้าถึงข้อมูล โดยใช้ URI เนื้อหา ต้องดำเนินการต่อไปนี้
- แอปแหล่งที่มาต้องตั้งค่า
DRAG_FLAG_GLOBAL_URI_READ
และDRAG_FLAG_GLOBAL_URI_WRITE
แฟล็ก ขึ้นอยู่กับสิทธิ์การอ่านหรือการเขียนข้อมูลที่แอปต้นทาง ต้องการมอบให้กับแอปเป้าหมาย - แอปเป้าหมายต้องเรียกใช้
requestDragAndDropPermissions()
ทันทีก่อนที่จะจัดการข้อมูลที่ผู้ใช้ลากเข้าสู่แอป ถ้า แอปเป้าหมายไม่ต้องการสิทธิ์เข้าถึงข้อมูลที่ลากมาอีกต่อไป แต่แอปสามารถ แล้วโทร เปิดrelease()
ออบเจ็กต์ที่ส่งคืนจากrequestDragAndDropPermissions()
มิฉะนั้น ระบบจะถอนสิทธิ์เมื่อกิจกรรมที่มี ถูกทำลายแล้ว หากการติดตั้งใช้งานของคุณเกี่ยวข้องกับการเริ่มกิจกรรมใหม่เพื่อประมวลผล URI ที่ลดลง คุณจะต้องให้สิทธิ์เดิมแก่กิจกรรมใหม่ คุณต้องตั้งค่าข้อมูลคลิปและธง ดังนี้Kotlin
intent.setClipData(clipData) intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
Java
intent.setClipData(clipData); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
ข้อมูลโค้ดต่อไปนี้แสดงวิธีเผยแพร่สิทธิ์การเข้าถึงระดับอ่านอย่างเดียว ที่ลากข้อมูลทันทีหลังจากที่มีการดำเนินการวางผู้ใช้ โปรดดู การสาธิตการลากและวาง ใน GitHub เพื่อให้ตัวอย่างที่สมบูรณ์มากขึ้น
กิจกรรมต้นทาง
Kotlin
// Drag a file stored in an images/ directory in internal storage. val internalImagesDir = File(context.filesDir, "images") val imageFile = File(internalImagesDir, imageFilename) val uri = FileProvider.getUriForFile(context, contentAuthority, imageFile) val listener = OnDragStartListener@{ view: View, _: DragStartHelper -> val clipData = ClipData(ClipDescription("Image Description", arrayOf("image/*")), ClipData.Item(uri)) // Must include DRAG_FLAG_GLOBAL to permit dragging data between apps. // This example provides read-only access to the data. val flags = View.DRAG_FLAG_GLOBAL or View.DRAG_FLAG_GLOBAL_URI_READ return@OnDragStartListener view.startDragAndDrop(clipData, View.DragShadowBuilder(view), null, flags) } // Container where the image originally appears in the source app. val srcImageView = findViewById<ImageView>(R.id.imageView) // Detect and start the drag event. DragStartHelper(srcImageView, listener).apply { attach() }
Java
// Drag a file stored in an images/ directory in internal storage. File internalImagesDir = new File(context.getFilesDir(), "images"); File imageFile = new File(internalImagesDir, imageFilename); final Uri uri = FileProvider.getUriForFile(context, contentAuthority, imageFile); // Container where the image originally appears in the source app. ImageView srcImageView = findViewById(R.id.imageView); // Enable the view to detect and start the drag event. new DragStartHelper(srcImageView, (view, helper) -> { ClipData clipData = new ClipData(new ClipDescription("Image Description", new String[] {"image/*"}), new ClipData.Item(uri)); // Must include DRAG_FLAG_GLOBAL to permit dragging data between apps. // This example provides read-only access to the data. int flags = View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ; return view.startDragAndDrop(clipData, new View.DragShadowBuilder(view), null, flags); }).attach();
กิจกรรมเป้าหมาย
Kotlin
// Container where the image is to be dropped in the target app. val targetImageView = findViewById<ImageView>(R.id.imageView) targetImageView.setOnDragListener { view, event -> when (event.action) { ACTION_DROP -> { val imageItem: ClipData.Item = event.clipData.getItemAt(0) val uri = imageItem.uri // Request permission to access the image data being dragged into // the target activity's ImageView element. val dropPermissions = requestDragAndDropPermissions(event) (view as ImageView).setImageURI(uri) // Release the permission immediately afterward because it's no // longer needed. dropPermissions.release() return@setOnDragListener true } // Implement logic for other DragEvent cases here. // An unknown action type is received. else -> { Log.e("DragDrop Example", "Unknown action type received by View.OnDragListener.") return@setOnDragListener false } } }
Java
// Container where the image is to be dropped in the target app. ImageView targetImageView = findViewById(R.id.imageView); targetImageView.setOnDragListener( (view, event) -> { switch (event.getAction()) { case ACTION_DROP: ClipData.Item imageItem = event.getClipData().getItemAt(0); Uri uri = imageItem.getUri(); // Request permission to access the image data being dragged into // the target activity's ImageView element. DragAndDropPermissions dropPermissions = requestDragAndDropPermissions(event); ((ImageView)view).setImageURI(uri); // Release the permission immediately afterward because it's no // longer needed. dropPermissions.release(); return true; // Implement logic for other DragEvent cases here. // An unknown action type was received. default: Log.e("DragDrop Example","Unknown action type received by View.OnDragListener."); break; } return false; });