안드로이드 배터리 위젯 만들기
위젯 과 홈스크린은 직접적으로 접근이 제한되어 있습니다.
그래서 브로드캐스트를 이용하여 어떤 액션을 해달라고 요청하여 위젯을 나타내게 됩니다.
1. 프로젝트 생성
기존 안드로이드 프로젝트를 생성 합니다.
위젯 프로젝트는 액티비티가 필요없기 때문에 제거 하고 진행해 보겠습니다.
그러면 프로젝트 구성을 보면 src 와 res > layout 이 비어있는 것을 볼수있습니다.
위제 만들기의 시작은 브로드캐스트 등록부터가 되겠습니다.
Manifast 에 receiver 를 등록해 보겠습니다.
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
|
package="com.example.batterywidget"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<receiver
android:name="C28_Battery"
android:label="배터리 위젯" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.example.batterytest.C28_BatteryService" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/c28_batteryinfo" />
</receiver>
</application>
</manifest>
|
이와 같이 application 태그 안에 receiver 를 만들어 주면 되겠습니다.
label 속성의 위젯 메뉴의 제목이 됩니다.
갱신신호를 받기 위해서 인텐트 필터에 APPWIDGET_UPDATE 액션을
수신한다는 선언을 해야 합니다.
meta-data 속성은 컴포넌트의 추가적인 속성을 지정 합니다.
resource 는 위젯 속성을 설정하는 xml 이 되겠습니다.
이렇게 소스를 작성 하면 meta-data resource 부분에서 에러가 나타납니다.
resource 작성한 xml 이 없어서 나는 오류입니다 .
xml 을 작성해 보겠습니다 .
xml 생성시 resource Type 을 AppWidget Provider 로 변경하고 생성을 합니다.
1
2
3
4
5
6
7
8
|
<?xml version="1.0" encoding="utf-8"?>
android:initialLayout="@layout/battery"
android:minHeight="72dp"
android:minWidth="72dp"
android:updatePeriodMillis="0" >
</appwidget-provider>
|
생성후 소스를 작성합니다 .
initialLayout 은 홈스크린에 나타나는 위젯을 구성하는 xml 이 되겠습니다 .
minHeight , minWidth dp 는 (셀수 x 74) -2 dp 입니다.
한셀에 72 dp 로 잡아서 위젯을 구성하시면 되겠습니다.
updatePeriodMillis 는 위젯의 업데이트 주기 입니다 . 시간 단위는 1/1000 초가 되겠습니다.
이렇게 위젯을 설정을 완료하면 battery xml 을 구성해야 합니다.
이 xml 은 위젯을 구성하는 xml 이므로 기존 안드로이드에서 구성하는 xml 로 생성하여 디자인 하면 되겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<?xml version="1.0" encoding="utf-8"?>
android:id="@+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:src="@drawable/battery" />
<TextView
android:id="@+id/gauge"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="30sp"
android:textColor="#ffffff"
/>
</FrameLayout>
|
저는 배터리 위젯을 만들기 위해서 1x1 크기로 이미지와 텍스트를 이용하여 구성하였습니다.
매니페스트에서 작성한 이름을 맞춰 클래스를 만들어서 방송을 수신했을때 정보를 조사하고 화면을 갱신하는 코드를 만들어 보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public class Battery extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
Intent intent = new Intent(context, BatteryService.class);
context.startService(intent);
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
Intent intent = new Intent(context, BatteryService.class);
context.stopService(intent);
}
}
|
방송을 수신했을때 정보를 조사하고 화면을 갱신하는 코드를 만들어 보겠다고 했는데 서비스에 위임을 하고있는것을 볼수 있습니다.
배터리의 상태는 브로트 캐스트 방송을 수신해야 조사할수 있습니다.
위젯도 마찬가지로 브로트 캐스트를 통해서 홈스크린을 통제할수 있습니다.
여기서 배터리 브로트 캐스트와 위젯 브로트 캐스트가 있어 일종의 무한 후르에 빠져 버리는 문제가 있습니다. 그래서 서비스를 두고 서비스가 배터리 BR을 대신 등록하는 구조를 가지게 된것입니다.
서비스 작성을 구성하겠습니다.
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
|
public class BatteryService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(mBRBattery, filter);
return 1;
}
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mBRBattery);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
BroadcastReceiver mBRBattery = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
int scale, level, ratio;
scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
ratio = level * 100 / scale;
RemoteViews views = new RemoteViews
(context.getPackageName(), R.layout.battery);
views.setTextViewText(R.id.gauge, "" + ratio + "%");
AppWidgetManager wm = AppWidgetManager.getInstance(BatteryService.this);
ComponentName widget = new ComponentName(context, Battery.class);
wm.updateAppWidget(widget, views);
}
}
};
}
|
onStartCommand 에서 배터리 BR을 등록합니다.
등록후 BR 에서 배터리 잔량을 ratio 변수에 백분율로 조사 합니다.
조사한 값을 출력을 해야하는데 홈스크린 통제를 할수가 없어 RemoteViews 클래스 작성을 통하여 관리자에게 부탁을 해야합니다.
마지막으로 메니페스트에
1 |
<service android:name="BatteryService"></service> |
작성한 서비스를 추가시키면 되겠습니다
이렇게 완료를해서 배터리 위젯을 완성하였습니다 .