Разработка ИИ запросов (AI Prompts) для генерации кода. https://oflameron.ru/Valery_Shmelev_5eng.pdf AI-powered Code Generation Разработаем запрос к ИИ для генерирования Android Studio Java кода генератора энтропии - гигантского псевдослучайного числа. В запросе длина числа ограничена размером файла - 10124000 байт. Можно поменять на большее значение. Генератор использует случайность младшего разряда данных от канада X акселерометра смартфона. Принципиально возможно значительно повысить эффективность такой генерации случайных чисел используя добавление значений от криптографических алгоритмов (например Блюма-Блюма-Шуба), из потока разговорного Интернет-радио, данных от микрофона, многочисленных преобразований "Текст В Голос" и т.д. Запрос проверялся в бесплатном чате chat.deepseek.com Приложение тестировалось на смартфоне Samsung S23 под Android 14. Файл с псевдослучайным числом записывается в папку Download смартфона и может быть скопирован на второй смартфон, после чего может быть организован обмен защищёнными сообщениями с использованием кода Вернама (XOR преобразования) -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Техническое задание (prompt) для приложения "LargeEntropy" 1. ОСНОВНЫЕ ХАРАКТЕРИСТИКИ -Цель: Генерация файла энтропии на основе данных акселерометра/гироскопа -Платформа: Android 14 (API 33), минимальная поддержка Android 5.0 (API 21) -Язык: Java -Архитектура: Single Activity с простой MVP структурой -Требования к производительности: Минимальное потребление ресурсов, фоновая работа сенсоров 2. ТЕХНОЛОГИИ И БИБЛИОТЕКИ - Android SDK 33 - AndroidX: AppCompat, Core, Activity - Sensor API (Hardware Sensor Framework) - File I/O (java.io) - BigInteger для обработки числовых данных - Handler для периодических задач - AlertDialog для пользовательских сообщений - Logging для отладки - Permission Handling для Android 11+ 3. РАЗРЕШЕНИЯ (PERMISSIONS) 3.1 Необходимые разрешения: AndroidManifest.xml: xml 3.2 Логика запроса разрешений: 1. Проверка версии Android: - API >= 30: Использовать MANAGE_EXTERNAL_STORAGE - API < 30: Использовать WRITE_EXTERNAL_STORAGE 2. Процесс запроса: a) Проверить текущие разрешения b) Если нет разрешения -> показать диалог с объяснением c) Для MANAGE_EXTERNAL_STORAGE: открыть системные настройки d) Для WRITE_EXTERNAL_STORAGE: стандартный запрос разрешений 3. Обработка результата: - Успех: продолжить инициализацию - Отказ: показать сообщение и завершить приложение 4. ПЕРЕМЕННЫЕ И ТИПЫ В MainActivity.java 4.1 Константы (Constants): java private static final String TAG = "LargeEntropy"; // Тег для логирования private static final int FSize = 1024000; // Целевой размер файла (1MB) private static final int PERMISSION_REQUEST_LEGACY = 100; // Код запроса для API < 30 private static final int MANAGE_STORAGE_REQUEST = 101; // Код запроса для API >= 30 4.2 Ссылки на UI компоненты (UI References): java private TextView tvStatus; // TextView для отображения статуса и размера файла private Button btnExit; // Кнопка для завершения приложения 4.3 Объекты сенсоров (Sensor Objects): java private SensorManager sensorManager; // Менеджер сенсоров для доступа к аппаратным датчикам private Sensor sensor; // Текущий активный сенсор (акселерометр или гироскоп) private SensorEventListener sensorListener; // Слушатель событий сенсора 4.4 Файловые объекты (File Objects): java private File dataFile; // Объект файла czechentropy.mp4 private FileOutputStream fos; // Поток для записи в файл 4.5 Переменные обработки данных (Data Processing Variables): java private char LeastSignificantDigit = '0'; // Текущая цифра (последняя записанная) private char LeastSignificantDigit2 = '0'; // Новая цифра (полученная с сенсора) 4.6 Флаги состояния (State Flags): java private boolean isRunning = true; // Флаг работы приложения private boolean hasStoragePermission = false; // Флаг наличия разрешений на хранилище 4.7 Объекты многопоточности (Threading Objects): java private Handler handler; // Handler для периодических задач в UI потоке private Runnable fileCheckRunnable; // Задача для периодической проверки размера файла 5. ЛОГИРОВАНИЕ (LOGGING) 5.1 Уровни логирования: java Log.d(TAG, "Информационные сообщения"); // DEBUG - общая информация Log.i(TAG, "Важные события"); // INFO - ключевые события Log.w(TAG, "Предупреждения"); // WARN - не критичные ошибки Log.e(TAG, "Критические ошибки"); // ERROR - критичные ошибки Log.e(TAG, "=== Least Significant Digit ===" + digit); // Специальный лог для цифр 5.2 Ключевые точки логирования: 1. Инициализация приложения 2. Запрос и получение разрешений 3. Создание/открытие файла 4. Подключение сенсора 5. Получение каждой новой цифры 6. Запись в файл 7. Проверка размера файла 8. Ошибки на всех этапах 6. ПРОВЕРКА ЦИФР (DIGIT VALIDATION) 6.1 Алгоритм проверки: java // Шаг 1: Получение значения с сенсора (только ось X) float xValue = event.values[0]; // Шаг 2: Преобразование float -> строка String valueStr = Float.toString(xValue); // Шаг 3: Очистка строки (удаление точки и минуса) valueStr = valueStr.replace(".", "").replace("-", ""); // Шаг 4: Удаление ведущих нулей while (valueStr.startsWith("0") && valueStr.length() > 1) { valueStr = valueStr.substring(1); } // Шаг 5: Проверка на пустую строку if (valueStr.isEmpty()) return; // Шаг 6: Преобразование в BigInteger BigInteger bigInt = new BigInteger(valueStr); String bigIntStr = bigInt.toString(); // Шаг 7: Извлечение последней цифры if (!bigIntStr.isEmpty()) { char digit = bigIntStr.charAt(bigIntStr.length() - 1); // Шаг 8: Валидация цифры (0-9) if (digit >= '0' && digit <= '9') { // Шаг 9: Логирование Log.e(TAG, "=== Least Significant Digit ===" + digit); // Шаг 10: Сравнение с предыдущей цифрой if (previousDigit != digit) { // Шаг 11: Запись в файл writeDigitToFile(previousDigit); previousDigit = digit; } } } 7. ОБРАБОТКА ОШИБОК (ERROR HANDLING) 7.1 Уровни обработки ошибок: 1. Уровень разрешений: - Нет доступа к хранилищу - Пользователь отказал в разрешениях 2. Уровень файловой системы: - Хранилище недоступно (не mounted) - Не удалось создать папку - Не удалось создать файл - Ошибка записи в файл - Ошибка чтения файла 3. Уровень сенсоров: - Сенсоры недоступны - Ошибка регистрации слушателя - Ошибка обработки данных сенсора 4. Уровень данных: - Некорректные данные с сенсора - Ошибка преобразования типов - Ошибка валидации цифр 7.2 Механизмы обработки: java // 1. Try-Catch для критичных операций try { // Критичный код } catch (IOException e) { Log.e(TAG, "Ошибка ввода-вывода", e); showErrorToUser("Ошибка работы с файлом: " + e.getMessage()); } catch (SecurityException e) { Log.e(TAG, "Ошибка безопасности", e); showErrorToUser("Нет разрешения: " + e.getMessage()); } catch (Exception e) { Log.e(TAG, "Неизвестная ошибка", e); showErrorToUser("Произошла ошибка: " + e.getMessage()); } // 2. Проверки перед выполнением операций if (!isStorageAvailable()) { showErrorToUser("Хранилище недоступно"); return; } // 3. Graceful degradation if (sensor == null) { Log.w(TAG, "Сенсор недоступен, работа без генерации данных"); tvStatus.setText("Сенсоры недоступны - сбор данных невозможен"); // Приложение продолжает работать, но без генерации } 8. ПОЛЬЗОВАТЕЛЬСКИЕ СООБЩЕНИЯ (USER MESSAGES) 8.1 Типы сообщений: java // 1. Toast - краткие уведомления Toast.makeText(context, "Сообщение", Toast.LENGTH_SHORT).show(); // 2. AlertDialog - важные сообщения, требующие внимания new AlertDialog.Builder(context) .setTitle("Заголовок") .setMessage("Подробное сообщение") .setPositiveButton("OK", null) .show(); // 3. TextView статуса - постоянная информация tvStatus.setText("Текущий статус: " + status); // 4. Log - для разработчиков Log.d(TAG, "Отладочная информация"); 8.2 Ключевые сообщения для пользователя: 1. Начальные: - "Проверка разрешений..." - "Запуск приложения..." 2. Разрешения: - "Доступ к хранилищу необходим для создания файла czechentropy.mp4" - "Доступ отклонен. Приложение закроется." 3. Файловая система: - "Хранилище недоступно" - "Файл создан" - "Файл найден. Размер: X байт" 4. Сенсоры: - "Акселерометр подключен" - "Гироскоп подключен" - "Нет доступных датчиков" 5. Процесс генерации: - "Размер файла: X / 1024000 байт" - "Maximum Entropy Maked" 6. Ошибки: - "Ошибка создания файла" - "Ошибка сенсора: [описание]" - "Не удалось получить доступ к хранилищу" 9. ОСНОВНЫЕ МЕТОДЫ MainActivity 9.1 Методы жизненного цикла: java onCreate() - Инициализация UI, запрос разрешений onDestroy() - Освобождение ресурсов, отписка от сенсоров onRequestPermissionsResult() - Обработка результата запроса разрешений onActivityResult() - Обработка результата системного запроса (MANAGE_EXTERNAL_STORAGE) 9.2 Методы разрешений: java checkPermissions() - Определение необходимых разрешений requestManageExternalStorage() - Запрос MANAGE_EXTERNAL_STORAGE (API 30+) setupApp() - Инициализация после получения разрешений 9.3 Методы файловой системы: java isStorageAvailable() - Проверка доступности хранилища setupFile() - Создание/открытие файла czechentropy.mp4 loadLastDigit() - Загрузка последней цифры из файла startFileCheck() - Запуск периодической проверки размера файла stopEverything() - Корректное завершение работы с файлом 9.4 Методы работы с сенсорами: java setupSensor() - Инициализация акселерометра/гироскопа SensorEventListener - Обработчик данных с сенсора (внутренний класс) 9.5 Методы пользовательского интерфейса: java showErrorToUser() - Отображение ошибок пользователю updateFileSize() - Обновление отображения размера файла exitApp() - Корректный выход из приложения 10. ТРЕБОВАНИЯ К КОДУ 10.1 Структура кода: 1. Импорты (сгруппированы по типам) 2. Константы и статические переменные 3. Переменные экземпляра 4. Методы жизненного цикла Activity 5. Методы разрешений 6. Методы инициализации 7. Методы работы с файлами 8. Методы работы с сенсорами 9. Методы UI и обработки ошибок 10. Вспомогательные методы 10.2 Правила именования: - Константы: UPPER_SNAKE_CASE - Переменные: camelCase - Методы: camelCase() - Классы: PascalCase - Теги логирования: "ClassName" 10.3 Обработка null и исключений: - Все внешние объекты проверяются на null - Критические операции в try-catch - Ресурсы освобождаются в finally или onDestroy Итоговый запрос для генерации кода: Сгенерируйте полный Java-код для MainActivity.java, activity_main.xml и AndroidManifest.xml на основе приведенных выше спецификаций. Требования: 1. Код должен быть максимально простым и понятным 2. Все переменные должны быть явно типизированы 3. Обязательно включить все описанные проверки и обработку ошибок 4. Реализовать логирование как описано в разделе 5 5. Добавить проверку цифр как в разделе 6 6. Реализовать обработку ошибок как в разделе 7 7. Включить пользовательские сообщения как в разделе 8 8. Соблюдать структуру методов как в разделе 9 9. Следовать требованиям к коду из раздела 10 Особое внимание уделить: - Корректной работе с разрешениями на Android 14 - Стабильной работе сенсоров - Надежной обработке файловых операций - Понятным сообщениям для пользователя - Полному логированию для отладки -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- (c) by Valery Shmelev https://oflameron.ru/Valery_Shmelev_5eng.pdf AI-powered Code Generation -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Листинг проекта -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- MainActivity.java package com.example.largeentropy; import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.provider.Settings; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import java.io.File; import java.io.FileOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.math.BigInteger; public class MainActivity extends AppCompatActivity { private static final String TAG = "LargeEntropy"; private static final int FSize = 1024000; private SensorManager sensorManager; private Sensor sensor; private TextView tvStatus; private Button btnExit; private File dataFile; private FileOutputStream fos; private char LeastSignificantDigit = '0'; private char LeastSignificantDigit2 = '0'; private boolean isRunning = true; private Handler handler = new Handler(); private Runnable fileCheckRunnable; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d(TAG, "Приложение запущено"); tvStatus = findViewById(R.id.tvStatus); btnExit = findViewById(R.id.btnExit); tvStatus.setText("Проверка разрешений..."); btnExit.setOnClickListener(v -> { Log.d(TAG, "Нажата кнопка Exit"); stopEverything(); finish(); System.exit(0); }); // Проверяем и запрашиваем разрешения checkPermissions(); } private void checkPermissions() { // Для Android 11+ используем MANAGE_EXTERNAL_STORAGE if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Environment.isExternalStorageManager()) { Log.d(TAG, "MANAGE_EXTERNAL_STORAGE уже есть"); setupApp(); } else { requestManageExternalStorage(); } } else { // Для старых версий if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { setupApp(); } else { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100); } } } private void requestManageExternalStorage() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("Доступ к хранилищу"); builder.setMessage("Приложению нужен доступ к хранилищу для работы с файлом czechentropy.mp4"); builder.setPositiveButton("Разрешить", (dialog, which) -> { try { Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); intent.setData(android.net.Uri.parse("package:" + getPackageName())); startActivityForResult(intent, 101); } catch (Exception e) { Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION); startActivityForResult(intent, 101); } }); builder.setNegativeButton("Отмена", (dialog, which) -> { tvStatus.setText("Доступ отклонен. Приложение закроется."); Toast.makeText(this, "Доступ отклонен", Toast.LENGTH_LONG).show(); finish(); }); builder.setCancelable(false); builder.show(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 101) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Environment.isExternalStorageManager()) { setupApp(); } else { tvStatus.setText("Доступ не предоставлен"); Toast.makeText(this, "Доступ к хранилищу не предоставлен", Toast.LENGTH_LONG).show(); } } } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 100 && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { setupApp(); } else { tvStatus.setText("Разрешение отклонено"); Toast.makeText(this, "Разрешение отклонено", Toast.LENGTH_LONG).show(); } } private void setupApp() { Log.d(TAG, "Настройка приложения"); // Проверка хранилища String storageState = Environment.getExternalStorageState(); if (!Environment.MEDIA_MOUNTED.equals(storageState)) { tvStatus.setText("Хранилище недоступно: " + storageState); Toast.makeText(this, "Хранилище недоступно", Toast.LENGTH_LONG).show(); return; } // Настройка файла if (!setupFile()) { return; } // Настройка сенсора setupSensor(); // Запуск проверки файла startFileCheck(); } private boolean setupFile() { try { File downloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); Log.d(TAG, "Папка Download: " + downloadDir.getAbsolutePath()); if (!downloadDir.exists()) { if (!downloadDir.mkdirs()) { tvStatus.setText("Ошибка: не могу создать папку Download"); return false; } } dataFile = new File(downloadDir, "czechentropy.mp4"); Log.d(TAG, "Файл: " + dataFile.getAbsolutePath()); if (dataFile.exists()) { long fileSize = dataFile.length(); Log.d(TAG, "Файл существует, размер: " + fileSize + " байт"); tvStatus.setText("Файл найден. Размер: " + fileSize + " байт"); if (fileSize >= FSize) { tvStatus.setText("Maximum Entropy Maked"); isRunning = false; return true; } else { fos = new FileOutputStream(dataFile, true); } } else { if (dataFile.createNewFile()) { Log.d(TAG, "Файл создан"); fos = new FileOutputStream(dataFile, true); tvStatus.setText("Файл создан"); } else { tvStatus.setText("Ошибка создания файла"); return false; } } // Загружаем последнюю цифру loadLastDigit(); return true; } catch (Exception e) { Log.e(TAG, "Ошибка настройки файла", e); tvStatus.setText("Ошибка файла: " + e.getMessage()); return false; } } private void loadLastDigit() { try { if (dataFile.exists() && dataFile.length() > 0) { FileInputStream fis = new FileInputStream(dataFile); fis.skip(dataFile.length() - 1); int lastByte = fis.read(); fis.close(); if (lastByte != -1) { LeastSignificantDigit = (char) lastByte; Log.d(TAG, "Загружена последняя цифра: " + LeastSignificantDigit); } } } catch (Exception e) { Log.e(TAG, "Ошибка загрузки последней цифры", e); } } private void setupSensor() { try { sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); // Сначала пробуем акселерометр Sensor accelSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); if (accelSensor != null) { sensor = accelSensor; sensorManager.registerListener(sensorListener, sensor, SensorManager.SENSOR_DELAY_NORMAL); Log.d(TAG, "Акселерометр подключен"); tvStatus.append("\nАкселерометр подключен"); return; } // Если нет акселерометра, пробуем гироскоп Sensor gyroSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); if (gyroSensor != null) { sensor = gyroSensor; sensorManager.registerListener(sensorListener, gyroSensor, SensorManager.SENSOR_DELAY_NORMAL); Log.d(TAG, "Гироскоп подключен"); tvStatus.append("\nГироскоп подключен"); return; } tvStatus.append("\nНет доступных датчиков"); Log.e(TAG, "Нет доступных датчиков"); } catch (Exception e) { Log.e(TAG, "Ошибка настройки сенсора", e); tvStatus.append("\nОшибка сенсора: " + e.getMessage()); } } private SensorEventListener sensorListener = new SensorEventListener() { @Override public void onSensorChanged(SensorEvent event) { if (!isRunning || fos == null) return; try { // Берем только значение по оси X (первый элемент массива) float xValue = event.values[0]; // Преобразуем float в строку, убираем точку и минус String valueStr = Float.toString(xValue); valueStr = valueStr.replace(".", "").replace("-", ""); // Убираем ведущие нули if (valueStr.length() > 1) { while (valueStr.startsWith("0") && valueStr.length() > 1) { valueStr = valueStr.substring(1); } } // Если строка пустая, пропускаем if (valueStr.isEmpty()) return; // Преобразуем в BigInteger BigInteger bigInt = new BigInteger(valueStr); String bigIntStr = bigInt.toString(); // Берем последнюю цифру if (!bigIntStr.isEmpty()) { LeastSignificantDigit2 = bigIntStr.charAt(bigIntStr.length() - 1); // Логируем Log.e(TAG, "=== Least Significant Digit ===" + LeastSignificantDigit2); // Проверяем, что это цифра if (LeastSignificantDigit2 >= '0' && LeastSignificantDigit2 <= '9') { // Если цифра изменилась - записываем в файл if (LeastSignificantDigit != LeastSignificantDigit2) { try { fos.write(LeastSignificantDigit); fos.flush(); Log.d(TAG, "Записана цифра: " + LeastSignificantDigit); LeastSignificantDigit = LeastSignificantDigit2; } catch (IOException e) { Log.e(TAG, "Ошибка записи в файл", e); } } } } } catch (Exception e) { Log.e(TAG, "Ошибка обработки сенсора", e); } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // Не используется } }; private void startFileCheck() { fileCheckRunnable = new Runnable() { @Override public void run() { if (!isRunning) return; try { if (dataFile != null && dataFile.exists()) { long fileSize = dataFile.length(); runOnUiThread(() -> { tvStatus.setText("Размер файла: " + fileSize + " / " + FSize + " байт"); }); if (fileSize >= FSize) { runOnUiThread(() -> { tvStatus.setText("Maximum Entropy Maked"); }); stopEverything(); } } } catch (Exception e) { Log.e(TAG, "Ошибка проверки файла", e); } // Повторяем каждую секунду if (isRunning) { handler.postDelayed(this, 1000); } } }; handler.post(fileCheckRunnable); } private void stopEverything() { Log.d(TAG, "Остановка всего"); isRunning = false; // Останавливаем проверку файла if (handler != null && fileCheckRunnable != null) { handler.removeCallbacks(fileCheckRunnable); } // Отключаем сенсор if (sensorManager != null && sensorListener != null) { sensorManager.unregisterListener(sensorListener); } // Закрываем файл if (fos != null) { try { fos.close(); Log.d(TAG, "Файл закрыт"); } catch (IOException e) { Log.e(TAG, "Ошибка закрытия файла", e); } } } @Override protected void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy"); stopEverything(); } } -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Activity_main.xml