안드로이드 개발 질문/답변
(글 수 45,052)
05-17 05:47:33.512: WARN/SystemClock(5197): Unable to open alarm driver: Permission denied
일단 오류는 위 내용과 같습니다.
안드로이드 환경설정에 있는 날짜및 시간 소스를 그대로 옮겨와 필요한 부분만 남겨둔 상태입니다.
간단하게 말씀드리면 날짜, 시간, 표준시간대만 남겨둔 상태입니다.
표준시간대 변경은 별 문제 없이 완료가 되었는데 날짜와 시간 변경 부분에서 퍼미션 에러가 납니다.
소스에서 onDateSet(), 과 onTimeSet() 이 부분이 변경을 하도록 하는 메소드인 것같은데 이 두 메소드는
프레임웍 쪽에서 호출하고 있습니다.
android.permission.WRITE_SETTINGS 추가도 해봤지만 소용이 없더군요...
관련된 내용의 조언이라도 부탁드립니다~
<Settings에 위치한 Date& Time 관련 소스 부분 입니다.>
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings;
import android.app.Dialog;
import android.app.DatePickerDialog;
import android.app.TimePickerDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.os.SystemClock;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.text.format.DateFormat;
import android.widget.DatePicker;
import android.widget.TimePicker;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class DateTimeSettings
extends PreferenceActivity
implements OnSharedPreferenceChangeListener,
TimePickerDialog.OnTimeSetListener , DatePickerDialog.OnDateSetListener {
private static final String HOURS_12 = "12";
private static final String HOURS_24 = "24";
private Calendar mDummyDate;
private static final String KEY_DATE_FORMAT = "date_format";
private static final String KEY_AUTO_TIME = "auto_time";
private static final int DIALOG_DATEPICKER = 0;
private static final int DIALOG_TIMEPICKER = 1;
private CheckBoxPreference mAutoPref;
private Preference mTimePref;
private Preference mTime24Pref;
private Preference mTimeZone;
private Preference mDatePref;
private ListPreference mDateFormat;
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.date_time_prefs);
initUI();
}
private void initUI() {
boolean autoEnabled = getAutoState();
mDummyDate = Calendar.getInstance();
mDummyDate.set(mDummyDate.get(Calendar.YEAR), 11, 31, 13, 0, 0);
mAutoPref = (CheckBoxPreference) findPreference(KEY_AUTO_TIME);
mAutoPref.setChecked(autoEnabled);
mTimePref = findPreference("time");
mTime24Pref = findPreference("24 hour");
mTimeZone = findPreference("timezone");
mDatePref = findPreference("date");
mDateFormat = (ListPreference) findPreference(KEY_DATE_FORMAT);
String [] dateFormats = getResources().getStringArray(R.array.date_format_values);
String [] formattedDates = new String[dateFormats.length];
String currentFormat = getDateFormat();
// Initialize if DATE_FORMAT is not set in the system settings
// This can happen after a factory reset (or data wipe)
if (currentFormat == null) {
currentFormat = "";
}
for (int i = 0; i < formattedDates.length; i++) {
String formatted =
DateFormat.getDateFormatForSetting(this, dateFormats[i]).
format(mDummyDate.getTime());
if (dateFormats[i].length() == 0) {
formattedDates[i] = getResources().
getString(R.string.normal_date_format, formatted);
} else {
formattedDates[i] = formatted;
}
}
mDateFormat.setEntries(formattedDates);
mDateFormat.setEntryValues(R.array.date_format_values);
mDateFormat.setValue(currentFormat);
mTimePref.setEnabled(!autoEnabled);
mDatePref.setEnabled(!autoEnabled);
mTimeZone.setEnabled(!autoEnabled);
}
@Override
protected void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
((CheckBoxPreference)mTime24Pref).setChecked(is24Hour());
// Register for time ticks and other reasons for time change
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
registerReceiver(mIntentReceiver, filter, null, null);
updateTimeAndDateDisplay();
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mIntentReceiver);
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
private void updateTimeAndDateDisplay() {
java.text.DateFormat shortDateFormat = DateFormat.getDateFormat(this);
Date now = Calendar.getInstance().getTime();
Date dummyDate = mDummyDate.getTime();
mTimePref.setSummary(DateFormat.getTimeFormat(this).format(now));
mTimeZone.setSummary(getTimeZoneText());
mDatePref.setSummary(shortDateFormat.format(now));
mDateFormat.setSummary(shortDateFormat.format(dummyDate));
}
public void onDateSet(DatePicker view, int year, int month, int day) {
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, year);
c.set(Calendar.MONTH, month);
c.set(Calendar.DAY_OF_MONTH, day);
long when = c.getTimeInMillis();
if (when / 1000 < Integer.MAX_VALUE) {
SystemClock.setCurrentTimeMillis(when);
}
updateTimeAndDateDisplay();
}
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, hourOfDay);
c.set(Calendar.MINUTE, minute);
long when = c.getTimeInMillis();
if (when / 1000 < Integer.MAX_VALUE) {
SystemClock.setCurrentTimeMillis(when);
}
updateTimeAndDateDisplay();
// We don't need to call timeUpdated() here because the TIME_CHANGED
// broadcast is sent by the AlarmManager as a side effect of setting the
// SystemClock time.
}
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
if (key.equals(KEY_DATE_FORMAT)) {
String format = preferences.getString(key,
getResources().getString(R.string.default_date_format));
Settings.System.putString(getContentResolver(),
Settings.System.DATE_FORMAT, format);
updateTimeAndDateDisplay();
} else if (key.equals(KEY_AUTO_TIME)) {
boolean autoEnabled = preferences.getBoolean(key, true);
Settings.System.putInt(getContentResolver(),
Settings.System.AUTO_TIME,
autoEnabled ? 1 : 0);
mTimePref.setEnabled(!autoEnabled);
mDatePref.setEnabled(!autoEnabled);
mTimeZone.setEnabled(!autoEnabled);
}
}
@Override
public Dialog onCreateDialog(int id) {
Dialog d;
switch (id) {
case DIALOG_DATEPICKER: {
final Calendar calendar = Calendar.getInstance();
d = new DatePickerDialog(
this,
this,
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH));
d.setTitle(getResources().getString(R.string.date_time_changeDate_text));
break;
}
case DIALOG_TIMEPICKER: {
final Calendar calendar = Calendar.getInstance();
d = new TimePickerDialog(
this,
this,
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE),
DateFormat.is24HourFormat(this));
d.setTitle(getResources().getString(R.string.date_time_changeTime_text));
break;
}
default:
d = null;
break;
}
return d;
}
@Override
public void onPrepareDialog(int id, Dialog d) {
switch (id) {
case DIALOG_DATEPICKER: {
DatePickerDialog datePicker = (DatePickerDialog)d;
final Calendar calendar = Calendar.getInstance();
datePicker.updateDate(
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH));
break;
}
case DIALOG_TIMEPICKER: {
TimePickerDialog timePicker = (TimePickerDialog)d;
final Calendar calendar = Calendar.getInstance();
timePicker.updateTime(
calendar.get(Calendar.HOUR_OF_DAY),
calendar.get(Calendar.MINUTE));
break;
}
default:
break;
}
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
if (preference == mDatePref) {
showDialog(DIALOG_DATEPICKER);
} else if (preference == mTimePref) {
// The 24-hour mode may have changed, so recreate the dialog
removeDialog(DIALOG_TIMEPICKER);
showDialog(DIALOG_TIMEPICKER);
} else if (preference == mTime24Pref) {
set24Hour(((CheckBoxPreference)mTime24Pref).isChecked());
updateTimeAndDateDisplay();
timeUpdated();
} else if (preference == mTimeZone) {
Intent intent = new Intent();
intent.setClass(this, ZoneList.class);
startActivityForResult(intent, 0);
}
return false;
}
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
updateTimeAndDateDisplay();
}
private void timeUpdated() {
Intent timeChanged = new Intent(Intent.ACTION_TIME_CHANGED);
sendBroadcast(timeChanged);
}
/* Get & Set values from the system settings */
private boolean is24Hour() {
return DateFormat.is24HourFormat(this);
}
private void set24Hour(boolean is24Hour) {
Settings.System.putString(getContentResolver(),
Settings.System.TIME_12_24,
is24Hour? HOURS_24 : HOURS_12);
}
private String getDateFormat() {
return Settings.System.getString(getContentResolver(),
Settings.System.DATE_FORMAT);
}
private boolean getAutoState() {
try {
return Settings.System.getInt(getContentResolver(),
Settings.System.AUTO_TIME) > 0;
} catch (SettingNotFoundException snfe) {
return true;
}
}
private void setDateFormat(String format) {
if (format.length() == 0) {
format = null;
}
Settings.System.putString(getContentResolver(), Settings.System.DATE_FORMAT, format);
}
/* Helper routines to format timezone */
private String getTimeZoneText() {
TimeZone tz = java.util.Calendar.getInstance().getTimeZone();
boolean daylight = tz.inDaylightTime(new Date());
StringBuilder sb = new StringBuilder();
sb.append(formatOffset(tz.getRawOffset() +
(daylight ? tz.getDSTSavings() : 0))).
append(", ").
append(tz.getDisplayName(daylight, TimeZone.LONG));
return sb.toString();
}
private char[] formatOffset(int off) {
off = off / 1000 / 60;
char[] buf = new char[9];
buf[0] = 'G';
buf[1] = 'M';
buf[2] = 'T';
if (off < 0) {
buf[3] = '-';
off = -off;
} else {
buf[3] = '+';
}
int hours = off / 60;
int minutes = off % 60;
buf[4] = (char) ('0' + hours / 10);
buf[5] = (char) ('0' + hours % 10);
buf[6] = ':';
buf[7] = (char) ('0' + minutes / 10);
buf[8] = (char) ('0' + minutes % 10);
return buf;
}
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateTimeAndDateDisplay();
}
};
}
2010.05.17 16:28:25
아...저도 그 글을 보았지만..예전 버젼 이야기이길래.. 계속 찾아보는 중이거든요..
아직까지도 해답은 없지만...
According to this thread, user apps cannot set the time, regardless of the permissions we give it. Instead, the best approach is to make the user set the time manually. We will use:
startActivity(new Intent(android.provider.Settings.ACTION_DATE_SETTINGS));
Unfortunately, there is no way to link them directly to the time setting (which would save them one more click). By making use of ellapsedRealtime, we can ensure that the user sets the time correctly.
이런 글도 있길래..계속 다른 방법도 있을까하면서 찾고있습니다.
여기에서 보면, 할 수 없다고 나오네요.
**********************************************************************************
User apps cannot set the time. Only the system processes can. This is for
security, but also because it won't have much effect--the time is reset from
the radio via network time.
**********************************************************************************