Quick Settings?
- 안드로이드 상단을 스와이프하면 보이는 스위치 버튼들
- 기존 안드로이드 버전에서는 커스텀 버튼을 만들 수 없었다.(제조사에서 만든 버튼 제외)
- 7.0부터는 일반 앱에서 제공하는 커스텀 버튼을 추가할 수 있다.
- 이 버튼은 앱을 시작하기 위한 용도가 아니고, 앱을 켜지 않고도
빠르게 on/off해야하는 기능
을 추가하는 용도로 사용되어야 한다.
- Quick Settings를 구현하기 위해서는 7.0(API 24)에서 추가된
Tile
API를 이용해야 한다.
Quick Settings 구현
TileService 추가
Service
클래스의 하위 클래스로 Quick Setting을 구현하기 위한 컴포넌트 클래스
- 매니페스트 파일에
TileService
를 등록해야 한다.
android:label
속성값은 타일 버튼의 설명이 들어간다. 코드로 변경가능하다.
android:icon
속성값은 타일 버튼의 아이콘이 들어간다. 코드로 변경가능하다. (아이콘은 안드로이드 정책에 따라 반드시 흰색이어야 한다. off, 비활성 표시를 위해 알파를 이용한다)
android.permission.BIND_QUICK_SETTINGS_TILE
퍼미션을 꼭 추가해주어야 한다.
- 시스템이
TileService
를 인식하려면 TileService.ACTION_QS_TILE
액션을 인텐트필터로 등록해야 한다.
<service android:name=".TestTileService"
android:label="Test Label"
android:icon="@drawable/ic_toastdrive"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
</service>
- 시스템은 모든 앱의 매니페스트를 읽어서,
ACTION_QS_TILE
액션을 추가한 TileService
를 타일 리스트에 추가한다.(아직은 사용자의 입력을 받지 못한다.)
- 타일 리스트에 있는 타일을 QuickSetting 영역으로 드래그하면, 이때부터 타일버튼으로 사용자의 입력을 받을 수 있다.
Tile 버튼으로 사용자의 입력 받기
- TileService는 버튼의 상태에 따라 콜백을 받는 다음 메서드들이 정의되어 있다.
onTileAdded()
: 타일이 QuickSetting 영역에 추가되었을 때 호출
onTileRemoved()
: 타일이 QuickSetting 영역에서 제거되었을 때 호출
onStartListening()
: 타일이 리스닝 상태로 들어갔을 때(QuickSetting 영역이 보일때) 호출
onStopListening()
: 타일이 리스닝 상태에서 나왔을 때(QuickSetting 영역이 가려질때) 호출
onClick()
: QuickSetting 영역에서 타일이 눌렸을 때 호출
- onTileAdded/Removed, onStart/StopListening 메서드는 QuickSetting 영역과 타일리스트의 경계에서 여러번 호출될 수 있으니 유의하도록 한다.
- 일반적으로
onClick()
메서드를 이용해 사용자와 인터렉션 한다.
public class TestTileService extends TileService {
boolean isListening = false;
...
@Override
public void onClick() {
Tile tile = getQsTile();
int tileState = tile.getState();
if (isListening && tileState != Tile.STATE_UNAVAILABLE) {
tile.setState(tileState == Tile.STATE_ACTIVE? Tile.STATE_INACTIVE : Tile.STATE_ACTIVE);
tile.updateTile();
}
}
...
}
- 앱의 생명주기와는 상관없이, Tile 객체는 상태를 보존한다. 그러나, 시스템이 재부팅되면 상태보존이 되지 않는다.(실장비에서 확인이 필요)
Tile 버튼을 활용하기 위한 TileService의 기능들
다이얼로그 보여주기
- TitleService 클래스의
showDialog()
메서드를 호출한다. 인자로는 보여줄 다이얼로그 객체를 넘겨준다.
- 이 메서드를 호출하면, Quick Setting 영역은 닫히고, 다이얼로그가 호출된다.
- 다이얼로그는 반드시
Theme.AppCompat
테마 / 하위테마를 사용해야 한다.
public class TestTileService extends TileService {
boolean isListening = false;
...
@Override
public void onClick() {
Tile tile = getQsTile();
int tileState = tile.getState();
if (isListening && tileState != Tile.STATE_UNAVAILABLE) {
tile.setState(tileState == Tile.STATE_ACTIVE? Tile.STATE_INACTIVE : Tile.STATE_ACTIVE);
tile.updateTile();
if (tileState == Tile.STATE_ACTIVE) {
AlertDialog dialog = new AlertDialog.Builder(this, R.style.MaterialBaseTheme_AlertDialog)
.setTitle("Test Title")
.setMessage("Test Message")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(AppApplication.sContext, "OK", Toast.LENGTH_SHORT).show();
}
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(AppApplication.sContext, "Cancel", Toast.LENGTH_SHORT).show();
}
}).create();
showDialog(dialog);
}
}
}
...
}
엑티비티 시작하기
- TileService 클래스의
startActivityAndCollapse()
메서드를 호출한다. 인자로는 엑티비티를 호출하기 위한 인텐트를 넘겨준다.
- 이 메서드를 호출하면 Quick Setting 영역은 닫히고, 엑티비티가 실행된다.
- 만약, 기존 앱이 실행중이라면 인자로 넘겨주는 Intent의 엑티비티 스택관련 플래그에 영향을 받는다.
public class TestTileService extends TileService {
boolean isListening = false;
...
@Override
public void onClick() {
Tile tile = getQsTile();
int tileState = tile.getState();
if (isListening && tileState != Tile.STATE_UNAVAILABLE) {
tile.setState(tileState == Tile.STATE_ACTIVE? Tile.STATE_INACTIVE : Tile.STATE_ACTIVE);
tile.updateTile();
if (tileState == Tile.STATE_ACTIVE) {
Intent intent = new Intent(AppApplication.sContext, WebViewActivity.class);
intent.putExtra(WebViewActivity.ARG_URL, "http://developer.android.com");
startActivityAndCollapse(intent);
}
}
}
...
}
잠금화면에서의 동작
- 잠금화면 상태에서는 잠금화면에 가려서 위의 다이얼로그 / 엑티비티 호출은 보이지 않는다.(잠금화면에 가려졌을 뿐, 정상적으로 동작한다.)
- 현재 상태가 잠금화면 상태인지를 확인하려면 다음 메서드를 이용한다.
isLocked()
: 현재 상태가 잠금화면일 경우 true 반환
isSecure()
: 현재 상태가 보안중일 경우 true 반환(true 인 경우에는 당연히 잠금화면 상태이므로 isLocked()
는 true를 반환)
- TileService 의
unlockAndRun()
메서드를 이용하면 잠금화면을 해제하고 동작을 수행한다. 인자로는 unlock을 수행한 후에 수행될 내용을 구현한 Runnable 객체이다.
unlockAndRun()
메서드가 Quick Setting 영역을 닫지는 않는다. 그래서 Quick Setting 영역이 그대로 보이며, 그 뒤에서 동작이 수행된다.
- 패턴이 걸려있는 경우,
unlockAndRun()
메서드가 호출되면 패턴해제화면이 노출된다. 패턴을 풀어야 Runnable 객체를 수행한다.(지문은 실 장비에서 테스트가 필요하지만, 동일한 프로세스일 것으로 추정)
- 패턴해제화면에서 해제를 취소한 경우 Runnable 객체의 동작이 수행되지 않는다.
public class TestTileService extends TileService {
boolean isListening = false;
...
@Override
public void onClick() {
Tile tile = getQsTile();
int tileState = tile.getState();
if (isListening && tileState != Tile.STATE_UNAVAILABLE) {
tile.setState(tileState == Tile.STATE_ACTIVE? Tile.STATE_INACTIVE : Tile.STATE_ACTIVE);
tile.updateTile();
if (tileState == Tile.STATE_ACTIVE) {
unlockAndRun(new Runnable() {
@Override
public void run() {
Toast.makeText(AppApplication.sContext, "unlock and run Test", Toast.LENGTH_SHORT).show();
}
});
}
}
}
...
}
오....
답글삭제