Advertisement
Scroll to top
Read Time: 13 min

() translation by (you can also view the original English article)

Salah satu fitur yang membuat Android begitu istimewa adalah kemampuan untuk menyesuaikan setiap aspek dari pengalaman pengguna. Ketika memakai Android pertama kali diluncurkan di Google i/o 2014, banyak developer dan user menemukan bahwa ini tidak benar untuk smart watches, sebagai API resmi untuk membuat watch faces itu terasa hilang. Mengingat bahwa kemampuan untuk membuat custom watch faces adalah salah satu kunci ingin dari pengguna, hal ini tidak mengherankan bahwa developer menemukan cara untuk membuat watch faces mereka sendiri dengan tidak terdokumentasikan hack di Android Wear.

Untungnya, Google cepat membiarkan semua orang tahu bahwa API resmi di jalan dan di Desember 2014 yang API akhirnya dirilis ke komunitas development. Dalam artikel ini, Anda akan belajar tentang official Watch Faces API untuk memakai Android dan implementasi simple digital watch face bahwa Anda akan mampu memperluas pada kebutuhan Anda sendiri. Menerapkan watch faces dapat sedikit verbose, tetapi Anda dapat menemukan contoh aplikasi untuk artikel ini pada GitHub.

1. menyiapkan IDE Anda

Hal pertama yang Anda akan perlu untuk membuat wajah menonton Anda sendiri adalah mendapatkan proyek Anda di Android Studio. Ketika membuat proyek Anda, pilih Phone and Tablet dengan SDK Minimum API 18 sebagai Android 4.3 versi terendah dari sistem operasi untuk mendukung dibundel memakai Android aplikasi. Anda juga perlu untuk memeriksa Wear box memakai dengan Minimum SDK dari API 21 dipilih. Anda dapat melihat contoh dari Target Android Device layar akan terlihat seperti apa.

Ketika Anda mendapatkan ke dua Add an Activity, pilih Add No Activity untuk kedua layar.

Setelah mengklik Finish, project enviroment Anda harus membangun dan memiliki modul untuk mobile dan satu lagi untuk wear.

2. Membuat Wear Watch Service

Android memakai mengimplementasikan watch facdes melalui WatchFaceService. Dalam artikel ini, Anda akan membuat ekstensi CanvasWatchFaceService kelas, yang merupakan implementasi WatchFaceService yang juga menyediakan sebuah Canvas untuk menggambar watch face. Mulailah dengan membuat kelas Java baru di bawah modul wear di Studio Android yang extend CanvasWatchFaceService.

1
public class WatchFaceService extends CanvasWatchFaceService

Setelah Anda memiliki kelas Anda, Anda akan perlu untuk membuat inner kelas, WatchFaceEngine dalam file sumber dari artikel ini, yang extend Engine. Ini adalah watch face engine yang menangani sistem event, seperti layar mematikan atau pergi ke modus ambient.

1
private class WatchFaceEngine extends Engine

Ketika kode stub untuk WatchFaceEngine dimasukan, kembali ke luar kelas dan meng-override metode onCreateEngine untuk kembali ke kelas inner yang baru. Ini akan mengasosiasikan watch face service dengan kode yang akan mendorong tampilan.

1
@Override
2
public Engine onCreateEngine() {
3
    return new WatchFaceEngine();
4
}

Setelah Anda memiliki layanan tulang telanjang menempatkan bersama-sama, Anda dapat melanjutkan untuk tugas-tugas rumah tangga umum memperbarui file AndroidManifest sehingga layanan Anda akan ditemukan oleh Android Wear. Perlu diketahui bahwa kode Anda saat ini tidak akan melakukan apa pun belum. Kami akan kembali ke kelas ini dan flesh out engine setelah melakukan beberapa project housekeeping.

3. memperbarui AndroidManifest file

Buka AndroidManifest.xml file dalam modul wear. Di dekat bagian atas Anda harus sudah melihat garis yang mengatakan:

1
<uses-feature android:name="android.hardware.type.watch" />

Di bawah baris tersebut, kita perlu menambahkan dua permission yang diperlukan untuk watch face. Persyaratan tersebut adalah:

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

Setelah permission Anda ditetapkan, Anda akan perlu untuk menambahkan sebuah node untuk layanan Anda di node application dengan permission untuk BIND_WALLPAPER, beberapa set meta-data yang berisi referensi gambar wajah Anda menonton untuk layar seleksi (dalam contoh ini kita hanya menggunakan ikon pelancar), dan intent-filter untuk membiarkan sistem mengetahui bahwa layanan Anda dimaksudkan untuk menampilkan watch face.

1
<service android:name=".service.CustomWatchFaceService"
2
    android:label="Tuts+ Wear Watch Face"
3
    android:permission="android.permission.BIND_WALLPAPER">
4
5
    <meta-data
6
        android:name="android.service.wallpaper"
7
        android:resource="@xml/watch_face" />
8
    <meta-data
9
        android:name="com.google.android.wearable.watchface.preview"
10
        android:resource="@mipmap/ic_launcher" />
11
    <meta-data
12
        android:name="com.google.android.wearable.watchface.preview_circular"
13
        android:resource="@mipmap/ic_launcher" />
14
    <intent-filter>
15
        <action android:name="android.service.wallpaper.WallpaperService" />
16
        <category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" />
17
    </intent-filter>
18
19
</service>

Setelah wear manifest selesai, Anda akan perlu untuk membuka AndroidManifest.xml file pada modul mobile dan menambahkan dalam dua permission kami digunakan dalam modul wear untuk PROVIDE_BACKGROUND dan WAKE_LOCK, karena Android memakai mengharuskan wear dan mobile modul meminta permission yang sama untuk wear APK untuk diinstal pada user watch. Setelah kedua file manifest diisi, Anda dapat kembali ke CustomWatchFaceService.java untuk mulai menerapkan engine.

4. Memulai Engine anda

Objek Engine yang terkait dengan layanan Anda adalah apa yang mendorong watch face anda. Ini menangani timer, menampilkan user interface Anda, bergerak masuk dan keluar dari modus ambient, dan mendapatkan informasi tentang tampilan fisik watch. Singkatnya, ini adalah dimana magic happen.

Langkah 1: Mendefinisikan nilai-nilai yang diperlukan dan variabel

Hal pertama yang Anda akan ingin lakukan adalah menerapkan serangkaian variabel member di engine Anda untuk melacak perangkat state, timer interval dan atribut untuk tampilan Anda.

1
//Member variables

2
private Typeface WATCH_TEXT_TYPEFACE = Typeface.create( Typeface.SERIF, Typeface.NORMAL );
3
4
private static final int MSG_UPDATE_TIME_ID = 42;
5
private long mUpdateRateMs = 1000;
6
7
private Time mDisplayTime;
8
9
private Paint mBackgroundColorPaint;
10
private Paint mTextColorPaint;
11
12
private boolean mHasTimeZoneReceiverBeenRegistered = false;
13
private boolean mIsInMuteMode;
14
private boolean mIsLowBitAmbient;
15
16
private float mXOffset;
17
private float mYOffset;
18
19
private int mBackgroundColor = Color.parseColor( "black" );
20
private int mTextColor = Color.parseColor( "red" );

Seperti yang Anda lihat, kita mendefinisikan TypeFace yang kita akan gunakan untuk teks digital watch serta watch face background dan warna teks. Objek Time yang digunakan untuk, Anda dapat menebaknya, keeping tract waktu device saat ini. mUpdateRateMs digunakan untuk mengontrol timer bahwa kita perlu untuk menerapkan untuk memperbarui kami watch face setiap detik (maka 1000 milidetik nilai untuk mUpdateRateMs), karena WatchFaceService standar hanya terus melacak yang waktu dalam satu menit secara bertahap. mXOffset dan mYOffset didefinisikan setelah engine tahu bentuk fisik watch sehingga facth watch kita dapat ditarik tanpa menjadi terlalu dekat ke atas atau ke kiri layar, atau dipotong dengan sudut bulat. Nilai-nilai boolean tiga yang digunakan untuk melacak berbagai perangkat dan aplikasi state.

Objek berikutnya yang Anda akan perlu untuk menentukan adalah penerima siaran yang menangani situasi dimana pengguna dapat bepergian dan mengubah zona waktu. Penerima ini hanya membersihkan out zona waktu disimpan dan me-reset waktu tampilan.

1
final BroadcastReceiver mTimeZoneBroadcastReceiver = new BroadcastReceiver() {
2
    @Override
3
    public void onReceive(Context context, Intent intent) {
4
        mDisplayTime.clear( intent.getStringExtra( "time-zone" ) );
5
        mDisplayTime.setToNow();
6
    }
7
};

Setelah Penerima Anda didefinisikan, tujuan akhir Anda akan perlu untuk membuat di bagian atas engine Anda adalah sebuah Handler untuk mengurus memperbarui watch face setiap detik. Hal ini diperlukan karena keterbatasan WatchFaceService yang dibahas di atas. Jika Anda watch face hanya perlu diperbarui setiap menit, maka Anda dapat dengan aman mengabaikan bagian ini.

1
private final Handler mTimeHandler = new Handler() {
2
    @Override
3
    public void handleMessage(Message msg) {
4
        switch( msg.what ) {
5
            case MSG_UPDATE_TIME_ID: {
6
                invalidate();
7
                if( isVisible() && !isInAmbientMode() ) {
8
                    long currentTimeMillis = System.currentTimeMillis();
9
                    long delay = mUpdateRateMs - ( currentTimeMillis % mUpdateRateMs );
10
                    mTimeHandler.sendEmptyMessageDelayed( MSG_UPDATE_TIME_ID, delay );
11
                }
12
                break;
13
            }
14
        }
15
    }
16
};

Pelaksanaan Handler cukup sederhana. Pertama-tama memeriksa pesan ID. Jika cocok MSG_UPDATE_TIME_ID, terus invalidate view saat ini untuk redrawing. Setelah view telah di invalidated, Handler memeriksa untuk melihat jika layar terlihat dan tidak dalam modus ambient. Jika terlihat, hal mengirimkan permintaan berulang sedetik kemudian. Alasan kami hanya mengulangi tindakan di Handler ketika watch face terlihat dan tidak dalam modus ambient adalah bahwa hal itu dapat sedikit baterai intensif untuk terus update setiap detik. Jika pengguna tidak melihat layar, kita hanya kembali pada implementasi WatchFaceService yang update setiap menit.

Langkah 2: Initializing Engine

Sekarang bahwa variabel dan objek dinyatakan, saatnya untuk memulai initializing watch face. Engine ini memiliki onCreate metode yang harus digunakan untuk membuat objek dan tugas-tugas lain yang dapat mengambil sejumlah besar waktu dan baterai. Anda juga akan ingin untuk mengatur beberapa falg untuk WatchFaceStyle di sini untuk mengontrol bagaimana sistem berinteraksi dengan pengguna ketika watch face Anda aktif.

1
@Override
2
public void onCreate(SurfaceHolder holder) {
3
    super.onCreate(holder);
4
5
    setWatchFaceStyle( new WatchFaceStyle.Builder( CustomWatchFaceService.this )
6
                    .setBackgroundVisibility( WatchFaceStyle.BACKGROUND_VISIBILITY_INTERRUPTIVE )
7
                    .setCardPeekMode( WatchFaceStyle.PEEK_MODE_VARIABLE )
8
                    .setShowSystemUiTime( false )
9
                    .build()
10
    );
11
12
    mDisplayTime = new Time();
13
14
    initBackground();
15
    initDisplayText();
16
}

Untuk contoh aplikasi, Anda akan menggunakan setWatchFaceStyle untuk mengatur background kartu notification singkat menunjukkan jika jenis kartu ditetapkan sebagai interruptive. Anda juga akan mengatur modus mengintip sehingga notification card hanya mengambil ruang sebanyak yang diperlukan.

Akhirnya, Anda akan ingin memberitahu sistem untuk menunjukkan waktu standar karena Anda akan menampilkan itu sendiri. Sementara ini hanya beberapa pilihan yang tersedia, Anda dapat menemukan lebih banyak informasi dalam dokumentasi resmi untuk WatchFaceStyle.Builder objek.

Setelah WatchFaceStyle Anda telah ditetapkan, Anda dapat menginisialisasi mDisplayTime sebagai objek Time baru.

initBackground dan initDisplayText mengalokasikan cat dua objek yang Anda tetapkan di bagian atas Paint. Latar belakang dan teks kemudian memiliki warna mereka mengatur dan teks telah menetapkan ukuran huruf dan font, sementara juga berputar pada anti-aliasing.

1
private void initBackground() {
2
    mBackgroundColorPaint = new Paint();
3
    mBackgroundColorPaint.setColor( mBackgroundColor );
4
}
5
6
private void initDisplayText() {
7
    mTextColorPaint = new Paint();
8
    mTextColorPaint.setColor( mTextColor );
9
    mTextColorPaint.setTypeface( WATCH_TEXT_TYPEFACE );
10
    mTextColorPaint.setAntiAlias( true );
11
    mTextColorPaint.setTextSize( getResources().getDimension( R.dimen.text_size ) );
12
}

Langkah 3: Menangani perangkat state

Selanjutnya, Anda harus menerapkan berbagai metode dari kelas Engine yang dipicu oleh perubahan status perangkat. Kita akan mulai dengan pergi ke onVisibilityChanged metode, yang disebut saat pengguna menyembunyikan atau menunjukkan watch face.

1
@Override
2
public void onVisibilityChanged( boolean visible ) {
3
    super.onVisibilityChanged(visible);
4
5
    if( visible ) {
6
        if( !mHasTimeZoneReceiverBeenRegistered ) {
7
8
            IntentFilter filter = new IntentFilter( Intent.ACTION_TIMEZONE_CHANGED );
9
            CustomWatchFaceService.this.registerReceiver( mTimeZoneBroadcastReceiver, filter );
10
11
            mHasTimeZoneReceiverBeenRegistered = true;
12
        }
13
14
        mDisplayTime.clear( TimeZone.getDefault().getID() );
15
        mDisplayTime.setToNow();
16
    } else {
17
        if( mHasTimeZoneReceiverBeenRegistered ) {
18
            CustomWatchFaceService.this.unregisterReceiver( mTimeZoneBroadcastReceiver );
19
            mHasTimeZoneReceiverBeenRegistered = false;
20
        }
21
    }
22
23
    updateTimer();
24
}

Ketika metode ini disebut, itu akan memeriksa untuk melihat apakah watch face terlihat atau tidak. Jika menonton wajah terlihat, tampaknya untuk melihat apakah BroadcastReceiver yang Anda tetapkan di bagian atas Engine terdaftar. Jika tidak, metode menciptakan IntentFilter untuk tindakan ACTION_TIMEZONE_CHANGED dan register BroadcastReceiver mendengarkan untuk itu.

Jika watch face tidak terlihat, metode ini akan memeriksa untuk melihat apakah BroadcastReceiver bisa di unregister. Setelah BroadcastReceiver telah ditangani, updateTimer dipanggil untuk memicu invalid watch face dan redraw watch face. updateTimer memberhikan semua Handler yang tertunda dan memeriksa untuk melihat apakah lain harus dikirim.

1
private void updateTimer() {
2
    mTimeHandler.removeMessages( MSG_UPDATE_TIME_ID );
3
    if( isVisible() && !isInAmbientMode() ) {
4
        mTimeHandler.sendEmptyMessage( MSG_UPDATE_TIME_ID );
5
    }
6
}

Langkah 4: Bekerja sama dengan Wearable Hardware

Ketika layanan Anda dikaitkan dengan memakai Android, onApplyWindowInsets dipanggil. Ini digunakan untuk menentukan apakah perangkat watch face Anda berjalan pada bulat atau persegi. Hal ini memungkinkan Anda mengubah watch face Anda untuk menyesuaikan dengan hardware.

Ketika metode ini disebut dalam aplikasi sampel, metode ini hanya memeriksa bentuk perangkat dan perubahan x offset digunakan untuk drawing watch face untuk memastikan watch face Anda terlihat pada perangkat.

1
@Override
2
public void onApplyWindowInsets(WindowInsets insets) {
3
    super.onApplyWindowInsets(insets);
4
5
    mYOffset = getResources().getDimension( R.dimen.y_offset );
6
7
    if( insets.isRound() ) {
8
        mXOffset = getResources().getDimension( R.dimen.x_offset_round );
9
    } else {
10
        mXOffset = getResources().getDimension( R.dimen.x_offset_square );
11
    }
12
}

Metode berikutnya yang akan Anda perlukan untuk menimpa adalah onPropertiesChanged. Metode ini disebut ketika properti hardware untuk memakai perangkat yang ditentukan, misalnya, jika perangkat mendukung burn-in perlindungan atau modus ambient bit rendah.

Dalam metode ini, Anda memeriksa jika atribut tersebut berlaku untuk perangkat yang menjalankan watch face Anda dan menyimpannya dalam variabel anggota yang didefinisikan di atas Engine Anda.

1
@Override
2
public void onPropertiesChanged( Bundle properties ) {
3
    super.onPropertiesChanged( properties );
4
5
    if( properties.getBoolean( PROPERTY_BURN_IN_PROTECTION, false ) ) {
6
        mIsLowBitAmbient = properties.getBoolean( PROPERTY_LOW_BIT_AMBIENT, false );
7
    }
8
}

Langkah 5: Conserving baterai dalam mode Ambient dan Muted

Setelah Anda menangani initial state perangkat, Anda akan ingin untuk implementasi onAmbientModeChanged dan onInterruptionFilterChanged. Seperti namanya, onAmbientModeChanged dipanggil ketika perangkat bergerak dalam atau keluar dari modus ambient.

Jika perangkat ini dalam ambient mode, Anda akan ingin mengubah warna Anda watch face menjadi hitam dan putih untuk menjadi sadar pengguna baterai. Ketika perangkat kembali dari ambient mode, Anda dapat menyetel warna wajah watch face. Anda juga akan ingin untuk berhati-hati dari anti-aliasing untuk perangkat yang meminta dukungan ambient bit rendah. Setelah semua variabel flag yang ditetapkan, Anda dapat menyebabkan watch face invalide redraw dan kemudian memeriksa jika satu timer kedua harus mulai.

1
@Override
2
public void onAmbientModeChanged(boolean inAmbientMode) {
3
    super.onAmbientModeChanged(inAmbientMode);
4
5
    if( inAmbientMode ) {
6
        mTextColorPaint.setColor( Color.parseColor( "white" ) );
7
    } else {
8
        mTextColorPaint.setColor( Color.parseColor( "red" ) );
9
    }
10
11
    if( mIsLowBitAmbient ) {
12
        mTextColorPaint.setAntiAlias( !inAmbientMode );
13
    }
14
15
    invalidate();
16
    updateTimer();
17
}


onInterruptionFilterChanged dipanggil ketika pengguna secara manual perubahan pengaturan gangguan pada dpt dipakai mereka. Ketika ini terjadi, Anda akan perlu untuk memeriksa jika muted dan kemudian mengubah antarmuka pengguna yang sesuai. Dalam situasi ini, Anda akan mengubah transparansi watch face, menetapkan Handler Anda hanya update setiap menit jika dibisukan, dan kemudian redraw watch face Anda.

1
@Override
2
public void onInterruptionFilterChanged(int interruptionFilter) {
3
    super.onInterruptionFilterChanged(interruptionFilter);
4
5
    boolean isDeviceMuted = ( interruptionFilter == android.support.wearable.watchface.WatchFaceService.INTERRUPTION_FILTER_NONE );
6
    if( isDeviceMuted ) {
7
        mUpdateRateMs = TimeUnit.MINUTES.toMillis( 1 );
8
    } else {
9
        mUpdateRateMs = DEFAULT_UPDATE_RATE_MS;
10
    }
11
12
    if( mIsInMuteMode != isDeviceMuted ) {
13
        mIsInMuteMode = isDeviceMuted;
14
        int alpha = ( isDeviceMuted ) ? 100 : 255;
15
        mTextColorPaint.setAlpha( alpha );
16
        invalidate();
17
        updateTimer();
18
    }
19
}

Bila perangkat Anda dalam modus ambient, Handler timer akan dinonaktifkan. Watch face masih dapat memperbarui saat setiap menit melalui menggunakan metode built-in onTimeTick untuk invalide Canvas.

1
@Override
2
public void onTimeTick() {
3
    super.onTimeTick();
4
5
    invalidate();
6
}

Langkah 6: Drawing Watch Face

Setelah semua kontinjensi Anda dilindungi, saatnya untuk akhirnya menarik keluar Watch face Anda. CanvasWatchFaceService menggunakan objek Canvas standar, sehingga Anda akan perlu untuk menambahkan onDraw ke Engine Anda dan secara manual menarik keluar watch face anda.

Dalam tutorial ini kita hanya akan menggambar representasi teks waktu, meskipun Anda bisa mengubah Anda onDraw untuk dengan mudah mendukung analog watch face. Dalam metode ini, Anda akan ingin untuk memverifikasi bahwa Anda menampilkan waktu yang tepat dengan memperbarui objek Time Anda dan kemudian Anda dapat mulai menerapkan watch face Anda.

1
@Override
2
public void onDraw(Canvas canvas, Rect bounds) {
3
    super.onDraw(canvas, bounds);
4
5
    mDisplayTime.setToNow();
6
7
    drawBackground( canvas, bounds );
8
    drawTimeText( canvas );
9
}

drawBackground berlaku warna solid untuk latar belakang wear device.

1
private void drawBackground( Canvas canvas, Rect bounds ) {
2
    canvas.drawRect( 0, 0, bounds.width(), bounds.height(), mBackgroundColorPaint );
3
}

drawTimeText, namun, membuat teks waktu yang akan ditampilkan dengan bantuan beberapa metode helper dan kemudian berlaku untuk canvas di x dan y offset poin yang Anda tetapkan dalam onApplyWindowInsets.

1
private void drawTimeText( Canvas canvas ) {
2
    String timeText = getHourString() + ":" + String.format( "%02d", mDisplayTime.minute );
3
    if( isInAmbientMode() || mIsInMuteMode ) {
4
        timeText += ( mDisplayTime.hour < 12 ) ? "AM" : "PM";
5
    } else {
6
        timeText += String.format( ":%02d", mDisplayTime.second);
7
    }
8
    canvas.drawText( timeText, mXOffset, mYOffset, mTextColorPaint );
9
}
10
11
private String getHourString() {
12
    if( mDisplayTime.hour % 12 == 0 )
13
        return "12";
14
    else if( mDisplayTime.hour <= 12 )
15
        return String.valueOf( mDisplayTime.hour );
16
    else
17
        return String.valueOf( mDisplayTime.hour - 12 );
18
}

Kesimpulan

Setelah Anda telah menerapkan metode untuk drawing watch face Anda, Anda harus siap dengan pengetahuan dasar yang diperlukan untuk pergi keluar dan membuat watch face Anda sendiri. Yang menyenangkan tentang Android watch face adalah bahwa ini adalah hanya menggaruk permukaan dari apa yang mungkin.

Anda dapat menambahkan pendamping konfigurasi kegiatan watch atau telepon, menggantikan Canvas berbasis watch face dengan implementasi OpenGL, atau mendapatkan kelas Anda sendiri dari WatchFaceService untuk memenuhi kebutuhan Anda.

Tambahkan ke bahwa Anda dapat mengakses api atau informasi lainnya dari pengguna telepon dan kemungkinan tampaknya tak ada habisnya. Mendapatkan kreatif dengan watch face Anda dan menikmati.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.