Программно установить системное время

Я понимаю, что этот вопрос появляется в другом месте на 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();
Другие вопросы по тегам