Где находится файл .apk в Android Studio?
Не подписывается файл apk после обновления Android Studio
Столкнулся с вот какой проблемой. Обновил Android Studio до версии 2.3, gradle до 3.3 Вроде бы все.
Где находится файл csc.exe у Microsoft Visual Studio 2008?
Задаю не новый вопрос, но всё же. Где находится файл csc.exe у Microsoft Visual Studio 2008.
Открытие apk в Android Studio
Каким способом можно открыть apk в программе? просто надо проверить антивирус, а он засекает.
Скомпилировать apk в Android Studio
У меня есть проект, который я разрабатывал в Visual Studio. Сейчас мне надо создать апк файл для.
Android Studio. Kotlin. Сохранение файла в общедоступной папке Download
В работе над своим проектом больше всего времени я убил на то, чтобы разобраться, как правильно сохранить файл в общедоступную папку, например, Download. Мне не удалось найти четкого и ясного объяснения в интернете. Собирал информацию по частям и доходил до результата методом проб и ошибок.
Виной всей этой сложности — множество факторов. Языковой барьер: русский — английский, Kotlin — Java. Различия в способах копирования в разных версиях Android. Разобраться было не просто. В итоге — пишу этот гайд, чтобы облегчить жизнь тем, кто пойдет за мной следом.
Задача
Мне нужно было реализовать в моем приложении возможность делать резервную копию базы данных так, чтобы пользователь мог получить доступ к копии из другого приложения. Например, отправить файл резервной копии себе на электронную почту или скачать по проводу на стационарный компьютер.
Я понял, что все данные приложения, в том числе и файл базы данных находятся во внутренней папке, к которой доступ из-вне получить невозможно. Посему, нужно каким-то образом сделать копию файла базы данных из внутреннего хранилища в общедоступную папку. Я выбрал папку Download.
Решение
1. Правлю файл Манифеста
Я так понял, что этого достаточно. При разрешенном доступе для записи, доступ для чтения можно не получать.
2. Обрабатываю исключение (exeption)
Весь код, отвечающий за копирование, упаковываю в try. Если что-то пойдет не так, то приложение «не вылетит», выдав пользователю сообщение об ошибке, а выполнится код в catch.
try < // копирую данные . >catch (e: Exception) < e.printStackTrace() // если что-то пошло не так . >
3. Проверяю версию Android
Смотрю информацию о версии в файле build.gradle (Module)
android < . defaultConfig < applicationId "имя.вашего.проекта" minSdkVersion 23 targetSdkVersion 30 . >. >
В моем проекте указано, что целевая версия — 30, минимальная — 23. Это значит, что устройства с такой минимальной версией должны справляться с моим приложением успешно. Для большей ясности о версиях Android можно посмотреть на следующий скриншот:

В табличке выше смотрю столбец API Level. Android 6.0 Marshmellow — минимальная версия Android, 84,9% устройств будет поддерживаться.
Android 10 в коде имеет маркировку «Q» (Build.VERSION_CODES.Q) Оказывается, что копирование файлов, а именно организация доступа к общедоступным папкам, с этой версии Android и выше выглядит совершенно иначе!

Зачем? Чтобы дать вам почувствовать вкус вашего будущего, предварительный просмотр того, что грядет. Con permiso, Capitan. Зал арендован, оркестр задействован. Пришло время посмотреть, умеешь ли ты танцевать.
Видимо я танцевать научился, иначе бы не писал эту статью. Я понял, что код для копирования файла в общедоступную папку для Android 10+ должен быть другим.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) < // version >= 29 (Android 10, 11, . ) . > else < // version
Засим в обязательном порядке проверяю версию и готовлюсь писать разный код. Печаль.
4. Копирую, если версия Android >= 10 (SdkVersion >= 29)
В этом случае никаких разрешений получать не надо. По-моему, даже в Манифесте можно ничего не указывать. Тут и правда мне пришлось, как у нас говорят - "потанцевать с бубном", пока я не разобрался что к чему.
val contentValues = ContentValues().apply < put(MediaStore.MediaColumns.DISPLAY_NAME, dbFileName) >val dstUri = applicationContext.contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues) if (dstUri != null) < val src = FileInputStream(applicationContext.getDatabasePath(DbName.DATABASE_NAME)) val dst = applicationContext.contentResolver.openOutputStream(dstUri) src.copyTo(dst!!) src.close() dst.close() backupOk(dbFileName) >else backupFail()
Здесь я пользуюсь компонентом MediaStore. Его использование похоже на работу с базой данных. Сначала "запись" со всеми ее полями прописывается в contentValues. Я пишу тут только имя файла в колонке DISPLAY_NAME, хотя в примерах видел, что указывают еще размер SIZE и некоторые другие поля. Но у меня работает и так.
Потом при помощи contentResolver вставляю свою запись в таблицу MediaStore.Downloads.EXTERNAL_CONTENT_URI. В итоге получаю путь к файлу в формате Uri и только после этого по нему копирую данные.
О различных способах копирования можно почитать тут: https://stackoverflow.com/questions/9292954/how-to-make-a-copy-of-a-file-in-android Я несколько из них попробовал. Все рабочие, но короче и лаконичнее, конечно, выглядит src.copyTo(dst)
5. Проверяю, получены ли разрешения
Для Android 9 и ниже мало указать в Манифесте разрешения для доступа. Их еще нужно получить. Доступ к общим папкам приложению может дать пользователь, если его об этом запросить или он сам в настройках указал разрешения.

Для того, чтобы проверить, есть ли у моего приложения разрешение доступа к хранилищу, пишу следующий код:
if (ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) < // разрешение есть . >else < // разрешения нет . >
Попытки копировать без разрешения не увенчаются успехом.
6. Запрашиваю разрешение, если его нет
Можно попросить пользователя дать разрешение приложению на копирование файлов в общие папки. Выглядеть оно может примерно так:

Код запроса состоит из двух частей. Первая - спрашивает. Вторая - получает ответ (callback).
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), Const.REQUEST_CODE)
Этот нехитрый код покажет пользователю окно с вопросом из скриншота выше и предложит разрешить (allow) или запретить (deny) доступ. Request_code - любое число, с которым в последствии нужно свериться, чтобы убедиться, что пришел ответ именно для вашего приложения.
7. Обрабатываю ответ пользователя
Ответ буду получать в другой части программы при помощи функции onRequestPermissionsResult. Она запускается при нажатии пользователем "Allow" или "Deny".
override fun onRequestPermissionsResult( requestCode: Int, permissions: Array, grantResults: IntArray ) < super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == Const.REQUEST_CODE && permissions[0] == Manifest.permission.WRITE_EXTERNAL_STORAGE) < if (grantResults[0] == PackageManager.PERMISSION_GRANTED) < try < copyFile() >catch (e: Exception) < e.printStackTrace() backupFail() >> else backupFail() > >
Код выше даю в том виде, как он написан у меня без пропусков. Проверяю, что пришло именно разрешение WRITE_EXTERNAL_STORAGE и requestCode тоже совпадает. Тогда только смотрю результат. Если он - PERMISSION_GRANTED, то копирую, не забыв упаковать копирование в try.
8. Копирую, если версия Android < 10 (SdkVersion < 29)
Код копирования в данном случае упаковал в отдельную функцию, т.к. он запускается из разных частей программы. Если разрешение получено, то сразу копирую и после получения разрешения, если его еще не было.
private fun copyFile() < val downloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) if (downloadDir.canWrite()) < val dbFileName = Const.BACKUP_FILENAME_MASK + fHelper.dateFromLong(applicationContext, fHelper.dateFromToday(), Const.YEAR_MONTH_DAY) + ".db" val src = FileInputStream(applicationContext.getDatabasePath(DbName.DATABASE_NAME)) val dst = FileOutputStream(File(downloadDir, dbFileName)) src.copyTo(dst) src.close() dst.close() backupOk(dbFileName) >else backupFail() >
Ответ
Создание копии базы данных работает на всех устройствах Android. Мое приложение не поддерживает версии меньше 6.0 Marshmellow (SdkVersion 23), поэтому на самых ранних версиях я и не проверял.
Очень надеюсь, что мое описание процесса сэкономит вам время, ибо я его в таком полном виде в интернете не встречал.
Творите добро, пусть мир будет лучше!
Задавайте вопросы, пишите комментарии. Нужно ли что-нибудь пояснить более подробно?
- сохранение данных
- общедоступные папки
- разные версии Android
- работа с файлами
- разрешения android
Публикация приложения
После создания приложения, его тестирования и отладки мы можем приступить к его публикации. Суть публикации заключается в создании файла с расширением .apk, которое будет представлять приложение, и его последующее размещение в Google Play Market или на других внешних сайтах. По умолчанию в процессе отладки и создания приложения файл apk уже создается, и мы можем его найти в папке проекта по пути Название_проекта\app\build\outputs\apk. По умолчанию файл называется app-debug.apk и представляет debug-версию.
Но для полноценно публикации данного файла может оказаться недостаточно. И нам еще дополнительно надо произвести некоторую подготовку проекта к релизу. Для это следует указать в файле манифеста у элемента установлены атрибуты android:versionCode и android:versionName . Также в файле манифеста элемент не должен содержать атрибута android:debuggable
Кроме того, на этом этапе можно установить иконку для приложения, которая будет отображаться на рабочем экране гаджета, название приложения (атрибут android:label у элемента), а также можно задать лицензионное соглашение.
В файле манифеста также следует определить название пакета (атрибут package элемента ), которое будет использоваться для приложения в дальнейшем. По умолчанию при разработке в Android Studio пакеты приложений начинаются с com.example. Не стоит оставлять данное название, так как название пакета будет служить уникальным идентификатором вашего приложения. Например, ниже в моем случае названием пакета служит "com.maverics.eugene.telephonelist":
При этом если в файлах кода java название пакета в начале файла также должно соответствовать пакету приложения.
Установка требований
На этапе подготовки к релизу также можно установить требования к API. Например, наше приложение имеет определеную минимальную версию ОС Android, поэтому мы можем установить в файле манифеста соответствующие атрибуты у элемента
- android:minSdkVersion — минимальная версия Android
- android:targetSdkVersion — оптимальная версия API
- android:maxSdkVersion — максимальная версия системы
Например, пусть минимальная версия Jelly Beans 4.1.2, а оптимальная KitKat 4.4.4:
Подпись приложения
Когда все уже готово, приложение для Android должно быть подписано сертификатом, благодаря которому можно идентифицировать автора приложения. Когда мы тестируем приложение, устанавливая его через Android Studio на устройство, то оно подписывается автоматически. Но для создания релиз-версии нам надо произвести дополнительно ряд действий.
При создании сертификата следует помнить, что при обновлении приложения система будет сравнивать сертификаты старой и новой версии. И обновление будет происходить, если сертификаты обоих версий совпадут. Но если новая версия будет подписана новым сертификатом, то приложение будет расцениваться как совершенно новое, никак не связанное со старой версией и представляющее совершенно другое приложение. В этом случае чтобы его установить, новая версия должна будет иметь другой название пакета, нежели старая.
Во-первых, в Android Studio выберем в меню пункт Build -> Generate Signed APK . После этого нам откроется окно мастера:

Нажмем на кнопку Create new. . После этого нам откроется окно создания ключа:

Введем в поле Key store path путь к файлу сетификата, который будет создан. Если указанной папки не существует, то ее надо создать или определить существующую папку.
В поле Password/Confirm указываем пароль.
В поле Alias указываем псевдоним. Можно поставить произвольное название.
В поле First and Last Name вписываем имя и фамилию. И далее пишим подразделение, организацию, город, страну и код страны.
В конце нажимаем OK.
После этого автоматически обновится первое окошко:

Далее нажмем на кнопку Next:

Финальное окно покажет нам путь к каталогу, где будет находиться подписанное приложение apk в release-версии. Нажмем на Finish.
Теперь по указанному пути можно будет найти подписанный apk, который будет иметь название app-release.apk:

Мы можем переименовать файл, сохранив его расширение и выложить в Play Market или на любой сайт или сразу загрузить на мобильное устройство. После загрузки на телефон/планшет достоточно нажать на него, и с помощью стандартного установщика пакетов приложение будет установлено. Правда, здесь также надо учитывать, что если мы устанавливаем приложение не из Play Market, то в настройках надо разрешить установку из других источниках - Безопасность->Неизвестные источники (Разрешить установку приложений из других источников)
Куда android studio по умолчанию сохраняет файлы?
Однако потом никак в папке с проектом не могу найти этот файл. Куда студия его сохраняет по умолчанию?
Отслеживать
69.8k 9 9 золотых знаков 66 66 серебряных знаков 122 122 бронзовых знака
задан 4 сен 2018 в 17:19
Sergei Mikhailovskii Sergei Mikhailovskii
436 5 5 серебряных знаков 17 17 бронзовых знаков
IOException у вас будет и ничего никуда не запишется. Нельзя в Андроид просто взять и писть куда захочется. Вот здесь все об этом: developer.android.com/training/data-storage/files
4 сен 2018 в 18:07
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Вы пишете приложение под ОС андроид и запускаете его на девайсе/эмуляторе, не на машине, на которой компилируете и собираете.
А андроид приложение пишет файлы на тот девайс, на котором запущено. Таким образом вам надо искать файл не в проекте, но в файловой системе телефона. Скорее всего прямо в корне его диска.
Отслеживать
ответ дан 4 сен 2018 в 17:23
69.8k 9 9 золотых знаков 66 66 серебряных знаков 122 122 бронзовых знака
перерыл все папки и .android и .AndroidStudio3.1, но все равно нигде не нашел. Запускаю через эмулятор. Где он вообще хранится? Мне казалось, что он в папке со студией должен
4 сен 2018 в 17:37
@SergeiMikhailovskii, сказано же - в файловой системе эмулятора, а не компьютера. Но скорее всего он вообще не пишется и если заглянете в LogCat узнаете почему.
4 сен 2018 в 17:41
@SergeiMikhailovskii, ищите через эмулятор, не на компе. Хз где и в каком формате комп хранит файлы эмулятора. И да, скорее всего у вас файл не записался, т.к. выкидывает ошибку отсутствия разрешения пользователя на запись, если вы на ОС>6 версии запускаете.
4 сен 2018 в 17:47
ФС запущенного эмулятора/подключенного устройства можно увидеть в Device File Explorer ( Menu->View->Tool Windows->Device File Explorer )
