Alter.Org.UA
 << Back Home EN en   Donate Donate

Android Gallery don't see images uploaded via GVFS MTP

Досл╕дження

#сисадм╕нське побутове П╕в-дня намагався залити фото з камери на телефон. Не через GUI, а файловими операц╕ями. Воно ж доступне. Фото залива╓ться, ╖х видно в File Manager на телефон╕, *╕нколи* вони *частково* з'являються у пов╕домленн╕ "Found new images" в Gallery. ╤ майже н╕коли в загальный галере╖ чи в розд╕л╕ Download, куди я ╖х ╕ заливав. Майже так само з Instagram. То бачить (р╕дко), то не бачить. Повний розсинхрон всього.

Зл╕ ╕ стрьомн╕ методи з форум╕в з використанням adb ╕ в╕дладки - також не мають особливого усп╕ху. Купа ут╕л╕т типу Rescan - аналог╕чно. Нав╕ть зм╕г досягнути ситуац╕╖, коли файла нема, а залити з таким самим ╕менем не да╓ (як з'ясувалось - проблема на сторон╕ ноута, перезавантажив - ╕ все ок) А через GUI - знов норм.

Ок, не зря ж debugger п╕дключав... Врубив максимальний р╕вень лог╕в. ╤ виявля╓ться, що там де ок - одразу в╕дбува╓ться ╕ндексац╕я в╕дпов╕дно до типу файла, а там де н╕ - помилка unsupported type.

09-29 14:44:41.838 19668 25267 D MtpServer: path: /storage/emulated/0/Download/DSCN1429.JPG parent: 17 storageID: 00010001
09-29 14:44:41.864 19668 25267 D skia    : --- Failed to create image decoder with message 'unimplemented'
vs
09-29 14:49:25.575 19668 25267 D MtpServer: path: /storage/emulated/0/Download/DSCN1429.JPG parent: 17 storageID: 00010001
09-29 14:49:25.688 19668 25267 W ExifInterface: Skip the tag entry since tag number is not defined: 34864
09-29 14:49:25.688 19668 25267 W ExifInterface: Skip the tag entry since tag number is not defined: 2
09-29 14:49:25.688 19668 25267 W ExifInterface: Stop reading file since a wrong offset may cause an infinite loop: 0
09-29 14:49:25.689 19668 25267 I chatty  : uid=10031(com.android.providers.media) MtpServer identical 2 lines
09-29 14:49:25.689 19668 25267 W ExifInterface: Stop reading file since a wrong offset may cause an infinite loop: 0

Пошук, дореч╕, да╓ мало ц╕нного, кр╕м того, що проблема десь в б╕бл╕отеках... ╤ що ╓ такий android-file-transfer, ╓ в пакетах Linux, дореч╕. Типу FTP, т╕льки для MTP, для андро╕д╕в. ╤ в╕н працю╓ нормально ! ╤ коректно в╕дбува╓ться ╕ндексац╕я . То на ньому ╕ зробив соб╕ скрипт для автопереносу фоток.

От сиджу тепер ╕ пор╕внюю libmtp, що використову╓ться gvfs'ом ╕ android-file-transfer, в якого власна реал╕зац╕я. ╤ схоже, ще пот╕м в сам gvfs доведеться л╕зти...

PS. Ну що, подивився в GVFS.... Якщо файл просто коп╕ю╓ться як на файлову систему (/run/user/xxxx/gvfs/...), то йому признача╓ться тип unknown, коли в╕н створю╓ться. Хоча, нав╕ить сам libmtp ма╓ ф-ц╕ю отримання типу з назви. Правда, лише в прикладах. В продакшн не п╕шло. ╤ зв╕сно, android не зна╓ що з ним робити. А от якщо через GUI - то в комплект╕ йде mime type... Наприклад, image/jpeg... Що береться з ориг╕нала, який ми коп╕ю╓мо. От шоб вони були здоров╕...

Indexed upload

#!/bin.sh

#requires 'sudo apt install android-file-transfer'

#ANDROID_MNT=~/mnt/mi7
# Default Target dir on Android
ANDROID_DIR=${1:-Download}
CAMERA_DIR=${2:-DCIM/100NIKON}


# Android device name from gio mount -l
# or gvfs-mount -l
#MTP=mtp://Xiaomi_SDM660-MTP__SN%3AE39C9282_fb7f7b7/


############################################################
# actually symlink to /run/user/xxx/gvfs/Xiaomi_SDM660-MTP__SN%3Axxxxxxxx_zzzzzzzz/Internal Storage/
# ${XDG_RUNTIME_DIR}/gvfs/Xiaomi_SDM660-MTP__SN%3Axxxxxxxx_zzzzzzzz/Internal Storage/
# ls ${XDG_RUNTIME_DIR}/gvfs | grep `gio mount -l|grep mtp|awk '{print $6;}'|sed -e 's/mtp:\/\///' -e 's/\///'`
a=`which gio`
if [ "x$a" = "x" ] ; then
GIO_MOUNT="gvfs-mount"
else
GIO_MOUNT="gio mount"
fi

#MTP=`gio mount -l|grep mtp|awk '{print $6;}'`
echo ${GIO_MOUNT} -l|grep mtp|awk '{print $6;}'
MTP=`${GIO_MOUNT} -l|grep mtp|awk '{print $6;}'`
echo ${MTP}
if [ "x$MTP" = "x" ] ; then
echo "Android device not connected via MTP"
exit
fi
#A_DEV_MTP_TPL=`echo ${MTP}|sed -e 's/mtp:\/\///' -e 's/\///'`
#echo ${A_DEV_MTP_TPL}
#A_DEV_MTP_DIR=`ls ${XDG_RUNTIME_DIR}/gvfs/ |grep ${A_DEV_MTP_TPL}`
A_DEV_MTP_DIR=`ls ${XDG_RUNTIME_DIR}/gvfs/ |grep mtp:`
ANDROID_MNT="${XDG_RUNTIME_DIR}/gvfs/${A_DEV_MTP_DIR}/"

IStor=`ls -A ${ANDROID_MNT}`
ANDROID_MNT="${ANDROID_MNT}/${IStor}"

echo ${ANDROID_MNT}

# Camera's SD card mountpoint
#SD_MNT=/media/alter/FC30-3DA9
SD_MNT=`mount |grep /media|grep vfat|awk '{print $3;}'`
SD_DEV=`mount |grep /media|grep vfat|awk '{print $1;}'`
# Source dir on Camera's SD
SD=${SD_MNT}/${CAMERA_DIR}

#echo ${ANDROID_MNT}
#ls ${ANDROID_MNT}

FLIST=/var/tmp/android.files.txt
ANDROID=${ANDROID_MNT}/${ANDROID_DIR}
echo ${ANDROID}

if [ ! -d "${SD}" ] ; then
echo "SD card not mounted"
exit
fi

a=`which aft-mtp-cli`
if [ "x$a" = "x" ] ; then
echo "missing package, run"
echo " sudo apt install android-file-transfer"
exit
fi

if [ ! -d "${ANDROID}" ] ; then
echo "Mount Android"
#gio mount ${MTP}
${GIO_MOUNT} ${MTP}
do_mount=0
else
do_mount=1
fi

if [ ! -d "${ANDROID}" ] ; then
echo "Android device not mounted"
exit
fi

#ls "${ANDROID}"
ls "${ANDROID}" | awk '{print "/" $1;}' > ${FLIST}

echo "Unmount Android"
#gio mount -u ${MTP}
${GIO_MOUNT} -u ${MTP}
if [ -d "${ANDROID}" ] ; then
echo "Android device is busy, can't unmount"
exit
fi

echo "" > ${FLIST}.aft
#echo "cd /" >> ${FLIST}.aft
#echo "cd \"${IStor}\"" >> ${FLIST}.aft # we are already there with aft-mtp-cli
echo "cd \"${ANDROID_DIR}\"" >> ${FLIST}.aft

#echo "find ${SD} -ctime -60 -type f | grep -v -f ${FLIST} )"
for FN in `find ${SD} -ctime -60 -type f | grep -v -f ${FLIST} )`; do
#adb shell am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d "file:///mnt/sdcard/${ANDROID_DIR}/${FN}"
#cp -v -u "${FN}" ${ANDROID}
#adb shell am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d "file:///mnt/sdcard/${ANDROID_DIR}/${FN}"
echo "put \"${FN}\"" >> ${FLIST}.aft
done

cat ${FLIST}.aft
aft-mtp-cli -f ${FLIST}.aft > /dev/null

if [ "$do_mount" -eq 1 ] ; then
echo "Mount back"
#gio mount ${MTP}
${GIO_MOUNT} ${MTP}
fi

${GIO_MOUNT} -u ${SD_MNT}
#sudo umount -f ${SD_MNT}
#sudo fsck -y ${SD_DEV}
#sudo sync ${SD_DEV}

#CMD="for ANDROID_MEDIA in \$(find /mnt/sdcard/${ANDROID_DIR}/ -ctime -1 -type f | sed '\''s/ /\\*/g'\\''); do am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d "\${ANDROID_MEDIA}"; done"
#echo ${CMD}
##adb shell ' for ANDROID_MEDIA in $(find /mnt/sdcard/${ANDROID_DIR}/ -ctime -1 -type f | sed '\''s/ /\*/g'\''); do am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d "${ANDROID_MEDIA}"; done '
#echo "adb shell '${CMD}'" > ${FLIST}.sh
#cat ${FLIST}.sh
#. ${FLIST}.sh

sync_photos.sh

Technical, GVFS MTP

If image files are written to Android device via fuse mount point, they are not indexed correctly. They are not visible in gallery and other apps, however file managers can see them. Then can also be selected directly, but not with Gallery. Some tricks with manual indexing help. If image files are sent to Android phone via GUI, they immediately appear in Gallery and are visible for all apps.

The problem is caused by mtpfile->filetype = LIBMTP_FILETYPE_UNKNOWN in gvfs/daemon/gvfsbackendmtp.c, do_create() It prevents indexer from handling new files correctly.

Correct indexing happens when sending via GUI (Nautilus) which use do_push() with explicitly specified mtpfile->filetype derived from mime type of source file.

Other tools those upload files correctly and examples in libmtp set mtpfile->filetype according to filename/extension. It would be great to implement such mechanism in GVFS MTP, see patch below.

Patch: mtp_ftype.patch

2022.09.29


См. также


FB or mail alterX@alter.org.ua (remove X)   Share
Автор: Alter (Александр А. Телятников) Сервер: Apache+PHP под FBSD © 2002-2024