如何使用Data Layer实现安卓手机向Wear OS手表传输图片,代码分Phone.kt、Watch.kt两个文件
安卓手机向Wear OS手表传输图片实现方案(Data Layer通信)
前置要求:手机端与手表端应用需保持相同applicationId、相同签名,两端均需添加Wearable Data Layer依赖
// 两端build.gradle都需添加该依赖 dependencies { implementation "com.google.android.gms:play-services-wearable:18.1.0" } // 手机端AndroidManifest需添加权限 <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> // 手表端如需存储到公共目录需额外加存储权限,用内部存储可省略 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
1. 手机端代码(Phone.kt)
完整覆盖「选中要传输的照片」+「发送照片到绑定手表」两个实现步骤:
import android.app.Activity import android.content.Intent import android.net.Uri import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import com.google.android.gms.wearable.PutDataMapRequest import com.google.android.gms.wearable.Wearable import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.tasks.await import java.io.ByteArrayOutputStream import java.io.InputStream class PhoneActivity : AppCompatActivity() { private val IMAGE_PATH = "/image_transfer" private val IMAGE_KEY = "image_data" // 选图回调:实现步骤1 选中要传输的照片 private val pickImageLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == Activity.RESULT_OK) { result.data?.data?.let { imageUri -> val imageBytes = uriToByteArray(imageUri) imageBytes?.let { sendImageToWear(it) } } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 触发系统相册选图 val pickIntent = Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI) pickImageLauncher.launch(pickIntent) } private fun uriToByteArray(uri: Uri): ByteArray? { return try { val inputStream: InputStream? = contentResolver.openInputStream(uri) val byteBuffer = ByteArrayOutputStream() inputStream?.use { input -> val buffer = ByteArray(1024) var len: Int while (input.read(buffer).also { len = it } != -1) { byteBuffer.write(buffer, 0, len) } } byteBuffer.toByteArray() } catch (e: Exception) { e.printStackTrace() null } } // 实现步骤2 发送选中的照片到绑定的Wear OS手表 private fun sendImageToWear(imageBytes: ByteArray) { CoroutineScope(Dispatchers.IO).launch { try { // 查询已绑定的手表节点 val nodes = Wearable.getNodeClient(this@PhoneActivity).connectedNodes.await() if (nodes.isEmpty()) return@launch // 构造DataItem,加入时间戳确保每次传输都会触发同步 val putDataMapRequest = PutDataMapRequest.create(IMAGE_PATH).apply { dataMap.putByteArray(IMAGE_KEY, imageBytes) dataMap.putLong("timestamp", System.currentTimeMillis()) } val request = putDataMapRequest.asPutDataRequest() Wearable.getDataClient(this@PhoneActivity).putDataItem(request).await() } catch (e: Exception) { e.printStackTrace() } } } }
2. 手表端代码(Watch.kt)
完整覆盖「接收传输的图片」+「图片本地存储」两个实现步骤:
import android.graphics.Bitmap import android.graphics.BitmapFactory import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import com.google.android.gms.wearable.DataClient import com.google.android.gms.wearable.DataEvent import com.google.android.gms.wearable.DataEventBuffer import com.google.android.gms.wearable.Wearable import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch class WatchActivity : AppCompatActivity(), DataClient.OnDataChangedListener { private val IMAGE_PATH = "/image_transfer" private val IMAGE_KEY = "image_data" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } override fun onResume() { super.onResume() // 注册DataLayer数据变化监听 Wearable.getDataClient(this).addListener(this) } override fun onPause() { super.onPause() Wearable.getDataClient(this).removeListener(this) } // 实现步骤3 接收手机端传输的图片 override fun onDataChanged(dataEvents: DataEventBuffer) { dataEvents.forEach { event -> if (event.type == DataEvent.TYPE_CHANGED) { event.dataItem.takeIf { it.uri.path == IMAGE_PATH }?.let { dataItem -> val dataMap = com.google.android.gms.wearable.DataMapItem.fromDataItem(dataItem).dataMap dataMap.getByteArray(IMAGE_KEY)?.let { imageBytes -> val bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size) saveImageToLocal(bitmap) } } } } } // 实现步骤4 将接收到的图片存储到手表本地 private fun saveImageToLocal(bitmap: Bitmap) { CoroutineScope(Dispatchers.IO).launch { try { val fileName = "received_${System.currentTimeMillis()}.png" // 存储到应用内部存储,无需申请额外权限 openFileOutput(fileName, MODE_PRIVATE).use { fos -> bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos) fos.flush() } } catch (e: Exception) { e.printStackTrace() } } } }
- 补充使用说明:
- 传输前建议对图片做压缩处理,避免超过Data Layer单条100KB的大小限制
- 若需要传输大体积图片,可拆分多块分别传输,接收端再拼接还原
- 传输时需确保手机与手表保持正常绑定连接,两端应用都处于已安装状态
内容的提问来源于stack exchange,提问作者Oein0219
相关产品推荐
相关产品推荐

