Skip to content

zzhqk/OpenWear

 
 

Repository files navigation

##主要功能介绍##

1、精简的库大小

2、方便简洁、易拓展、定制性强的API - 更快速开发

3、支持兼容多个手表系统 - android wear谷歌版和中国版、ticwear、duwear

4、连接及通信自适应适配 - 无需关心手表系统 只需关心业务逻辑

5、生命周期内部管理 - 无需关心生命周期 只需关心业务逻辑

6、声明一个监听服务即可兼容多个手表系统

7、丰富的工具类 - 更快速开发

8、手表无需联网 也可在手表端直接发起网络

9、可以以布局文件的形式 构建自定义表盘

10、支持多种数据形式的通信 - 字节流、字符串、图片、文件、键值对

11、支持全双工双向通信

设备通信初始化

涉及设备通信相关包含数据发送、数据监听、统计分析、自定义事件、错误日志、独立网络请求、云更新。

Mobile端uses-sdk配置

<uses-sdk
    android:minSdkVersion="9"
    android:targetSdkVersion="22" />

Wearable端uses-sdk配置

<uses-sdk
    android:minSdkVersion="18"
    android:targetSdkVersion="22" />

Mobile端及Wearable端的平台兼容性配置 创建res/values/wearable_service_version.xml文件

<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- google play service版本号-->
<integer name="google_play_services_version">6587000</integer>
<!-- duwear连接服务版本号-->
<integer name="open_wearable_service_version">1000000</integer>
<!-- android wear中国版连接服务版本号-->
<integer name="android_wear_china_services_version">7887000</integer>
</resources>

Mobile端及Wearable端初始化代码

OpenWatchCommunication.init(context);

声明所需要兼容的Android Wear谷歌版、Android Wear中国版、DuWear连接服务的版本号(TicWear不需要)

兼容Android Wear谷歌版

    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />

兼容Android Wear中国版

	<meta-data
        android:name="com.google.android.wearable.version"
        android:value="@integer/android_wear_china_services_version" />

兼容Duwear

    <meta-data
        android:name="org.owa.wear.ows.sdk.version"
        android:value="@integer/open_wearable_service_version" />

可以自定义内部线程池

例如

OpenWatchCommunication.setTheadPool(Executors.newCachedThreadPool());

若不设置,则内部默认使用newCachedThreadPool创建的线程池,线程优先级为Process.THREAD_PRIORITY_BACKGROUND的非守护线程。

数据发送

需要初始化设备通信相关,详见设备通信相关初始化一节。

提供多种手机与手表间的数据发送方式,不用手动管理连接,内部会在必要时自动断开或打开连接,不需要再关心设备连接、通信、数据层,且所发送的数据均没有大小限制,无论是手机端还是在手表端,代码写法及逻辑相同。

无需再导入其他第三方系统平台的开发jar包。

每种数据发送行为都由path和data组成:

  • path:自定义的任意字符串,用于标识该数据发送行为的唯一性。
  • data:所发送的任意类型数据,可以是基本数据类型、字节流、图片或者map类型,详见Demo。

1、数据存储和手机与手表间的自动同步,当配对设备未连接,数据并不会被丢失,会在下次连接上配对设备时接收到数据:

OpenWatchSender.sendData(context, "/send_data", "hello openwatch", new SendListener() {
				
				@Override
				public void onSuccess() {
					// TODO Auto-generated method stub
					//发送成功
				}
				
				@Override
				public void onError(ErrorStatus error) {
					// TODO Auto-generated method stub
					//发送失败及失败原因
				}
			});

2、数据以消息的形式发送,当配对设备未连接,数据会被丢失,用于发送临时性或时效性数据:

OpenWatchSender.sendMsg(this, "/send_msg", "hello openwatch", new SendListener() {
				
				@Override
				public void onSuccess() {
					// TODO Auto-generated method stub
					//发送成功
				}
				
				@Override
				public void onError(ErrorStatus error) {
					// TODO Auto-generated method stub
					//发送失败及失败原因
				}
			});

3、有时你的需求场景会需要类似网络请求,数据发送为请求/响应交流模型,可以等待配对设备的响应直到超时。当配对设备未连接,数据会被丢失:

OpenWatchBothWay.request(this, "/send_bothway", "hello openwatch", new BothWayCallback() {

				@Override
				public void onResponsed(byte[] rawData) {
					// TODO Auto-generated method stub
					//配对设备响应回来的数据
				}

				@Override
				public void onError(ErrorStatus error) {
					// TODO Auto-generated method stub
					//数据请求错误及原因
				}
			});

配对设备接收到对应的请求并响应,同时传入接收到的path

if (path.equals("/send_bothway")) {
	OpenWatchBothWay.response(this, path, "response bothway");
}

可设置数据发送的超时时间(默认10秒):

OpenWatchSender.setTimeOutMills(15000);

可设置请求响应的超时时间(默认10秒):

OpenWatchBothWay.setTimeOutMills(15000);

数据接收与监听

需要初始化设备通信相关,详见设备通信相关初始化一节。

数据接收与监听有两种方式,可任选其一或者两者结合使用,无论是手机端还是在手表端,代码写法及逻辑相同(详见Demo):

1、设置Listener,一般用于activity中,可根据应用具体业务和功能需求,添加不同层面的监听,并在监听的回调函数中接收到配对设备发送的数据:

	// 添加设备连接的监听
	OpenWatchRegister.addConnectListener(this);
	// 添加接收数据的监听
	OpenWatchRegister.addDataListener(this);
	OpenWatchRegister.addMessageListener(this);
	// 添加接收图片、map等特殊类型数据的监听
	OpenWatchRegister.addSpecialTypeListener(this);

取消监听

	OpenWatchRegister.removeDataListener(this);
	OpenWatchRegister.removeConnectListener(this);
	OpenWatchRegister.removeMessageListener(this);
	OpenWatchRegister.removeSpecialTypeListener(this);

2、设置监听服务:

在配置文件注册监听服务 根据应用想要兼容的智能手表系统,可选择性配置不同的action,action name不可修改

<!-- 继承自OpenWatchListenerService的子类service 下面service name需要修改成自己的类名 -->
    <!-- 根据自身业务需求和兼容性需求 可选择性添加不同的intent-filter 其中action name不可修改-->

    <service android:name="cn.openwatch.mobile.demo.ListenerService" >
        <intent-filter>

            <!-- 兼容android wear谷歌版和中国版 -->
            <action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
            <!-- 兼容duwear-->
            <action android:name="org.owa.wear.ows.BIND_LISTENER" />
            <!-- 兼容ticwear -->
            <action android:name="com.mobvoi.android.wearable.BIND_LISTENER" />
        </intent-filter>
    </service>

继承OpenWatchListenerService,内部会管理OpenWatchListenerService的生命周期,当有数据接收到时会启动service,当不需要再工作时销毁service,无需手动管理。

public class ListenerService extends OpenWatchListenerService {

@Override
public void onMessageReceived(String path, byte[] rawData) {
	// TODO Auto-generated method stub
	Toast.makeText(this, getClass().getSimpleName() + ":配对设备发来临时性数据", Toast.LENGTH_SHORT).show();
}

@Override
public void onDataReceived(String path, byte[] rawData) {
	// TODO Auto-generated method stub
	Toast.makeText(this, getClass().getSimpleName() + ":配对设备发来数据", Toast.LENGTH_SHORT).show();
}

@Override
public void onDataDeleted(String path, byte[] rawData) {
	// TODO Auto-generated method stub
	Toast.makeText(this, getClass().getSimpleName() + ":配对设备删除了一条数据", Toast.LENGTH_SHORT).show();
}

@Override
public void onDataMapReceived(String path, DataMap dataMap) {
	// TODO Auto-generated method stub
	Toast.makeText(this, getClass().getSimpleName() + ":配对设备发来键值对", Toast.LENGTH_SHORT).show();
}

@Override
public void onBitmapReceived(String path, Bitmap bitmap) {
	// TODO Auto-generated method stub
	Toast.makeText(this, getClass().getSimpleName() + ":配对设备发来图片", Toast.LENGTH_SHORT).show();
}

  @Override
public void onFileReceived(SpecialData data) {
    // TODO Auto-generated method stub
    Toast.makeText(this, getClass().getSimpleName() + ":配对设备发来文件:" + new String(data.getData()), Toast.LENGTH_SHORT)
            .show();

    //保存成文件
    data.receiveFile(getExternalCacheDir() + File.separator + "file.txt");
}

@Override
public void onStreamReceived(SpecialData data) {
    // TODO Auto-generated method stub
    Toast.makeText(this, getClass().getSimpleName() + ":配对设备发来数据流:" + new String(data.getData()), Toast.LENGTH_SHORT).show();

    try {
        FileOutputStream fileOutputStream = new FileOutputStream(new File(getExternalCacheDir(), "file.txt"));
        //写入到输出流
        data.receiveStream(fileOutputStream);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

}

@Override
public void onInputClosed(String path) {
	//在调用SpecialData的receiveStream或receiveFile后回调
    Toast.makeText(this, getClass().getSimpleName() + ":保存配对设备发来的数据完成", Toast.LENGTH_SHORT).show();
}

@Override
public void onPeerConnected(String displayName, String nodeId) {
	// TODO Auto-generated method stub
	Toast.makeText(this, getClass().getSimpleName() + ":和配对设备连接上了  设备名:" + displayName + " 设备id:" + nodeId,
			Toast.LENGTH_SHORT).show();
}

@Override
public void onPeerDisconnected(String displayName, String nodeId) {
	// TODO Auto-generated method stub
	Toast.makeText(this, getClass().getSimpleName() + ":和配对设备断开了连接  设备名:" + displayName + " 设备id:" + nodeId,
			Toast.LENGTH_SHORT).show();
}
}

手表端独立网络请求

需要初始化设备通信相关,详见设备通信相关初始化一节。

大部分智能手表不可以独立联网,OpenWatch提供了在手表端应用中,可独立发起网络请求的方式,支持get和post请求。

OpenWatchHttp http = new OpenWatchHttp(context);
http.get("http://www.baidu.com", new HttpCallback() {

				@Override
				public void onResponse(String response) {
					// TODO Auto-generated method stub
					Log.d(WearListAdapter.class.getName(), response);
					Toast.makeText(context, "网络请求响应成功", Toast.LENGTH_SHORT).show();
				}

				@Override
				public void onError(byte[] data, int statusCode, Map<String, String> headers) {
					// TODO Auto-generated method stub
					Toast.makeText(context, "网络请求响应失败:" + statusCode, Toast.LENGTH_SHORT).show();
				}
			});

可以自定义网络请求的实现方式

OpenWatchHttp.setCustomHttpCaller(new IHttpCaller() {

		@Override
		public void setTimeOutMills(int timeOut) {
			// TODO Auto-generated method stub

		}

		@Override
		public void getWithHeaders(String url, Map<String, String> params, Map<String, String> headers,
				HttpCallback callback) {
			// TODO Auto-generated method stub

		}

		@Override
		public void postWithHeaders(String url, byte[] body, Map<String, String> headers, HttpCallback callback) {
			// TODO Auto-generated method stub

		}

		@Override
		public void cancelAll() {
			// TODO Auto-generated method stub

		}
	});

创建自定义表盘

OpenWatch提供自定义View或者布局文件的方式创建表盘,并提供时间变化与时区变化回调等(详见Demo)。

public class DigitalWatchFace extends OpenWatchFace {

	private TextView timeTextView, dateTextView;

	// 构建表盘布局时回调
	@Override
	public View onCreateView() {
		// TODO Auto-generated method stub

		//设置表盘样式 指针样式等 此处略
		......

		View watchface = View.inflate(this, R.layout.digital_watchface_layout, null);
		timeTextView = (TextView) watchface.findViewById(R.id.watchface_time_tv);
		dateTextView = (TextView) watchface.findViewById(R.id.watchface_date_tv);

		// 返回自定义view或者布局文件生成的view
		return watchface;
	}


	// 时区发生改变时回调
	@Override
	public void onTimeZoneChanged() {
		// TODO Auto-generated method stub
		super.onTimeZoneChanged();
	}

	// 时间发生改变时回调
	@Override
	public void onTimeUpdate(Time time) {
		// TODO Auto-generated method stub
		super.onTimeUpdate(time);

		// 刷新表盘
		invalidate();
	}


}

改变表盘上的日期和时间显示

    @Override
	protected void onWatchFaceDraw(Canvas canvas, Rect bounds) {
		// TODO Auto-generated method stub

		Time time = getTime();
		setDate(time);
		setTime(time);

		super.onWatchFaceDraw(canvas, bounds);
	}

	private void setDate(Time time) {
		String dateStr = (time.month + 1) + "." + time.monthDay + "  " + (time.hour > 12 ? "下午" : "上午");
		dateTextView.setText(dateStr);
	}

	private void setTime(Time time) {
		String minStr = time.minute < 10 ? "0" + time.minute : String.valueOf(time.minute);
		String timeStr = (time.hour > 12 ? time.hour - 12 : time.hour) + ":" + minStr;

		timeTextView.setText(timeStr);
	}

可设置秒针及相关样式,可设置长宽、纯色指针、图片指针等。

@Override
public View onCreateView() {
	// TODO Auto-generated method stub

	OpenWatchFaceStyle style = new OpenWatchFaceStyle(this);

	// 如果需要的话 构建表盘秒针 否则不会绘制秒针
	OpenWatchFaceHand secondHand = new OpenWatchFaceHand();
	secondHand.setLength(DisplayUtil.dip2px(this, 10));
	secondHand.setWidth(DisplayUtil.dip2px(this, 3));
	// 秒针在表盘边界显示
	secondHand.setDrawGravity(OpenWatchFaceHand.DRAW_GRAVITY_BORDER);

	style.setSecondHand(secondHand);

	setStyle(style);

	//设置表盘样式 创建布局等 此处略
	......
}

可设置onTimeUpdate函数的回调频率模式

//这里设置的模式 表现为交互模式下每秒回调一次 省电模式下每分钟回调一次
setTimeUpdateMode(TIME_UPDATE_PER_SECOND_MODE);

可设置表盘样式

@Override
public View onCreateView() {
	// TODO Auto-generated method stub

	OpenWatchFaceStyle style = new OpenWatchFaceStyle(this);

	// 构建秒针及设置秒针样式等 此处略
	......

	// 表盘上的通知卡片以单行高度显示
	style.setCardPeekMode(OpenWatchFaceStyle.PEEK_MODE_SHORT);

	setStyle(style);

	//创建布局等 此处略
	......
}

声明权限

<uses-permission android:name="com.google.android.permission.PROVIDE_BACKGROUND" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

在工程中创建res/xml目录,并创建watch_face.xml文件,文件内容为

<?xml version="1.0" encoding="utf-8"?>
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android" />

注册表盘Service,注意要替换name为自定义类,其中label属性为表盘名称。

<service
android:name="cn.openwatch.wearable.demo.DigitalWatchFace"
android:allowEmbedded="true"
android:label="@string/digital_watch_face_name"
android:permission="android.permission.BIND_WALLPAPER" >
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />

<category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" />
</intent-filter>

<meta-data
android:name="android.service.wallpaper"
android:resource="@xml/watch_face" />

<!-- 表盘预览图 自行替换android:resource 对于圆形设备 预览图会被裁剪成圆形 -->
<meta-data
android:name="com.google.android.wearable.watchface.preview"
android:resource="@drawable/ic_launcher" />
</service>

若应用想构建多个表盘 则可以自定义多个OpenWatchFace子类,并分别注册多个表盘Service。

Proguard混淆配置

Eclipse或其他IDE打包

-keep class cn.openwatch.** {*; }
-dontwarn cn.openwatch.**

Android Studio或Gradle打包

-keep class cn.openwatch.** {*; }
-dontwarn cn.openwatch.**

打包应用

当发布应用的时候,需要将手表端应用嵌入进手机端应用,因为用户不能直接在手表设备上查看或安装应用。

手机端与手表端应用包名、签名要保持一致,手机端应用声明的权限需要包含手表端应用的所有声明权限。

如果打包正确,当用户安装手机端应用后,系统会自动推送手表端应用到配对的手表设备上。如果应用正在开发或者是用debug签名,这个功能就没效果。

手机端应用模块中的权限声明,需要包含手表端应用模块中的所有权限,否则这个功能也会没有效果。

在开发的时候,需要用adb install命令或者直接用相应的IDE(比如Android studio)来安装。

创建一个res/xml/wearable_app_desc.xml文件,里面包含Android Wear应用的版本和路径信息。例如:

<wearableApp package="wearable.app.package.name">
  <versionCode>1</versionCode>
  <versionName>1.0</versionName>
  <rawPathResId>android_wear_micro_apk</rawPathResId> 
</wearableApp>

package, versionCode, 和versionName的值要和手表端应用的AndroidManifest.xml文件中的一样,rawPathResId的值不要改变。

用Android Studio打包

在手机端应用的AndroidManifest.xml文件中,在manifest根标签下添加

xmlns:tools="http://schemas.android.com/tools"

在application标签下添加meta-data 用于引用wearable_app_desc.xml描述文件(针对android wear谷歌版和中国版不需要手动添加手表端App的描述文件,打包的时候,studio会自动添加):

兼容DuWear

<!-- 引用同一个wearable_app_desc文件 需要添加tools:replace="android:resource" 否则打包会报错-->
<meta-data
        android:name="org.owa.wear.app"
        android:resource="@xml/wearable_app_desc"
        tools:replace="android:resource" />

兼容TicWear

 <meta-data
        android:name="com.mobvoi.ticwear.app"
        android:resource="@xml/wearable_app_desc" />

用Eclipse或其他IDE打包

如果你使用的是其他编译方式或者IDE,还可以手动打包。

1、拷贝已签名的手表端应用apk到手机端工程的res/raw目录下,apk重命名为android_wear_micro_apk.apk,文件名不要改变。

3、在手机端应用的AndroidManifest.xml文件中,在application标签下添加一个meta-data 用于引用wearable_app_desc.xml描述文件:

兼容Android Wear谷歌版及中国版

<meta-data android:name="com.google.android.wearable.beta.app"
 android:resource="@xml/wearable_app_desc"/>

兼容DuWear

<meta-data
        android:name="org.owa.wear.app"
        android:resource="@xml/wearable_app_desc" />

兼容TicWear

 <meta-data
        android:name="com.mobvoi.ticwear.app"
        android:resource="@xml/wearable_app_desc" />

##其他##

1、将原生gms谷歌版jar包从几兆精简到了300k

2、删除了原生gms谷歌版jar包中大量的log输出

3、gms谷歌版jar包基于版本6.5 以免用户手机端安装的版本过低 会弹出升级提示

4、gms中国版基于版本7.8

5、为避免gms谷歌版和中国版类名的冲突 用jarjar修改了各自的包名

About

Android Wear & TicWear & Duwear Library

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Java 100.0%