일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- convert base64
- Android
- 기존 앱
- Tuist
- Swift Package Manager
- development language
- DevelopmentRegion
- Side Menu
- 스크롤 탭
- UIPresentationController
- ViewBuilder
- url 추적
- DataBinding
- GeometryReader
- SwiftUI
- oberve url
- swift #swift keychain #keychain 사용법
- detect url
- base64 변환
- List
- scrolling tab
- UIViewControllerTransitioningDelegate
- url 관찰
- 개발자 면접
- 상단 탭바
- pod install
- ios
- notifychanged
- swift
- transformation.map
- Today
- Total
버그 잡이
안드로이드(android) 위젯(widget) 만들기 본문
습관앱을 만들면서 진행 현황을 핸드폰 홈 스크린에서 확인할 수 있는 위젯을 만들었습니다.
주요 기능
1. 리스트뷰를 위젯에 표현
2. 위젯 클릭시 앱으로 이동
3. 데이터 최신화
구현 방법
1. 리스트뷰를 위젯에 표현
- https://onepinetwopine.tistory.com/402
기본 홈 위젯 출력과 ListView 출력은 위의 블로그를 따라했습니다.(감사합니다!)
간단하게 저만의 정리를 덧붙이자면
1) 단순 버튼 위젯 구현
- 일단 위젯은 액티비티 위에서 작동하는 것이 아니라
- AppWidgetProvider를 상속받아서 구현한다.
- Appwidgetprovider를 상속받으면 위젯 상태변화에 따라 호출되는 콜백함수를 작성할 수 있습니다.
2) ListView 위젯 구현
- 단순한 버튼 위젯이라면 AppWidgetProvider만 있어도 되지만
- ListView를 출력하기 위해서는 Adapter가 필요합니다.
- 그 adapter의 역할을 RemoteViewFactory 클래스가 해줍니다.
- RemoteViewFactory를 위해서 RemoteViewService도 필요
2. 위젯 클릭시 앱으로 이동
- 여기서는 listView 각 항목별 다른 이벤트가 아닌 위젯 전체에 대한 클릭 이벤트를 설정했습니다.
- 위젯을 클릭하면 해당앱의 MainActivity(저의 경우 HabitListActivity.class)로 이동하는 것입니다.
*안드로이드 공식문서를 참고하여 작성하였습니다.
(핵심 내용을 요약하자면)
1) WidgetListView.class의 onUpdate에서 setPendingIntentTemplate 설정
- setPendingIntentTemplate에 pendingIntent를 등록
- listView가 클릭되면 pendingIntent를 수행하도록 함.
2) WidgetListViewclass의 onReceive에서 클릭시 수행될 작업 설정
- 클릭시 구체적인 동작은 여기에 작성
3) MyRemoteViewsFactory의 RemoteViews getViewAt에서 setOnClickFillInIntent 설정
- 1번의 setPendingIntentTemplate와 함께 쓰임. extraData를 추가적으로 전달할 수 있음.
- setPendingIntentTemplate와 setOnClickFillInIntent는 꼭 같이 써야함(왜 그런지는 잘 모르겠습니다 ㅜ)
*WidgetListView.class
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
for (int appWidgetId : appWidgetIds) {
// RemoteViewsService 실행 등록시키는 함수 -> Factory작동을 위해서 -> Factory는 위젯에 담기는 뷰들을 생성해줌.(listview가 아닌 간단한 텍스트뷰라면 필요없음.)
Intent serviceIntent = new Intent(context, MyRemoteViewsService.class);
serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)));
RemoteViews widget = new RemoteViews(context.getPackageName(), R.layout.widget_listview);
widget.setRemoteAdapter(R.id.widget_listview, serviceIntent);
//Listview 클릭 이벤트를 위한 코드. -> 원리는 pendingIntent 부여 -> 하나씩 부여하기에는 부담이 되어서 각 항목의 클릭이 아닌 위젯 자체에 대한 클릭
Intent toastIntent = new Intent(context, WidgetListView.class);
toastIntent.setAction(WidgetListView.TOAST_ACTION);
toastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)));
PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, toastIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
widget.setPendingIntentTemplate(R.id.widget_listview, toastPendingIntent); //listView의 collection에 하나하나 pendingIntent를 부여하는 것은 메모리 부담이 많이 됨. 그래서 콜렉션에 하나의 펜딩인텐트만 부여한다.
//보내기
appWidgetManager.updateAppWidget(appWidgetIds, widget);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
@Override
public void onReceive(Context context, Intent intent) {
AppWidgetManager mgr = AppWidgetManager.getInstance(context);
if (intent.getAction().equals(TOAST_ACTION)) {
Intent i = new Intent(context, HabitListActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
super.onReceive(context, intent);
}
*MyRemoteViewsFactory
@Override
public RemoteViews getViewAt(int position) {
RemoteViews listviewWidget = new RemoteViews(context.getPackageName(), R.layout.item_collection);
Intent fillInIntent = new Intent();
fillInIntent.putExtra(WidgetListView.EXTRA_ITEM, position);
listviewWidget.setOnClickFillInIntent(R.id.listView_parent, fillInIntent); //pendingIntent와 같이 쓰이는 녀석. 클릭시 설정된 extraData를 추가적으로 전달할 수 있다.
return listviewWidget;
}
3. 데이터 실시간 최신화
- 이거는 간단합니다. MainActivity에서 데이터가 바뀔때 AppWidgetManager를 import해서 "notifyAppWidgetViewDataChanged" 를 해주면 됩니다.
*아래 코드는 WidgetListView.class가 아닌 Activity에 작성합니다.
*HabitListActivity.class
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
int appWidgetIds[] = appWidgetManager.getAppWidgetIds(
new ComponentName(this, WidgetListView.class));
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.widget_listview);
'안드로이드' 카테고리의 다른 글
android 기울기 센서로 공 움직이기(Accelometer sensor) #android sensor (0) | 2020.03.17 |
---|---|
picass vs glide vs fresco 안드로이드 이미지 라이브러리 비교 (0) | 2020.03.13 |
안드로이드 EditText 안에 스크롤바 넣기, 키보드 뜰때 밀림 현상 해결 (0) | 2019.11.03 |
안드로이드 getIntent() 두 개 이상 받기. (0) | 2019.10.27 |
RecyclerView 선택 삭제, action Mode, contextual action bar (0) | 2019.10.20 |