+1

Tạo ứng dụng widget đơn giản

Lời nói đầu :

Các bạn dùng android chắc hẳn không xa lạ gì với widget . Vậy ta đặt ra câu hỏi widget là gì ?

Khái niệm widget có nghĩa là một thiết bị nhỏ, đính kèm theo một dụng cụ nào đó. Trên Android, bạn có thể hiểu widget chính là những ứng dụng nhỏ gắn trên màn hình chính của Launcher. Những ứng dụng nhỏ này có khả năng liên kết và hiển thị thông tin từ các ứng dụng lớn khác hoặc thực hiện những chức năng của riêng nó, không phụ thuộc vào ứng dụng nào. Widget chỉ mới xuất hiện trên thiết bị di động trong những năm gần đây. Nhờ vào màn hình cảm ứng, việc thêm/xóa, di chuyển, sắp xếp và sử dụng widget đã trở nên dễ dàng hơn.

Trong bài viết dưới đây mình giúp các bạn tạo 1 widget cực kì đơn giản để tắt bật đèn flash máy ảnh .(một ứng dụng nhỏ nhưng thực sự rất tiện lợi)

Viết widget đơn giản

Để thực hiện 1 app widget chúng ta cần chú ý các điểm sau :

  • 1 class extends AppWidgetProvider :
  • 1 class extends BroadcastReceiver : class xử lí các xự kiện từ hệ thống ( tắt bật Flash )
  • File AndroidManifest.xml.
  • Flie khai báo layout cho widget trong res/xml Sau đây mình sẽ hướng dẫn các bạn thao tác với từng file :

Tạo file giao diện widget :

  • B1 : bạn tao 1 file giao diện wiget như bình thường. Ở đây mình dùng 1 button có 2 trạng thái on/off để thể hiện . Mình tạo file main.xml trong folder res/layout như các app bình thường.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Turn on" />
</LinearLayout>
  • B2 : sau khi tạo file layout xong, trong thư mục /res mình tạo thêm 1 thư mục xml trong đó tạo 1 file flashwidget.xml (res/xml/flashwidget.xml ) với nội dung như sau :
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="1dp"
    android:minHeight="1dp"
    android:updatePeriodMillis="86400000"
    android:initialLayout="@layout/main"
    android:resizeMode="horizontal|vertical"
    android:widgetCategory="home_screen|keyguard" />

Ở đây các bạn chú ý có trường android:initialLayout="@layout/main" .

Sửa file AndroidManifest.xml

Mình gửi các bạn file manifest mình đã làm :

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.flashlightwidget"
    android:versionCode="1"
    android:versionName="0.1"> <!--Update this in gradle too!-->

    <uses-sdk android:minSdkVersion="5" />
    <uses-permission android:name="android.permission.CAMERA" />

    <application android:allowBackup="true"
        android:label="@string/app_name"
        android:icon="@drawable/ic_launcher"
        android:theme="@style/AppTheme">
        
        <receiver android:name="Main">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <meta-data android:name="android.appwidget.provider"
                android:resource="@xml/flashwidget" />
        </receiver>

        <receiver android:name="Receiver">
            <intent-filter>
                <action android:name="com.test.flashwidget.FLASHLIGHT"></action>
            </intent-filter>
        </receiver>

    </application>

</manifest>

Ở trên ban thấy app widget không hề cần filter :

<action android:name="android.intent.action.MAIN" />
 <category android:name="android.intent.category.LAUNCHER" />

Vì bản chất 1 app widget không cần icon thể hiện để start app trong launcher 😃.

Khởi tạo class extends AppWidgetProvider :

Đây là code demo :

package com.test.flashlightwidget;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;

public class Main extends AppWidgetProvider {

    static RemoteViews createWidgetView(Context context) {
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.main);

        if(Receiver.isLightOn) {
            views.setTextViewText(R.id.button, "Turn off");
        } else {
            views.setTextViewText(R.id.button, "Turn on");
        }

        Intent receiver = new Intent(context, Receiver.class);
        receiver.setAction("com.test.flashlightwidget.FLASHLIGHT");
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, receiver, 0);
        views.setOnClickPendingIntent(R.id.button, pendingIntent);

        return views;
    }


    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        RemoteViews views = createWidgetView(context);
        appWidgetManager.updateAppWidget(appWidgetIds, views);
    }

}

Các bạn có thể thấy ở đây xử lí update layout cho widget khi có sự kiện update ( bật/tắt flash ). Chú ý ở đây không sử dụng các findview như bình thường mà nó xử lí qua remote view ( có 1 số custom view sẽ không sử dụng được. )

Khởi tạo class extends BroadcastReceiver :

Đây là code demo :

package com.test.flashlightwidget;

import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;

public class Receiver extends BroadcastReceiver {
    static boolean isLightOn = false;
    private static Camera camera;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (isLightOn) {
            if (camera != null) {
                camera.stopPreview();
                camera.release();
                camera = null;
                isLightOn = false;
            }
        } else {
            camera = Camera.open(); //Open the default rear facing camera

            if(camera != null) {
                Camera.Parameters param = camera.getParameters();
                param.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                try {
                    camera.setParameters(param);
                    camera.startPreview();
                    isLightOn = true;
                } catch (Exception e) {}
            }
        }

        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
        appWidgetManager.updateAppWidget(new ComponentName(context, Main.class), Main.createWidgetView(context));
    }
}

Như vậy ta đã xong giờ chỉ việc run và xem thành quả. Các bạn nhận thấy 1 vài đặc điểm sau :

  • Build xong ở phần build console của IDE chỉ hiển thị bước /Done mà không hế start activity : 😄
  • Mở điện thoại không hê thấy app trong launcher. Do là app widget nên các bạn cần phài vào widget để lôi app ra ngoài để sử dụng nhé 😃.

Kết luận :

Trên đây mình chia sẻ với các bạn 1 widget đơn giản, từ đó các bạn có thể tham khảo để tụ tạo ra 1 utility widget của chính mình thực hiện 1 số quick action ngay trên màn hình điện thoại mà chỉ bạn mới có 😄. Thanks all.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí