一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Android - Android Wear計(jì)時(shí)器開發(fā)

Android Wear計(jì)時(shí)器開發(fā)

2021-03-11 15:32Android開發(fā)網(wǎng) Android

這篇文章主要介紹了Android Wear計(jì)時(shí)器開發(fā),需要的朋友可以參考下

記得在2013年12月的時(shí)候,有系列文章是介紹怎么開發(fā)一個(gè)智能手表的app,讓用戶可以在足球比賽中記錄停表時(shí)間。隨著android wear的問世,在可穿戴設(shè)備中開發(fā)一款這樣的app確實(shí)是個(gè)很不錯(cuò)的想法,但是按照目前對(duì)于android wear的架構(gòu)了解來說,似乎有些困難。所以本系列文章我們就重寫這個(gè)應(yīng)用,帶領(lǐng)大家進(jìn)入android wear的世界。

本文不會(huì)長(zhǎng)篇大論地講解我們要開發(fā)的這款app的用途,因?yàn)槲覀冊(cè)谥暗南盗形恼乱呀?jīng)深入了解過了。這么說吧,這是一個(gè)計(jì)時(shí)類應(yīng)用,在比賽開始的時(shí)候開始執(zhí)行,在比賽的過程中可以暫停(停表),然后45分鐘過去后會(huì)有震動(dòng)提醒,然后比賽進(jìn)行45分鐘后也會(huì)有提醒。

在開始之前,很有必要先看看我們?yōu)槭裁匆貙戇@個(gè)app而不是直接上代碼。智能手表使用的是一個(gè)修改版的android1.6的系統(tǒng),所以它的架構(gòu)很像一個(gè)運(yùn)行android1.6的手機(jī),所以我們的app基于一個(gè)activity,我們所有的工作都運(yùn)行在這個(gè)activity上。在開始學(xué)習(xí)智能手表開發(fā)之前,我們必須很清楚地知道,我們之前的設(shè)計(jì)在android wear上并不適用,盡管它也是支持activity,但是在android wear上工作方式是不同的。在手機(jī)或者平板上,如果一個(gè)activity從sleep狀態(tài)回到喚醒狀態(tài),activity會(huì)被重新喚醒,但是在wear上卻不是這樣。一段時(shí)間過去后wear設(shè)備會(huì)進(jìn)入sleep,但是在設(shè)備喚醒后,處于sleep狀態(tài)的activity卻不會(huì)再被喚醒了。

首先這個(gè)問題使我非常驚訝,我一直很想知道activity有了這個(gè)限制后,還能開發(fā)實(shí)用的app嗎?后來才發(fā)現(xiàn)這個(gè)問題完全是多慮的,我漸漸地發(fā)現(xiàn),要開發(fā)一個(gè)實(shí)用的app也很簡(jiǎn)單——我們只需要轉(zhuǎn)變我們的軟件設(shè)計(jì)模式,使它更符合android wear的體系結(jié)構(gòu),而不是當(dāng)做一個(gè)手機(jī)來看。

這里我們需要考慮的最基本的問題是,這個(gè)計(jì)時(shí)應(yīng)用程序需要基于一個(gè)一直運(yùn)行的服務(wù)來記錄時(shí)間。但是基于長(zhǎng)運(yùn)行的服務(wù)不是一個(gè)好的方案,因?yàn)樗鼤?huì)耗電。這里我們提到的記錄時(shí)間這個(gè)關(guān)鍵詞,也就是說,我們并不需要真的實(shí)現(xiàn)一個(gè)長(zhǎng)運(yùn)行的服務(wù),只要在用戶需要看的時(shí)候我們可以更新消息顯示就行。在大部分的時(shí)間里,其實(shí)用戶只需要了解大概過去了多長(zhǎng)時(shí)間,只有在比賽暫停或者中場(chǎng)快結(jié)束的時(shí)候才需要顯示更詳細(xì)的信息。所以在大部分的時(shí)間里,我們只需要顯示精確到分鐘即可,然后在用戶需要的時(shí)候才精確到秒。

我們要實(shí)現(xiàn)這個(gè)方法的基本方法就是使用alarmmanager每分鐘觸發(fā)一次更新通知事件,去更新分鐘顯示。這個(gè)通知事件還包括顯示精確到秒的activity,但是只有在用戶滑動(dòng)屏幕的時(shí)候才會(huì)顯示整個(gè)通知。通過這種方式我們可以在必須顯示的時(shí)候才去更新消息,所以對(duì)大部分設(shè)備來說,每分鐘更新一次消息顯示比一直運(yùn)行一個(gè)服務(wù)更加省電。

下圖顯示充分證明了這點(diǎn),首先我們需要打開通知,這樣就可以得到精確到秒的顯示了。

Android Wear計(jì)時(shí)器開發(fā)

然而,在有信息顯示或者設(shè)備休眠的時(shí)候,我們只需要顯示精確到分鐘就可以了。

Android Wear計(jì)時(shí)器開發(fā)

Android Wear計(jì)時(shí)器開發(fā)

有一件事情需要說明一下,就是這個(gè)app的名字已經(jīng)改變了。之前在在i'm watch的版本上叫做“footy timer”,現(xiàn)在改為“match timer”。因?yàn)樵谑褂谜Z音啟動(dòng)app的時(shí)候,google的聲音識(shí)別對(duì)“footy”這個(gè)詞很不敏感,我們用“ok google,start footy timer”這個(gè)命令不能啟動(dòng)應(yīng)用,而使用“ok google,start match timer”就可以使用。

最后,很抱歉這篇文章沒有代碼,但是本系列文章會(huì)稍微有些變動(dòng)。以前本人會(huì)在每篇文章末尾附上文章相關(guān)的代碼段,這個(gè)請(qǐng)放心,之后的文章還是會(huì)這樣的,因?yàn)檫@個(gè)是一個(gè)功能完善的app,而不是系列技術(shù)文章,所以在接下來的文章會(huì)包含一些代碼示例和注釋,在本系列文章完結(jié)的時(shí)候會(huì)附上整個(gè)項(xiàng)目的源碼。

match timer 可以在google play上找到:https://play.google.com/store/apps/details?id=com.stylingandroid.matchtimer

上面我們解釋了為什么要在android wear重寫這個(gè)計(jì)時(shí)器app(因?yàn)橹耙呀?jīng)在“i'm watch”里面開發(fā)過了),下面我們就來看看代碼。

我們以這個(gè)app的一個(gè)核心類開始,這個(gè)類負(fù)責(zé)控制計(jì)時(shí)器的狀態(tài)。這個(gè)類包含了4個(gè)long類型的變量:第一個(gè)代表計(jì)時(shí)器開始的時(shí)間;第二個(gè)代表計(jì)時(shí)器停止的時(shí)間(在運(yùn)行中的話,它就是0);第三個(gè)代表計(jì)時(shí)器停表的時(shí)間(如果當(dāng)前沒有停表,那它也是0),第四個(gè)代表總共停表的時(shí)長(zhǎng)。通過這四個(gè)變量我們就可以維持計(jì)時(shí)器的狀態(tài)了,還可以通過計(jì)算得到我們需要展示的其他信息。這個(gè)類的基本功能就是都是為了操作這些變量,即維持計(jì)時(shí)器的這些狀態(tài)。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public final class matchtimer {
.
.
.
public static final int minute_millis = 60000;
 
private long start;
private long currentstoppage;
private long totalstoppages;
private long end;
.
.
.
public long getelapsed() {
  if (isrunning()) {
    return system.currenttimemillis() - start;
  }
  if (end > 0) {
    return end - start;
  }
  return 0;
}
 
public boolean isrunning() {
  return start > 0 && end == 0;
}
 
public boolean ispaused() {
  return currentstoppage > 0;
}
 
public int getelapsedminutes() {
  return (int) ((system.currenttimemillis() - start) / minute_millis);
}
 
public long gettotalstoppages() {
  long now = system.currenttimemillis();
  if (ispaused()) {
    return totalstoppages + (now - currentstoppage);
  }
  return totalstoppages;
}
 
public long getplayed() {
  return getelapsed() - gettotalstoppages();
}
 
public long getstarttime() {
  return start;
}
.
.
.
}

這些都是基本的java代碼,就不費(fèi)時(shí)間講了。下面的函數(shù)更高級(jí)一些,可以操作計(jì)時(shí)器的狀態(tài)。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public final class matchtimer {
.
.
.
public void start() {
  if (end > 0) {
    start = system.currenttimemillis() - (end - start);
    end = 0;
  } else {
    start = system.currenttimemillis();
  }
  save();
}
 
public void stop() {
  if (ispaused()) {
    resume();
  }
  end = system.currenttimemillis();
  save();
}
 
public void pause() {
  currentstoppage = system.currenttimemillis();
  save();
}
 
public void resume() {
  totalstoppages += system.currenttimemillis() - currentstoppage;
  currentstoppage = 0l;
  save();
}
 
public void reset() {
  resetwithoutsave();
  save();
}
 
private void resetwithoutsave() {
  start = 0l;
  currentstoppage = 0l;
  totalstoppages = 0l;
  end = 0l;
}
}

這些還是基本的java代碼,也可以不用講了。只有save()方法我們還沒有見到,這是在類的最后寫的,這個(gè)函數(shù)才值得的我們講講。

前一篇文章我們討論了關(guān)于喚醒機(jī)制的問題,我們不需要去維持一個(gè)長(zhǎng)連接或者后臺(tái)服務(wù),只需要維持這幾個(gè)計(jì)時(shí)器的狀態(tài)就可以了。我們使用sharedpreference來實(shí)現(xiàn):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  public final class matchtimer implements sharedpreferences.onsharedpreferencechangelistener {
  private static final string key_start = "com.stylingandroid.matchtimer.key_start";
  private static final string key_current_stoppage = "com.stylingandroid.matchtimer.key_current_stoppage";
  private static final string key_total_stoppages = "com.stylingandroid.matchtimer.key_total_stoppages";
  private static final string key_end = "com.stylingandroid.matchtimer.key_end";
  private static final string preferences = "matchtimer";
 
  private final sharedpreferences preferences;
 
  public static matchtimer newinstance(context context) {
    sharedpreferences preferences = context.getsharedpreferences(preferences, context.mode_private);
    long start = preferences.getlong(key_start, 0);
    long currentstoppage = preferences.getlong(key_current_stoppage, 0);
    long totalstoppages = preferences.getlong(key_total_stoppages, 0);
    long end = preferences.getlong(key_end, 0);
    return new matchtimer(preferences, start, currentstoppage, totalstoppages, end);
  }
 
  private matchtimer(sharedpreferences preferences, long start, long currentstoppage, long totalstoppages, long end) {
    this.preferences = preferences;
    this.start = start;
    this.currentstoppage = currentstoppage;
    this.totalstoppages = totalstoppages;
    this.end = end;
  }
 
  public void save() {
    preferences.edit()
        .putlong(key_start, start)
        .putlong(key_current_stoppage, currentstoppage)
        .putlong(key_total_stoppages, totalstoppages)
        .putlong(key_end, end)
        .apply();
  }
 
  public void registerforupdates() {
    preferences.registeronsharedpreferencechangelistener(this);
  }
 
  public void unregisterforupdates() {
    preferences.unregisteronsharedpreferencechangelistener(this);
  }
 
  @override
  public void onsharedpreferencechanged(sharedpreferences sharedpreferences, string key) {
    long value = sharedpreferences.getlong(key, 0l);
    if (key.equals(key_start)) {
      start = value;
    } else if (key.equals(key_end)) {
      end = value;
    } else if (key.equals(key_current_stoppage)) {
      currentstoppage = value;
    } else if (key.equals(key_total_stoppages)) {
      totalstoppages = value;
    }
  }
  .
  .
  .
}

我們需要的就是newinstance()方法從sharedpreference中構(gòu)造一個(gè)matchtimer實(shí)例,我們還需要save()方法,可以幫我們把當(dāng)前的計(jì)時(shí)器狀態(tài)保存到sharedpreference中。

最后我們要說明的是,如果某一部分持有matchtimer對(duì)象的引用,但是其他對(duì)象已經(jīng)改變了計(jì)時(shí)器的狀態(tài),就可能會(huì)發(fā)生異常(見下一篇文章)。所以我們還需要提供一些方法去注冊(cè)和注銷matchtimer的實(shí)例,在sharedpreference的值改變時(shí)去接收計(jì)時(shí)器狀態(tài)的變化。

現(xiàn)在我們已經(jīng)定義了一個(gè)基本的計(jì)時(shí)器了,下一篇文章我們會(huì)介紹怎么保持計(jì)時(shí)器的狀態(tài)以及在需要的時(shí)候去喚醒這些狀態(tài)。

match timer 可以在google play上下載:match timer.

在本系列前幾篇文章中,我們介紹了android wear計(jì)時(shí)器app,對(duì)設(shè)計(jì)思路和app的結(jié)構(gòu)進(jìn)行了分析。本文將講解如何定時(shí)喚醒程序提醒用戶。

對(duì)于為什么不用后臺(tái)服務(wù)的方式一直運(yùn)行,我們已經(jīng)進(jìn)行了解釋——這種方式非常耗電。因此,我們必須要有一個(gè)定時(shí)喚醒機(jī)制。我們可以使用alarmmanager來實(shí)現(xiàn)這個(gè)機(jī)制,定時(shí)執(zhí)行一個(gè)intent,然后通知broadcastreceiver。之所以選擇broadcastreceiver而不用intentservice,是因?yàn)槲覀円\(yùn)行的任務(wù)是輕量級(jí)的而且生命周期非常短暫。使用broadcastreceiver可以避免每次執(zhí)行任務(wù)的時(shí)候都經(jīng)歷service的整個(gè)生命周期。因此,對(duì)于我們這種輕量級(jí)的任務(wù)來說非常合適——我們執(zhí)行的任務(wù)都在毫秒級(jí)。

broadcastreceiver的核心在于onreceiver方法,我們需要在這里安排各種事件響應(yīng)。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
public class matchtimerreceiver extends broadcastreceiver {
public static final int minute_millis = 60000;
private static final long duration = 45 * minute_millis;
 
private static final intent update_intent = new intent(action_update);
private static final intent elapsed_alarm = new intent(action_elapsed_alarm);
private static final intent full_time_alarm = new intent(action_full_time_alarm);
 
private static final int request_update = 1;
private static final int request_elapsed = 2;
private static final int request_full_time = 3;
 
public static void setupdate(context context) {
  context.sendbroadcast(update_intent);
}
.
.
.
private void reset(matchtimer timer) {
  timer.reset();
}
 
private void resume(context context, matchtimer timer) {
  timer.resume();
  long playedend = timer.getstarttime() + timer.gettotalstoppages() + duration;
  if (playedend > system.currenttimemillis()) {
    setalarm(context, request_full_time, full_time_alarm, playedend);
  }
}
 
private void pause(context context, matchtimer timer) {
  timer.pause();
  cancelalarm(context, request_full_time, full_time_alarm);
  long elapsedend = timer.getstarttime() + duration;
  if (!isalarmset(context, request_elapsed, elapsed_alarm) && elapsedend > system.currenttimemillis()) {
    setalarm(context, request_elapsed, elapsed_alarm, elapsedend);
  }
}
 
private void stop(context context, matchtimer timer) {
  timer.stop();
  cancelalarm(context, request_update, update_intent);
  cancelalarm(context, request_elapsed, elapsed_alarm);
  cancelalarm(context, request_full_time, full_time_alarm);
}
 
private void start(context context, matchtimer timer) {
  timer.start();
  long elapsedend = timer.getstarttime() + duration;
  setrepeatingalarm(context, request_update, update_intent);
  if (timer.gettotalstoppages() > 0 && !timer.ispaused()) {
    long playedend = timer.getstarttime() + timer.gettotalstoppages() + duration;
    if (playedend > system.currenttimemillis()) {
      setalarm(context, request_full_time, full_time_alarm, playedend);
    }
    if (elapsedend > system.currenttimemillis()) {
      setalarm(context, request_elapsed, elapsed_alarm, elapsedend);
    }
  } else {
    if (elapsedend > system.currenttimemillis()) {
      setalarm(context, request_full_time, full_time_alarm, elapsedend);
    }
  }
}
.
.
.
}

代碼還是非常直觀易于理解的。首先實(shí)例化一個(gè)matchtimer對(duì)象(從sharedpreference中讀取數(shù)據(jù)),然后分別傳給對(duì)應(yīng)的事件處理handler。之后等待動(dòng)作發(fā)生,最后更新notification。

這里會(huì)處理8個(gè)事件動(dòng)作,其中5個(gè)負(fù)責(zé)控制計(jì)時(shí)器的狀態(tài)(start、stop、pause、resume、reset);一個(gè)負(fù)責(zé)更新notification,剩下兩個(gè)負(fù)責(zé)到45分鐘喚醒后震動(dòng)提示。

我們先從這幾個(gè)控制狀態(tài)開始:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
public class matchtimerreceiver extends broadcastreceiver {
public static final int minute_millis = 60000;
private static final long duration = 45 * minute_millis;
 
private static final intent update_intent = new intent(action_update);
private static final intent elapsed_alarm = new intent(action_elapsed_alarm);
private static final intent full_time_alarm = new intent(action_full_time_alarm);
 
private static final int request_update = 1;
private static final int request_elapsed = 2;
private static final int request_full_time = 3;
 
public static void setupdate(context context) {
  context.sendbroadcast(update_intent);
}
.
.
.
private void reset(matchtimer timer) {
  timer.reset();
}
 
private void resume(context context, matchtimer timer) {
  timer.resume();
  long playedend = timer.getstarttime() + timer.gettotalstoppages() + duration;
  if (playedend > system.currenttimemillis()) {
    setalarm(context, request_full_time, full_time_alarm, playedend);
  }
}
 
private void pause(context context, matchtimer timer) {
  timer.pause();
  cancelalarm(context, request_full_time, full_time_alarm);
  long elapsedend = timer.getstarttime() + duration;
  if (!isalarmset(context, request_elapsed, elapsed_alarm) && elapsedend > system.currenttimemillis()) {
    setalarm(context, request_elapsed, elapsed_alarm, elapsedend);
  }
}
 
private void stop(context context, matchtimer timer) {
  timer.stop();
  cancelalarm(context, request_update, update_intent);
  cancelalarm(context, request_elapsed, elapsed_alarm);
  cancelalarm(context, request_full_time, full_time_alarm);
}
 
private void start(context context, matchtimer timer) {
  timer.start();
  long elapsedend = timer.getstarttime() + duration;
  setrepeatingalarm(context, request_update, update_intent);
  if (timer.gettotalstoppages() > 0 && !timer.ispaused()) {
    long playedend = timer.getstarttime() + timer.gettotalstoppages() + duration;
    if (playedend > system.currenttimemillis()) {
      setalarm(context, request_full_time, full_time_alarm, playedend);
    }
    if (elapsedend > system.currenttimemillis()) {
      setalarm(context, request_elapsed, elapsed_alarm, elapsedend);
    }
  } else {
    if (elapsedend > system.currenttimemillis()) {
      setalarm(context, request_full_time, full_time_alarm, elapsedend);
    }
  }
}
.
.
.
}

這些方法主要有兩個(gè)功能:首先設(shè)置matchtimer的狀態(tài),然后設(shè)置時(shí)間提醒的鬧鈴,改變參數(shù)就可以播放鬧鈴。這個(gè)功能還可以封裝成一個(gè)工具方法,叫setupdate()。這樣外部也可以觸發(fā)計(jì)時(shí)器的更新。

我們使用標(biāo)準(zhǔn)alarmmanager的方法來設(shè)置鬧鈴:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class matchtimerreceiver extends broadcastreceiver {
.
.
.
public static final int minute_millis = 60000;
.
.
.
 
private void setrepeatingalarm(context context, int requestcode, intent intent) {
  alarmmanager alarmmanager = (alarmmanager) context.getsystemservice(context.alarm_service);
  pendingintent pendingintent = pendingintent.getbroadcast(context, requestcode, intent, pendingintent.flag_update_current);
  alarmmanager.setrepeating(alarmmanager.rtc_wakeup, system.currenttimemillis(), minute_millis, pendingintent);
}
 
private boolean isalarmset(context context, int requestcode, intent intent) {
  return pendingintent.getbroadcast(context, requestcode, intent, pendingintent.flag_no_create) != null;
}
 
private void setalarm(context context, int requestcode, intent intent, long time) {
  alarmmanager alarmmanager = (alarmmanager) context.getsystemservice(context.alarm_service);
  pendingintent pendingintent = pendingintent.getbroadcast(context, requestcode, intent, pendingintent.flag_update_current);
  alarmmanager.setexact(alarmmanager.rtc_wakeup, time, pendingintent);
}
 
private void cancelalarm(context context, int requestcode, intent intent) {
  pendingintent pendingintent = pendingintent.getbroadcast(context, requestcode, intent, pendingintent.flag_no_create);
  if (pendingintent != null) {
    alarmmanager alarmmanager = (alarmmanager) context.getsystemservice(context.alarm_service);
    alarmmanager.cancel(pendingintent);
    pendingintent.cancel();
  }
}
.
.
.
}

這里值得討論的是setrepeatingalarm()這個(gè)方法。因?yàn)樵趙ear在實(shí)現(xiàn)方式上有點(diǎn)不一樣。我們會(huì)在start事件中每秒鐘觸發(fā)一次鬧鈴更新notification動(dòng)作,所以這里需要記錄具體已經(jīng)過去了多少分鐘。正常來說我們會(huì)每隔60秒觸發(fā)一次這個(gè)動(dòng)作,但是在wear上不能這么做。原因是——當(dāng)設(shè)備在喚醒著的時(shí)候可以這樣做,但是如果設(shè)備進(jìn)入睡眠狀態(tài)就需要重新計(jì)算下一分鐘的邊界值。這就需要異步更新部件,然后設(shè)備只需要每分鐘喚醒一次。一分鐘結(jié)束后在計(jì)時(shí)器需要更新狀態(tài)的時(shí)候觸發(fā)操作。

對(duì)于我們的計(jì)時(shí)器應(yīng)用來說,顯示的分鐘數(shù)會(huì)比實(shí)際時(shí)間少1分鐘。但是顯示分鐘并不要求非常實(shí)時(shí)(但顯示秒數(shù)時(shí)需要非常精確),所以我們可以這樣操作:

完整的alarm handler是這樣使用振動(dòng)服務(wù)的:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class matchtimerreceiver extends broadcastreceiver {
.
.
.
private static final long[] elapsed_pattern = {0, 500, 250, 500, 250, 500};
private static final long[] full_time_pattern = {0, 1000, 500, 1000, 500, 1000};
 
private void elapsedalarm(context context) {
  vibrator vibrator = (vibrator) context.getsystemservice(context.vibrator_service);
  vibrator.vibrate(elapsed_pattern, -1);
}
 
private void fulltimealarm(context context) {
  vibrator vibrator = (vibrator) context.getsystemservice(context.vibrator_service);
  vibrator.vibrate(full_time_pattern, -1);
}
.
.
.
}

最后,我們通過這個(gè)方法來構(gòu)造notification然后呈現(xiàn)給用戶:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public class matchtimerreceiver extends broadcastreceiver {
public static final int notification_id = 1;
.
.
.
private void updatenotification(context context, matchtimer timer) {
  notificationbuilder builder = new notificationbuilder(context, timer);
  notification notification = builder.buildnotification();
  notificationmanagercompat notificationmanager = notificationmanagercompat.from(context);
  notificationmanager.notify(notification_id, notification);
}
}

notification是wear計(jì)時(shí)器的一個(gè)重要的部分,這里還需要一個(gè)自定義類來構(gòu)造這些notification通知。下一篇文章我們會(huì)講如何在計(jì)時(shí)器app中使用notification。

match timer可以在google play上下載:match timer

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 91在线视频国产 | 国模孕妇季玥337p人体 | 欧美日韩精品一区二区三区视频 | 国产在线91 | 亚洲激情网 | 成人做视频免费 | 娇妻在床上迎合男人 | 午夜福利理论片在线播放 | 日韩在线a视频免费播放 | 经典WC女厕所里TV | chinese男同志videos | 亚洲va精品中文字幕 | 青青草精品 | 成人综合婷婷国产精品久久免费 | 欧美一区二区三区综合色视频 | 国产一区二区免费不卡在线播放 | 国产成人久久精品区一区二区 | 国产精品亚欧美一区二区三区 | chinese调教踩踏视频 | 操美女 | 日韩毛片在线 | 欧美一区二区三区视视频 | 国产精品久久国产三级国电话系列 | 国内自拍网红在线自拍综合 | 成人欧美一区二区三区 | 紧身裙女教师miad711在线 | 久久亚洲精品AV成人无码 | 色操网| 国产精品免费拍拍拍 | 久久综合亚洲色hezyo | 男老头澡堂gay老头456 | 精品一区二区免费视频蜜桃网 | 成人另类视频 | 亚洲午夜视频 | 国内精品视频一区二区三区八戒 | www.av免费| 欧美人与禽交片在线播放 | 国产亚洲精品看片在线观看 | 日本高清在线播放一区二区三区 | 美女做又爽又黄又猛 | 羞羞视频动漫 |