Программно установить системное время
Я понимаю, что этот вопрос появляется в другом месте на SO, однако я попробовал все решения, которые я могу найти на сайте, и все еще испытываю трудности. Этим вопросам (и их ответам) также несколько лет, и вместо того, чтобы комментировать старые вопросы, я решил объединить здесь информацию для других и исследовать потенциально связанные изменения в Android между тогда и сейчас. Тем не менее, если вы считаете, что этот вопрос квалифицируется как дубликат, отметьте его как таковой.
Изменить: Как я уже говорил, другие ответы на SO не решили проблему. Я не понимаю, как комментарии к каждому потенциальному исправлению "Не работает для меня" способствуют тому, чтобы помочь себе и другим решить проблему, но если это так, пусть будет так. Для справки, 3 человека отметили вопросы как потенциальную копию этого вопроса, поэтому я добавил эти нерабочие ответы в список ниже.
У моего приложения есть очень специфические потребности, но для краткости давайте просто предположим, что мне нужно вручную установить системное время и дату на фиксированное значение. Ниже я подробно изложил некоторые заметки о моем прогрессе в попытке заставить это работать.
Приложение имеет минимальную версию SDK и нацелено на 24. Другие нашли, что им нужно увеличить версию до этого уровня.
Устройство было рутировано, и приложение устанавливается в /system/app, чтобы я мог изменить дату / время.
Некоторые отмечают, что приложениям просто невозможно установить время, однако, глядя на такие приложения, как ClockSync, это не так. Я знаю, что мое приложение не будет доступно в магазине Play.
Приложение должно установить дату / время автоматически без ввода пользователя, поэтому использование следующего кода для настройки пользователя не поможет;
startActivity(new Intent(android.provider.Settings.ACTION_DATE_SETTINGS));
Я добавил разрешение манифеста в манифест двумя способами: самостоятельно и затем вместе. Я также попытался добавить часть об удалении maxSDKversion.
<uses-permission android:name="android.permission.SET_TIME" tools:remove="android:maxSdkVersion" />
<permission android:name="android.permission.SET_TIME"
android:protectionLevel="signature|system"/>
Я читал, что для определенных разрешений требуется не только запись манифеста, но и чтобы пользователь мог их принять и разрешить. Однако SET_TIME не указан среди них. В любом случае я попытался сделать это, однако мой запрос на разрешение был автоматически отклонен без отображения окна подтверждения, возможно, потому, что он фактически не требовал разрешения в первую очередь.
Код, который я использую, чтобы попытаться установить время, выглядит следующим образом:
try {
Calendar c = Calendar.getInstance();
c.set(2017, 11, 21, 12, 32, 30);
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
am.setTime(c.getTimeInMillis());
} catch (Exception e) {
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
}
Ошибка, которую я получаю в тосте, когда это терпит неудачу:
java.lang.securityexception: setTime: neither user 10051 nor current process has android.permission.SET_TIME
Я попробовал два решения в вопросе, упомянутом в моем редактировании выше, оба из которых включают в себя запуск кода для установки даты как таковой:
Runtime.getRuntime().exec("su && date -s 20171122.153720");}
Оба из этих ответов ничего не делают - время не меняется, и никакие исключения не выбрасываются. Другой ответ требует доступа в интернет, что выходит за рамки моего вопроса.
Учитывая все вышесказанное, есть ли какой-то ключевой шаг, который я пропустил при выполнении этой работы, или что-то в коде, которое указывало бы на проблему?
1 ответ
Как оказалось, ответ лежал в ссылочном вопросе, найденном здесь. Однако команда для устройств Android 7 (и, возможно, 6, я не тестировал) отличается. У меня нет репутации, чтобы комментировать там, так что если кто-то хочет вставить / ссылаться на этот ответ на этот вопрос, продолжайте.
Код даты, который я использовал, был в формате MMddhhmmyy, а не yyyyMMdd.hhmmss; это работает для меня на Android 7. Я также удалил добавленные '-s'. Полный рабочий код, который я использовал для установки системного времени, приведен ниже. Снова следует отметить, что это требует рутирования устройства, поэтому оно полезно только в определенных сценариях, таких как мой.
try {
Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
String command = "date 1123104017\n";
// Log.e("command",command);
os.writeBytes(command);
os.flush();
os.writeBytes("exit\n");
os.flush();
process.waitFor();
} catch (InterruptedException e) {
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
} catch (IOException e) {
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
}
Для ясности, я ввел 23 ноября 2017 года в 10:40.
Если вам нужно установить второй, используйте этот формат: MMddhhmmyy.ss
если вы давно цените время, используйте это:
SimpleDateFormat dateFormat = new SimpleDateFormat("MMddhhmmyy.ss");
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timeValue);
Date date = calendar.getTime();
Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
String command = "date " + dateFormat.format(date) + "\n";
os.writeBytes(command);
os.flush();
os.writeBytes("exit\n");
os.flush();
process.waitFor();