Многие пользователи Android столкнулись с досадной проблемой, связанной с доступом приложений к SD карте. Одним из таких приложений является Google Фото. Когда-то всё было нормально. Но в Android 4.4 Google внедрили новую системную конфигурацию, которая запрещает приложениям писать на sd-карту. Удалять изображения через галерею, а затем снова удалять их же в google photos крайне неудобно.

Для себя я проблему решил рутованием девайса и исправлением конфигурации. Подробности на видео:



Но для обычных пользователей должно всё работать без root. О том как это осуществить я предлагаю обсудить в этой статье. Приглашаю представителей компании Google, Android разработчиков и всех интересующихся под хабракат.

Некоторых пользователей лишили функционала без предупреждения. Я видел комментарии пользователей со следующей ситуацией. Раньше они хранили фото на sd карте и пользовались google photo без каких-либо проблем. Потом производитель телефона предложил сделать OTA обновление (до 4.4 или выше), на что пользователи соглашались. Но они и думать не могли, что потеряют функционал. Теперь google photo не может удалять снимки, и чтобы обезболить процесс управления снимками, вынуждены хранить их на внутренней памяти, что само по себе болезненно.

В чём здесь дело


Google давно хотели запретить беспрепятственный доступ приложениям к sd карте. Объясняется это тем, что при удалении приложения, система не может узнать, какие файлы принадлежат приложению, таким образом sd карта захламлялась. И вот в Android 4.4 google ввели такое понятие как SAF (Storage Access Framework). Они запретили приложениям что-либо менять на sd карте, за исключением личного каталога приложения. А если приложение просит, то даёт право на чтение (но не запись) всего что на sd карте.

Цитата отсюда:
Just to sum up, here are the options 3rd-party apps have on KitKat:
An app without any permissions:
Automatic read and write for designated private folders on the primary and secondary storage
With WRITE_EXTERNAL_STORAGE, they also have:
Read and write for any public folder on the primary (built-in) storage
Read (not write) for any public folder on the secondary (SD card) storage

То есть для приложений, которые не предустановлены на телефоне, а в моём случае google Фото не было предустановлено, официально вообще нет возможности как-то управлять файлами! Google, я не понимаю, как можно было так поступить. Не доделали фичу – доделывайте. Но зачем в потребительские устройства внедрять то, что ещё не работает?

Как поступить в этой ситуации?


Как я уже сказал выше, для себя я уже проблему решил, исправив конфигурацию системы (нужен root). А что насчёт «простых» пользователей, которые не слышали о root? У меня есть несколько идей, как решить эту проблему. Некоторые из них подходят только для Google, а какие-то, возможно, по силам реализовать сообществу. Итак, какие есть варианты?

Вариант «Личный каталог»


Google должны сделать, чтобы по возможности всё работало. Понятно, что они не могут советовать рутовать устройство. Но что насчёт личного каталога /storage/extSdCard/Android/data/com.google.android.apps.photos? Что они там хранят? Скорее всего там не корзина, потому что удаляемые в корзину файлы находятся в /data/user/0/com.google.android.apps.photos/files/trash_files. Я не знаю, может в Android не принято хранить пользовательские данные в таких каталогах. Просто предлагаю рабочий вариант.

Т.е. если приложение видит, что работает на Android 4.4 и нет прав доступа, то вывести сообщение вроде «Нет доступа. Предлагаем в настройках вашей системной камеры задать сохранение в каталог /storage/extSdCard/Android/data/com.google.android.apps.photos/DCIM. Имейте в виду, что при удалении google photos все снимки будут удалены». Сейчас приложение игнорирует данный каталог. Если в него положить снимок, каталог не появится в списке выбора для синхронизации.

Скорее всего это мёртвый вариант, поскольку камера должна быть системной (иначе она не сможет писать в чужой каталог на sd карте), а системная камера скорее всего не умеет выбирать каталог для сохранения (на S4 не умеет точно).

Вариант «Не баг, а фича»


Но оказывается разработчики нашли лазейку, всё таки позволяющую приложениям манипулировать с файлами. Я сам проверял: восстановил исходный platform.xml (в котором нет доступа на запись на sd карту), перезагрузился, установил total commander и… Удаление работает! И даже код есть.

Тут решение за Google, может быть для них неприемлемо такое решение. Но как по мне, ничего зазорного в том, чтобы воспользоваться багом как фичей нет, ведь они должны сделать чтобы всё работало.

Вариант «Всё плохо, но вы обновитесь»


В той статье написано, что не на всех устройствах сработает такой хак. Тут уж ничего не остаётся, кроме как просто показать сообщение, что нет доступа. Правда в нём можно намекнуть, что помог бы рут, либо переход на другую версии Android, причём на более старую тоже сойдёт.

Вариант «Закладка»


Ещё у меня была идея, что Google могут обновить свои google сервисы (а это системное приложение) таким образом, чтобы к нему могло обращаться несистемное приложение google photos с просьбой удалить файл. И не нужен будет root. Пойдёт ли на это google?

Решение для более свежих версий Android


В Android 5.0 google улучшила SAF, и теперь приложения могут попросить пользователя предоставить доступ на запись в конкретные каталоги.

Цитата отсюда:
Richer access to secondary shared storage devices
In KitKat we introduced APIs that let apps read/write file in app-specific directories on secondary storage devices, such as SD cards.

We heard loud and clear that developers wanted richer access beyond these directories, so in Lollipop we added the new ACTION_OPEN_DOCUMENT_TREE intent.  Apps can launch this intent to pick and return a directory from any supported DocumentProvider, including any of the shared storage supported by the device.  Apps can then create, update, and delete files and directories anywhere under the picked tree without any additional user interaction.  Just like the other document intents, apps can persist this access across reboots.

This gives apps broad, powerful access to manage files while still involving the user in the initial selection process.  Users may choose to give your app access to a narrow directory like “My Vacation Photos,” or they could pick the top-level of an entire SD card; the choice is theirs.

Но даже на Android 5 google фото не использует эту возможность, а просто сообщает, что не имеет доступа. Я считаю, что прежде чем синхронизировать какой-то каталог, приложение сначала должно просить права на запись в него через SAF, чтобы можно было удалять снимки. Это можно сделать прямо с той самой активности, где переключателем выбираешь, какие каталоги хочешь синхронизировать (Настройки — Автозагрузка и синхронизация — Выберите папки). Google, почему вы так не делаете?

Подведём итог


Вот как себя ведёт приложение сейчас:
Пользователь нажал помоечку
Имеется ли непосредственный доступ на запись на sd карту?
Да — удаляем снимок.
Нет – выводим сообщение что нет доступа.

Как должно быть:
Пользователь нажал помоечку
Имеется ли непосредственный доступ/через лазейку на запись на sd карту?
Да — удаляем снимок.
Нет — тогда
— Мы работаем на Android 5.0+?
— Да — запросить доступ к каталогу через SAF и удалить снимок.
— Нет — (т. е. скорее всего это 4.4. Но может быть и специально изменённый 4.3-, настроенный как в 4.4) тогда:
— — Вывести сообщение: «Нет доступа, но вам поможет рут, либо смена версии Android» либо «Настройте системную камеру на сохранение снимков в /storage/extSdCard/Android/data/com.google.android.apps.photos/DCIM», либо «Обновите google сервысы, мы через них дадим доступ на запись» на усмотрение google.

Нужны разработчики


Если тут есть представители google, передайте информацию разработчикам. Потому что данная тема обсуждается уже давно, но Google не исправляет ситуацию.

А для хабраюзеров, которые умеют разрабатывать на Android хочу задать вопрос. Возможно ли изменить приложение так как я сказал, но своими силами, не дожидаясь google? Я знаю про несоответствие цифровой подписи, но в нашем случае это не важно. Ведь всё это нужно только если приложение не системное. А если оно не системное, то можно его удалить и затем установить с другой подписью. Я видел модифицированное приложение вместо youtube — OGYouTube. Возможно это как раз то, что я описываю.

Заполните эту форму, если у вас была/есть описываемая проблема.

Результаты опроса
Количество ответов: 101 (на момент 20 сентября 2016):










На этом считаю, что сделал своё дело. Теперь ход Google. Или сообщества.
Поделиться с друзьями
-->

Комментарии (26)


  1. ivvi
    28.09.2016 19:28
    +2

    Что такое помоечка?!?


    1. LinuxComp
      28.09.2016 19:34

      Иконка такая. Trash bin, мусорный бак, ведёрко.


  1. Thero
    28.09.2016 21:47

    увы разработчики гугл обычно воспринимают только отзывы отправленные через отзыв в приложении.
    боюсь эта статья не в аудиторию.

    цитата из справки гугл:

    Что делать, если удаленная фотография снова появилась в коллекции?

    Если это произошло, но вы не восстанавливали фото, попробуйте удалить его в приложении «Галерея». Возможно, фото или видео, которое вы пытаетесь удалить, хранится на съемной карте памяти.


    1. LinuxComp
      28.09.2016 21:58

      Я видел это в справке. И это значит, что google в курсе возможной проблемы. Даже само наличие диалога о недостатке прав — это факт того, что программисты предусмотрели такую ситуацию.
      Удивляет то, что google уже столько времени ничего с этим не делает.
      И через отзывы в приложении им много писали, судя по опросу. Хотелось бы надеяться, что этой статьёй я привлеку внимание google к проблеме.


      1. Thero
        28.09.2016 22:18

        ну я им написал отзыв щас через приложение, потому что у меня это ещё более абсурдно выглядит у меня нет галереи… только гугл.фото но меня посылают в галерею…


        1. LinuxComp
          28.09.2016 23:37

          А, точно. Забыл про этот абсурдный случай сказать на видео…


  1. TimsTims
    29.09.2016 11:00

    Призыв гугла ради совсем небольшой функции в небольшой программе Google Photo выглядит мягко говоря забавно на фоне того, как гугл уже призывали не удалять Reader, затем призывали не удалять Picasa и еще что-то там было кажется с Hangouts…
    А вы тут просите явиться разрабочтам с небесного гугла и узнать, что photo не удаляет фотки. Такая форма багрепорта… Есть ведь альтернативные программы, их в маркете полно. Т.е. альтернатива вполне себе есть.


    1. qw1
      29.09.2016 12:36

      Удаление Reader — политическое решение, поэтому повлиять на него очень сложно.
      А тут баг, который может исправить один программист, поэтому могут и прислушаться.


  1. nikitastaf1996
    29.09.2016 12:57

    Ну они потихоньку это дело улучшают.В 4.4 ввели SAF.В 6.0 права на доступ и обьеденение внутренней и внешней памяти.В 7.0 ввели возможность запросить права на отдельную папку и виртуальные файлы.


    1. LinuxComp
      29.09.2016 15:41

      Да, изменения были. Но порядок был такой:
      4.3 — всем всё можно
      4.4 — ввели saf, нет возможности записи на sd без root или лазейки
      5.0 — возможность предоставлять приложениям права записи в каталоги на sd
      6.0 — Возможность исп. sd карту вместо (!) встроенной памяти.
      7.0 — виртуальные файлы

      Обратите внимание, что нововведение в 6.0 превращает карту в несъёмную. Хоть физически файлы и лежат на ней, вы не можете просто вынуть её и вставить в комп, т.к. карта отформатирована особым образом. Кроме того, надо понимать, что в таком режиме sd карта будет именно заменять (но не дополнять) внутреннюю память. Соответственно, преимущество sd карты теряется. И прямого отношения к проблеме доступа на sd это нововведение не имеет. Как и нововведение в 7.0.


    1. niks255
      29.09.2016 19:04

      В 6.0 можно попросить разрешение WRITE_EXTERNAL_STORAGE и сможешь писать на карту памяти. Сталкивался с этим. Но отказ в разрешении тоже надо обрабатывать, система никаких песочниц для этого не даёт и приложение упадёт.


  1. xuman
    29.09.2016 15:26

    а на Android 6 как с этим? можно поинтересоваться.


    1. LinuxComp
      29.09.2016 15:58

      Некоторое время назад я проводил эксперименты, и, насколько помню, метод sd fix не работает для 6.0.
      Вот видео, где я показал неработоспособность варианта «сделать приложение системным» на 4.4.
      Но по-моему, на 6.0 это сделать можно. И есть ещё однин способ исправить конфигурацию системы.
      Когда на 6.0 прошьюсь, проверю это и запишу следующее видео.


  1. Kellis
    29.09.2016 15:58

    Проблеме уже около года. Не верится, что поправят или даже, что о ней знают ТАМ.


  1. kay
    29.09.2016 16:16

    Такая же проблема. root не получить (слишком редкий девайс), прошивку не обновить, застрял на 4.4


    1. LinuxComp
      29.09.2016 16:40

      А откатить на более старую не получится?


      1. kay
        30.09.2016 10:56

        Изначально была версия 4.4


        1. LinuxComp
          30.09.2016 21:45

          Я вас понял.
          Вот об этом то я и говорю, что есть пользователи, у которых нет вариантов решения, даже невзирая на наличие или отсутствие навыков по перепрошивке.
          Проверьте на всякий случай удаление файлой с помощью лазейки по варианту «не баг, а фича» (например, Total Commander'ом). Если сработает — значит у вас ещё не «всё плохо» и нужно бы модифицировать GP для исп. лазейки силами сообщества.
          Если же у вас совсем «всё плохо», то есть: системная камера не может сохранять в произвольный каталог, и Google никогда не сделают вариант «закладка»,
          то тут поможет либо смена девайса, либо искать вариант самостоятельного взлома девайса.


  1. kalterfive
    29.09.2016 16:58

    Ни у кого, кстати, не было опыта восстановления прав platform.xml без какого?либо, прежде имевшегося, инструментария самого смарта?


    1. LinuxComp
      29.09.2016 17:33

      Не понял ваш вопрос.


      1. kalterfive
        29.09.2016 18:33

        Есть проблема, связанная с правами platform.xml: они должны быть 644, в то время как копирование/перемещение без --preserve=mode может изменить их из?за umask – причём это происходит неосознанно со стороны модифицирующего.


        Factory reset технически никак не может помочь – не в его компетенции; подключить устройство через MTP, опять же, не выйдет из?за поломанной инициализации. Единственный простой выход – сменить eMMC на новый, но, может, есть альтернативные пути?


        1. LinuxComp
          30.09.2016 00:19

          Попробуйте сделать chmod через adb, зайдя в recovery.


  1. TheIncognito
    29.09.2016 19:04
    +1

    Тоже был возмущён этим. Но, так как с первого устройства на Андроиде использую root-доступ, для меня проблема решилась правкой 1 файла. Устройство должно подчиняться человеку, а не наоборот.

    Мои сочувствия пользователям, для устройств которых 4.4 — последняя запланированная версия, и обновлений не будет.


  1. LinuxComp
    01.10.2016 19:59
    +1

    Я понял, почему я подумал, что Google Photos было предустановлено. Я сделал обновление телефона на другую версию OS. Затем, когда хотел запустить google photos, на экране появилось приглашение обновить приложение. Я нажал кнопку обновить и открылось окно Play Market на странице Google Photos. Но меня смутил факт, что вместо кнопки «обновить» отображалась кнопка «установить». Значит, приложение ещё не установлено. Но из какого тогда приложения я только что пришёл в play market? Я же нажал на иконку Google Photos.
    Решил поинтересоваться, кто маскируется под Google Photos (названием и иконкой): при запущенной активности выполнил команду

    adb shell dumpsys window windows | grep -E 'mCurrentFocus|mFocusedApp'
    

    И увидел ответ:
    com.google.android.apps.plus/com.google.android.apps.plus.phone.PhotosAppPromoActivity
    


    Таким образом, приложение google plus имеет несколько иконок в меню приложений: свою и google photos. Я не знал, что такое бывает. Видимо, так сделано, чтобы переход от google+ photo к googe photos был прозрачным для пользователя.

    Вывод: при кажущейся предустановленности, реально приложение Google Photos не предустановлено на уже несвежих версиях ос.


    1. LinuxComp
      01.10.2016 20:46

      И теперь мне понятно, почему обсуждение этой проблемы обострилось только в середине 2015 года.
      Я задавался вопросом, если Андроид 4.4 вышла 31 октября 2013 года, почему тогда столько времени все как-то жили с ограничением на запись на sd, а потом вдруг стали бурно обсуждать?

      Я провёл собственное расследование.

      Оказывается был осуществлён незаметный переход от приложения Google+ Photos на отдельное приложение Google Photos. Названия очень похожи, а приложения разные. Но кому какое дело, пока всё работает?
      Первое сообщение на официальном форуме google датируется 17.08.2015, где человек говорит, что проблемы начались несколько недель назад:

      Since a few weeks google photos started to say that can not delete photos from device

      то есть, примерно с 3 августа.

      А Google в своём блоге объявляли, что с первого августа 2015 года они отключат Google+ Photos.

      Всё сходится.

      В google+ photos теперь предлагается установить google photos. Но google+ photos было системным приложением и могло удалять с sd, а приложение google photos, которое устанавливает пользователь, системным не является и на него распространяются ограничения на запись.


  1. LinuxComp
    02.10.2016 17:56

    Поделюсь ещё некоторыми моими исследованиями:

    1) Есть ли google api для Google Photos — отпадает
    Я подумал, а нельзя ли создать workaround application, которое бы получало доступ как к фоткам юзера, так и к sd карте по варианту «не баг, а фича». По аналогии с YouTube Data API, поискал есть ли что-то подобное для GP? Нашёл и обрадовался.
    Да, в интернете нагуглилась информация по Google Photos API. Радовался я рано. Оказывается, это api предоставляет возможность пользоваться алгоритмами googe по распознаванию объектов на снимках, как это происходит в их приложении. Но никакого отношения к снимкам пользователя этот api не имеtт.

    2) Перед тем как проводить модификации gp, захотел проверить, получится ли вообще его потом запустить.
    Итак, я решил переподписать gp своим ключом и посмотреть, бедет ли google работать с таким приложением.
    Взял orig_gp.apk, удалил внутри него папку META-INF, переименовал в orig_gp_nometa.apk
    Установил jdk6, положил свой keystore в ~/.keystore и выполнил

    jarsigner -verbose -keystore ~/.keystore orig_gp_nometa.apk my_alias 
    

    Файл перезаписался, переименовал его в gp_resigned_unaligned.apk
    Нашёл утилиту zipalign (эта утилита должна находиться где-то в sdk, но я не докопался где она лежит, поэтому скачал бинарник из интернета).
    Выполнил
    ./zipalign -v 4 gp_resigned_unaligned.apk gp_resigned_aligned.apk
    

    Проверил на всякий случай корректность подписи на выровненном файле
    jarsigner -verify gp_resigned_aligned.apk
    

    Перенёс apk на смартфон, удалил настоящий gp (а то невозможно установить с другой подписью), устанавливаю переподписанный вариант.
    Запускаю — приложение остановлено.
    В логах мы видим

    E/AndroidRuntime: FATAL EXCEPTION: main
                                                 Process: com.google.android.apps.photos,
                                                 PID: 30383
                                                 java.lang.SecurityException: Signature check failed for
                                                 com.google.android.apps.photos
    

    И, заметьте, мы ещё даже не модифицировали приложение, только переподписали.

    Чтобы убедиться, что я всё делал правильно, решил попробовать переподписать какое-нибудь отдельное приложение. Взял coolreader.apk, проделал с ним все те же манипуляции, ставлю — всё прекрасно работает.

    Значит, я всё делал как надо, а проблема кроется в том, что кто-то ещё проверяет подпись на принадлежность гуглу. Это скорее всего какие-нибудь google services.

    3) Принцип работы OG Youtube
    Интересно, а если пакет проверяется на нетронутость, то как тогда модифицировали youtube? Решил разобраться как работает OG Youtube.
    Понятно, что ни у одного модифицированного apk нет подписи google. Как устанавливается мод?
    Есть три варианта.
    a) безрутовый
    ставится как другой пакет параллельно с настоящим youtube. Авторизация при помощи microg.
    б) рутовый простой
    удаляется системный youtube, ставится под видом гугловского пакета. Авторизация при помощи microg.
    в) рутовый xposed
    удаляется системный youtube, ставится под видом гугловского пакета. Авторизация при помощи настоящих google сервисов путём их обмана о том, что подпись принадлежит гуглу.

    В нашем случае интересны варианты а и б. Не удивляйтесь, что я указал рутовый вариант: у нас же gp не системное, мы его можем спокойно удалить, чтобы система позволила поставить пакет с иной подписью. Принципиально а и б ничем не отличаются, просто в одном случае это будет установленное рядом с настоящим приложение, а в другом — заменяющее настоящее.

    Тут самое главное.
    Представим, что мы кул-хакеры, всё уже декомпилировали, добавили функционал, собрали модифицированный пакет apk. Вопрос: а есть ли возможность авторизоваться таким приложением, используя microG?
    Может мне кто-то это подсказать?
    Это принципиальный вопрос, т.к. если ответ будет отрицательный, зачем вообще пытаться что-то ковырять? Хотя…
    Есть одна интересная вещь: в ресурсах приложения Google Photos есть easter_egg.png.

    Может кто-то подсказать, как узнать кто использует этот ресурс и можно ли как то выяснить, что за пасхалка используется в Google Фото? Гугл молчит.