Creating en Android Wear Watch Face
30
Del
7
Del
Dette Cyber mandag Envato Tuts + Kursene vil bli redusert til bare $ 3. Ikke gå glipp av.
En av funksjonene som gjør Android så spesiell er muligheten til å tilpasse alle aspekter av brukeropplevelsen. Når Android Wear først lansert på Google I /O 2014, mange utviklere og brukere fant ut at dette ikke var helt sant for smarte klokker, som den offisielle API for å lage ur ansikter var merkbart mangler. Gitt at evnen til å lage egendefinerte watch ansikter var en av de viktigste ønsker fra brukere, er det ikke overraskende at utviklerne oppdaget en måte å skape sin egen klokke ansikter med en udokumentert hack i Android Wear.
Heldigvis, Google raskt la alle vite at en offisiell API var på vei, og i desember 2014 at API ble endelig sluppet til utviklingen samfunnet. I denne artikkelen kommer du til å lære om den offisielle Watch Faces API for Android Wear og implementere en enkel digital klokke ansikt som du vil være i stand til å utvide på for dine egne behov. Implementering watch ansikter kan være litt detaljert, men du kan finne prøveprogrammet for denne artikkelen på GitHub.
1. Sette opp IDE
Det første du kommer til å trenge å gjøre for å lage din egen urskiven er få prosjektet satt opp i Android Studio. Når du oppretter prosjektet, velger du Telefon og Tablet med en Minimum SDK av API 18 som Android 4.3 er den laveste versjonen av operativsystemet som støtter medfølgende Android-Wear-programmer. Du må også sjekke Wear boks med en Minimum SDK av API 21 valgt. Du kan se et eksempel på hva målet Android-enheter skjermen skal se ut.
Når du kommer til de to legge til en aktivitet skjermer, velg Legg Ingen aktivitet for begge skjermene. Anmeldelser
Når du klikker på Fullfør, bør prosjektet miljø bygge og ha en modul for mobil og en annen for slitasje.
2. Bygge Wear Watch Service Denne
Android Wear redskaper se ansiktene gjennom bruk av WatchFaceService. I denne artikkelen kommer du til å lage en forlengelse av CanvasWatchFaceService klassen, som er en implementering av WatchFaceService som også gir en magnet for å trekke ut din urskiven. Start med å lage en ny Java-klassen under slite modulen i Android Studio som strekker CanvasWatchFaceService.
Public class WatchFaceService strekker CanvasWatchFaceService
Når du har din klasse, du kommer til å trenge for å skape en indre klasse, WatchFaceEngine i kildefilene i denne artikkelen, som strekker Engine. Dette er urskiven motor som håndterer systemhendelser, slik som skjermen slås av eller går inn ambient-modus.
Private class WatchFaceEngine strekker Engine
Når stub kode for WatchFaceEngine er i, gå tilbake til den ytre klassen og overstyre onCreateEngine metode for å returnere den nye indre klasse. Dette vil knytte urskiven tjeneste med kode som vil drive skjermen
Overridepublic Engine onCreateEngine () {return new WatchFaceEngine ();}.
Når du har bare bones tjeneste satt sammen, du kan gå videre til de generelle rengjøringsoppgaver å oppdatere dine AndroidManifest filer slik at tjenesten vil være synlig for Android Wear. Husk at din nåværende koden ikke vil gjøre noe ennå. Vi vil komme tilbake til denne klassen og kjøtt ut av motoren etter å gjøre noen prosjekt rengjøring.
3. Oppdatere AndroidManifest Files
Åpne AndroidManifest.xml filen i slitasje modulen. Nær toppen bør du allerede se en linje som sier:
< bruker-feature android: name = "android.hardware.type.watch" />
Under denne linjen, må vi legge i de to nødvendige tillatelser for et urskiven. Dette kravet er:
< bruker-tillatelse android: name = "com.google.android.permission.PROVIDE_BACKGROUND" /> < bruker-tillatelse android: name = "android.permission.WAKE_LOCK" /> < p> Når tillatelsene er satt, må du legge til en node for din tjeneste i søknaden node med tillatelse til BIND_WALLPAPER, et par sett med meta-data som inneholder referanse bilder av din urskiven for valgskjermen (i dette eksempelet vi er kun ved hjelp av bærerakett ikonet), og en intensjon-filter for å la systemet vite at tjenesten er ment for å vise et urskiven
< tjeneste android: ".. service.CustomWatchFaceService" name = android: label = "Tuts + Wear Watch Face" android: tillatelse = "android.permission.BIND_WALLPAPER" > < meta-data android: name = "android.service.wallpaper" android: ressurs = "@ xml /watch_face" /> < meta-data android: name = "com.google.android.wearable.watchface.preview" android: ressurs = "@ Mipmap /ic_launcher" /> < meta-data android: name = "com.google.android.wearable.watchface.preview_circular" android: ressurs = "@ Mipmap /ic_launcher" /> < intent-filter > < handling android: name = "android.service.wallpaper.WallpaperService" /> < kategori android: name = "com.google.android.wearable.watchface.category.WATCH_FACE" /> < /intent-filter > < /tjenesten >
Når slitasje manifest er fullført, må du åpne AndroidManifest.xml filen i mobilmodul og legg i de to tillatelsene vi brukte i slite modul for PROVIDE_BACKGROUND og WAKE_LOCK, fordi Android Wear krever at både slitasje og mobile moduler be om de samme tillatelsene for slitasje APK som skal installeres på brukerens watch. Når begge manifestfiler er fylt ut, kan du gå tilbake til CustomWatchFaceService.java begynne å innføre motoren.
4. Start din Engine
Engine objekt som er tilknyttet tjenesten er det som driver din urskiven. Det håndterer tidtakere, viser brukergrensesnittet, beveger seg inn og ut av ambient-modus, og få informasjon om den fysiske klokke displayet. Kort sagt, dette er der magien skjer
Trinn 1:. Definere nødvendige verdier og variabler
Det første du kommer til å ønske å gjøre er å implementere et sett av medlem variabler i din motoren for å holde oversikt over enhetsstater, timer intervaller, og attributter for skjermen
//Medlems variablesprivate Face WATCH_TEXT_TYPEFACE = Typeface.create (Typeface.SERIF, Typeface.NORMAL);. private static final int MSG_UPDATE_TIME_ID = 42; privat lang mUpdateRateMs = 1 000, privat tid mDisplayTime; privat Paint mBackgroundColorPaint; privat Paint mTextColorPaint; private boolean mHasTimeZoneReceiverBeenRegistered = false; private boolean mIsInMuteMode; private boolean mIsLowBitAmbient; privat float mXOffset; privat float mYOffset; private int mBackgroundColor = Color.parseColor ("svart"); private int mTextColor = Color.parseColor ("rød");
Som du ser, vi definerer skriftsnitt som vi vil bruke for vår digitale ur teksten samt urskiven bakgrunnsfarge og tekstfarge. The Time objektet brukes for, du gjettet det, holde styr på den aktuelle enheten tid. mUpdateRateMs brukes til å kontrollere en timer som vi må iverksette for å oppdatere vår urskiven hvert sekund (derav 1000 millisekunder valuta for mUpdateRateMs), fordi standarden WatchFaceService holder bare styr på tiden i ett minutt av gangen. mXOffset og mYOffset defineres når motoren kjenner den fysiske formen på vakt, slik at våre urskiven kan trekkes uten å være for nær toppen eller venstre på skjermen, eller å bli avskåret av et avrundet hjørne. De tre boolske verdier brukes til å holde styr på forskjellige enheter og programland.
Den neste objekt du må definere er en radiomottaker som håndterer situasjonen der en bruker kan være på reise og endre tidssoner. Denne mottakeren bare sletter ut den lagrede tidssone og tilbakevisningstiden.
Endelige BroadcastReceiver mTimeZoneBroadcastReceiver = new BroadcastReceiver () {Override public void OnReceive (Context kontekst, Intent hensikt) {mDisplayTime.clear (intent.getStringExtra ("time -sone" ) ); mDisplayTime.setToNow (); }};
Etter at mottakeren er definert, det siste objektet du trenger for å lage på toppen av motoren din er en Handler å tar vare på oppdatere urskiven hvert sekund. Dette er nødvendig på grunn av begrensningene i WatchFaceService omtalt ovenfor. Hvis din egen urskiven bare må oppdateres hvert minutt, så kan du trygt ignorere denne delen.
Privat endelige Handler mTimeHandler = new Handler () {Override public void handleMessage (Message msg) {switch (msg.what) {case MSG_UPDATE_TIME_ID: {ugyldig (); if (isVisible () & &! isInAmbientMode ()) {lang currentTimeMillis = System.currentTimeMillis (); lang forsinkelse = mUpdateRateMs - (currentTimeMillis% mUpdateRateMs); mTimeHandler.sendEmptyMessageDelayed (MSG_UPDATE_TIME_ID, delay); } gå i stykker; }}}};
Gjennomføringen av Handler er ganske grei. Den sjekker første meldingen ID. Hvis kamper MSG_UPDATE_TIME_ID, fortsetter det å oppheve gjeldende visning for redrawing. Etter visningen har blitt ugyldiggjort, kontrollerer Handler for å se om skjermen er synlig og ikke i ambient-modus. Hvis det er synlig, sender den en gjentakelse forespørsel et sekund senere. Grunnen til at vi er bare å gjenta handlingen i Handler når klokken ansiktet er synlig og ikke i ambient-modus er at det kan være litt batterikrevende å holde oppdatere hvert sekund. Hvis brukeren ikke er å se på skjermen, vi bare falle tilbake på WatchFaceService implementering som oppdateres hvert minutt
Trinn 2:. Initial motor
Nå som variabler og objekter er erklært , er det på tide å begynne å initial urskiven. Motoren har en onCreate metode som skal brukes for å lage objekter og andre oppgaver som kan ta en betydelig mengde tid og batteri. Du vil også være lurt å sette noen flagg for WatchFaceStyle her for å kontrollere hvordan systemet samhandler med brukeren når urskiven er aktiv
Overridepublic void onCreate (SurfaceHolder holder) {super.onCreate (holder).; setWatchFaceStyle (ny WatchFaceStyle.Builder (CustomWatchFaceService.this) .setBackgroundVisibility (WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE) .setCardPeekMode (WatchFaceStyle.PEEK_MODE_VARIABLE) .setShowSystemUiTime (falsk) att bygga ()); mDisplayTime = nye Time (); initBackground (); initDisplayText ();}
For prøven app, vil du bruke setWatchFaceStyle å sette bakgrunnen av dine varslings kort å kort vise om korttype er angitt som interruptive. Du vil også sette titt modus slik at varslings kort bare ta opp så mye plass som er nødvendig.
Til slutt, vil du ønsker å fortelle systemet til å ikke vise standard tid siden du skal vise det selv . Selv om disse er bare noen få av de tilgjengelige alternativene, kan du finne enda mer informasjon i den offisielle dokumentasjonen for WatchFaceStyle.Builder objektet.
Etter WatchFaceStyle er satt, kan du initial mDisplayTime som en ny tid objekt .
initBackground og initDisplayText fordele de to malings objekter som du definerte på toppen av motoren. Bakgrunnen og teksten da har sin farge satt og teksten har sin skrifttype og skriftstørrelse sett, samtidig som du slår på anti-aliasing
private void initBackground () {mBackgroundColorPaint = new Paint (.); mBackgroundColorPaint.setColor (mBackgroundColor);} private void initDisplayText () {mTextColorPaint = new Paint (); mTextColorPaint.setColor (mTextColor); mTextColorPaint.setTypeface (WATCH_TEXT_TYPEFACE); mTextColorPaint.setAntiAlias (true); mTextColorPaint.setTextSize (getResources () getDimension (R.dimen.text_size).);}
Trinn 3: Håndtering Device State
Deretter må du gjennomføre ulike metoder fra Engine klasse som er utløst av endringer i enhetsstatusen. Vi starter med å gå over onVisibilityChanged metoden, som kalles når brukeren skjuler eller viser urskiven
Overridepublic void onVisibilityChanged (boolsk synlig) {super.onVisibilityChanged (synlig).; if (synlig) {if (mHasTimeZoneReceiverBeenRegistered!) {IntentFilter filter = new IntentFilter (Intent.ACTION_TIMEZONE_CHANGED); CustomWatchFaceService.this.registerReceiver (mTimeZoneBroadcastReceiver, filter); mHasTimeZoneReceiverBeenRegistered = true; } MDisplayTime.clear (TimeZone.getDefault () getID ().); mDisplayTime.setToNow (); } Else {if (mHasTimeZoneReceiverBeenRegistered) {CustomWatchFaceService.this.unregisterReceiver (mTimeZoneBroadcastReceiver); mHasTimeZoneReceiverBeenRegistered = false; }} UpdateTimer ();}
Når denne metoden kalles, sjekker den for å se om urskiven er synlig eller ikke. Hvis urskiven er synlig, det ser ut for å se om BroadcastReceiver at du har definert på toppen av motoren er registrert. Hvis det ikke er det, skaper metoden en IntentFilter for ACTION_TIMEZONE_CHANGED handling og registrerer BroadcastReceiver å lytte til det.
Hvis urskiven er ikke synlig, vil denne metoden sjekke for å se om BroadcastReceiver kan være uregistrert . Når BroadcastReceiver har blitt håndtert, er updateTimer kalt til å utløse ugyldig urskiven og tegne urskiven. . updateTimer stopper eventuelle Handler handlinger som venter og sjekker for å se om en annen skal sendes
private void updateTimer () {mTimeHandler.removeMessages (MSG_UPDATE_TIME_ID); if (isVisible () & &! isInAmbientMode ()) {mTimeHandler.sendEmptyMessage (MSG_UPDATE_TIME_ID); }}
Trinn 4: samarbeider med Wearable Hardware
Når tjenesten er assosiert med Android Wear, onApplyWindowInsets kalles. Dette brukes til å finne ut om enheten din urskiven kjører på er avrundet eller firkantet. Dette lar deg endre urskiven til å matche opp med maskinvaren.
Når denne metoden kalles i prøveprogrammet, sjekker denne metoden bare enheten forme og endrer x offset brukes for å tegne opp urskiven å gjøre for at urskiven er synlig på enheten
Overridepublic void onApplyWindowInsets (WindowInsets innfellinger) {super.onApplyWindowInsets (innfellinger).; mYOffset = getResources () getDimension (R.dimen.y_offset.); if (insets.isRound ()) {mXOffset = getResources () getDimension (R.dimen.x_offset_round.); } Else {mXOffset = getResources () getDimension (R.dimen.x_offset_square.); }}
Den neste metoden som du må overstyre er onPropertiesChanged. Denne metoden kalles når maskinvaren egenskaper for Wear enheten er bestemt, for eksempel hvis enheten støtter innbrenning beskyttelse eller lav bit ambient modus.
I denne metoden, sjekker du om disse attributtene gjelder enhet som kjører din urskiven og lagre dem i et medlem variabel definert på toppen av din Engine
Overridepublic void onPropertiesChanged (Bundle egenskaper) {super.onPropertiesChanged (egenskaper).; if (properties.getBoolean (PROPERTY_BURN_IN_PROTECTION, false)) {mIsLowBitAmbient = properties.getBoolean (PROPERTY_LOW_BIT_AMBIENT, false); }}
Trinn 5: Spare batteri i Ambient og Dempet Modes
Når du håndterer de innledende enhetsstater, vil du ønsker å implementere onAmbientModeChanged og onInterruptionFilterChanged. Som navnet tilsier, er onAmbientModeChanged kalles når de beveger enheten i eller ut av ambient-modus.
Hvis enheten er i ambient-modus, vil du ønsker å endre fargen på urskiven til å være svart og hvitt til være oppmerksom på brukerens batteri. Når enheten er på vei tilbake fra ambient modus kan du tilbakestille urskiven farger. Du vil også være lurt å være oppmerksom på anti-aliasing for enheter som ber om lav oppslutning litt ambient. Etter at alle flagg variablene er satt, kan du føre opp urskiven å ugyldig og tegne, og deretter sjekke om den andre timeren skal starte
Overridepublic void onAmbientModeChanged (boolsk inAmbientMode) {super.onAmbientModeChanged (inAmbientMode.); if (inAmbientMode) {mTextColorPaint.setColor (Color.parseColor ("hvit")); } Else {mTextColorPaint.setColor (Color.parseColor ("rød")); } If (mIsLowBitAmbient) {mTextColorPaint.setAntiAlias (inAmbientMode!); } Ugyldig (); updateTimer ();}
onInterruptionFilterChanged kalles når brukeren endrer avbruddsinnstillingene på sin bærbare manuelt. Når dette skjer, må du sjekke om enheten er dempet og deretter endre brukergrensesnittet tilsvarende. I denne situasjonen, vil du endre gjennomsiktigheten din urskiven, angi Handler bare oppdatere hvert minutt hvis enheten er dempet, og deretter tegne din urskiven.
Overridepublic Void onInterruptionFilterChanged (int interruptionFilter) {super.onInterruptionFilterChanged (interruptionFilter); boolean isDeviceMuted = (interruptionFilter == android.support.wearable.watchface.WatchFaceService.INTERRUPTION_FILTER_NONE); if (isDeviceMuted) {mUpdateRateMs = TimeUnit.MINUTES.toMillis (1); } Else {mUpdateRateMs = DEFAULT_UPDATE_RATE_MS; } If (mIsInMuteMode = isDeviceMuted!) {MIsInMuteMode = isDeviceMuted; int alpha = (isDeviceMuted)? 100: 255; mTextColorPaint.setAlpha (alfa); ugyldig (); updateTimer (); }}
Når enheten er i ambient-modus, vil Handler timeren deaktiveres. Din urskiven kan fortsatt oppdatere med gjeldende tid hvert minutt gjennom å bruke den innebygde onTimeTick metode for å oppheve Canvas
Overridepublic void onTimeTick () {super.onTimeTick (.); ugyldig ();}
Trinn 6: Tegning urskiven
Når alle dine eventualiteter er dekket, er det på tide å endelig trekke ut urskiven. CanvasWatchFaceService bruker en standard Canvas objekt, så du må legge onDraw til din motor og manuelt trekke ut urskiven.
I denne opplæringen vi bare kommer til å tegne en tekstrepresentasjon av tiden, selv om du kunne endre onDraw å enkelt støtte en analog klokke ansikt. I denne metoden, vil du ønsker å bekrefte at du viser korrekt tid ved å oppdatere Time objekt og deretter kan du begynne å bruke ditt urskiven.
Overridepublic Void onDraw (Canvas lerret, rect grenser) {super.onDraw ( lerret, grenser); mDisplayTime.setToNow (); drawBackground (lerret, grenser); drawTimeText (lerret);.}
drawBackground gjelder en farge til bakgrunnen av Wear enheten
private void drawBackground (Canvas lerret, rect grenser) {canvas.drawRect (0, 0, bounds.width () bounds.height (), mBackgroundColorPaint);}
drawTimeText skaper imidlertid tiden tekst som skal vises ved hjelp av et par hjelpemetoder og da gjelder det å lerretet på x og y offset poeng som du definerte i onApplyWindowInsets
private void drawTimeText (lerret lerret) {String timeText = getHourString () + ":". + String.format ("% 02d", mDisplayTime.minute); if (isInAmbientMode () || mIsInMuteMode) {timeText + = (mDisplayTime.hour < 12)? "FORMIDDAG ETTERMIDDAG"; } Else {timeText + = String.format (":% 02d", mDisplayTime.second); } Canvas.drawText (timeText, mXOffset, mYOffset, mTextColorPaint);} private String getHourString () {if (mDisplayTime.hour% 12 == 0) return "12"; else if (mDisplayTime.hour < = 12) tilbake String.valueOf (mDisplayTime.hour); annet tilbake String.valueOf (mDisplayTime.hour - 12);}
Konklusjon
Når du har implementert de metoder for å tegne ditt urskiven, bør du være klar med den grunnleggende kunnskapen som trengs for å gå ut og lage din egen klokke ansikter. Det fine med Android Wear watch står overfor er at dette er bare toppen av isfjellet av hva som er mulig.
Du kan legge følgeskonfigurasjons aktiviteter på klokken eller på telefonen, må du bytte Canvas basert urskiven med OpenGL implementering eller utlede din egen klasse fra WatchFaceService å møte dine behov.
Legg til at du kan få tilgang til andre APIer eller informasjon fra brukerens telefon og mulighetene virker uendelige. Vær kreativ med ur ansikter og nyte.