Jak można pobrać (prywatne) dane z własnej aplikacji na Androida?


97

Próba ściągnięcia pojedynczego pliku przy użyciu

adb pull /data/data/com.corp.appName/files/myFile.txt myFile.txt

zawodzi z

failed to copy '/data/data/com.corp.appName/files/myFile.txt myFile.txt' to 'myFile.txt': Permission denied

pomimo tego debugowanie USB jest włączone na urządzeniu.

Możemy obejść problem archaiczną drogą

adb shell
run-as com.corp.appName
cat files/myFile.txt > myFile.txt

ale jest to nieporęczne dla więcej niż jednego pliku.

Jak mogę ściągnąć katalog /data/data/com.corp.appName/files do mojego MacBooka?

Robienie tego bezpośrednio lub przez tranzyt w `/ storage / sdcard0 / myDir (skąd mogę kontynuować transfer plików Android) jest w porządku.

Dodatkowy komentarz

Może to po prostu bieganie

adb backup  -f myFiles com.corp.appName

wygeneruje pliki, których szukam. W takim przypadku szukam sposobu na rozpakowanie / rozpakowanie powstałej kopii zapasowej!


5
Dopóki urządzenie nie jest zrootowane, po prostu nie możesz tego zrobić.
323go,

Mam nadzieję, że się mylisz, ale na wszelki wypadek przenieś swój komentarz, aby był odpowiedzią. Czy mógłbyś dodać jakieś odniesienie, aby potwierdzić, dlaczego tak myślisz? Chciałbym zapisać wszystkie niepotrzebne pliki, które zapisały błędne wersje mojego programu, aby upewnić się, że mój program, który jest bliżej wydania, z wdziękiem obsłuży wszystkie rodzaje plików wejściowych.
Calaf

1
Czy to oznacza, że ​​można chmodować katalog od world: - x do world: rx na tyle długo, aby móc pobrać pliki?
Calaf

1
@Knossos Niezależnie od tego, że jest to moja aplikacja, czy nie jest uzasadnione, aby użytkownicy mogli zapisywać kopię prywatnych danych przechowywanych przez aplikację na ich urządzeniach? W końcu dane przypuszczalnie należą do właściciela urządzenia, a nie do autora aplikacji.
Calaf

1
Problem polega na tym, jak odróżnić właściciela od złośliwej aplikacji / programu, próbując połączyć się z prywatnymi danymi aplikacji. (w którym mogą znajdować się dane osobowe użytkowników)
Knossos

Odpowiedzi:


101

adb backup zapisze archiwum specyficzne dla Androida:

adb backup  -f myAndroidBackup.ab  com.corp.appName

To archiwum można przekonwertować do formatu tar za pomocą:

dd if=myAndroidBackup.ab bs=4K iflag=skip_bytes skip=24 | openssl zlib -d > myAndroidBackup.tar

Odniesienie:

http://nelenkov.blogspot.ca/2012/06/unpacking-android-backups.html

Wyszukaj „Aktualizuj” pod tym linkiem.


Alternatywnie, użyj narzędzia do wyodrębniania kopii zapasowych systemu Android, aby wyodrębnić pliki z .abpliku kopii zapasowej systemu Android ( ).


5
bs=24 skip=1jest znacznie szybszy niż bs=1 skip=24(w moim systemie 38,6 MB / s vs 1,7 MB / s) :)
netvope

18
Alternatywa dla Pythona, gdzie openssl nie została skompilowana z zlib: dd if=data.ab bs=1 skip=24 | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" | tar -xvf -(z powyższego źródła)
OJFord,

6
Nigdy nie odniosłem sukcesu z ddpoleceniem na moim MacBooku w pracy. Zamiast tego używam java -jar ./abe.jar unpack data.ab data.tar. Możesz pobrać narzędzie abe ze strony sourceforge.net/projects/adbextractor/files/?source=navbar
Someone Somewhere.

3
Zauważyłem również, że musiałem wymusić zamknięcie aplikacji, której dane chcę zarchiwizować, w przeciwnym razie kopia zapasowa będzie pusta! (Android 4.4.2) Efekt jest taki sam, jak w przypadku manifestuandroid:allowBackup="false"
Someone Somewhere.

2
Nawet lepiej, bezpośrednio wypakuj pliki do lokalnego katalogu:dd if=myAndroidBackup.ab bs=24 skip=1 | openssl zlib -d | tar -x
mreichelt

50

Miałem ten sam problem, ale rozwiązałem go, wykonując następujące czynności:

$ adb shell
$ run-as {app-package-name}
$ cd /data/data/{app-package-name}
$ chmod 777 {file}
$ cp {file} /mnt/sdcard/

Po tym możesz biec

$ adb pull /mnt/sdcard/{file}

1
dzięki! musisz także użyć "cp -r", aby uczynić z niego kopię rekurencyjną. stackoverflow.com/questions/39961621/…
朱 西西

31

Oto, co zadziałało dla mnie:

adb -d shell "run-as com.example.test cat /data/data/com.example.test/databases/data.db" > data.db

Drukuję bazę danych bezpośrednio do pliku lokalnego.


3
Dokładnie to polecenie spowodowało uszkodzenie mojego pliku db. Ale udało mi się działać z następującymi krokami: ------ adb shell ------ wewnątrz powłoki run-as com.example.test ------ wewnątrz powłoki cat ...db > /mnt/sdcard/file.db------ adb pull /mnt/sdcard/file.db .------ koniec (przepraszam, łamanie linii nie działa)
Kirill Oficerov

@KirillOficerov byłoby dobrze, gdyby te polecenia można było zapisać w jednej linii
emen

Świetne, gdy potrzebujesz 1 pliku. Używam tego do bazy danych. W obliczu sytuacji, w której potrzebuję wielu plików.
Dave Thomas,

Z jakiegoś powodu używanie adb shellnie zadziałało dla mnie, ale zastosowanie tej odpowiedzi i użycie adb exec-outjej zadziałało!
EpicPandaForce

21

W systemie MacOSX, łącząc odpowiedzi od Calafa i Ollie Forda, zadziałały następujące rozwiązania.

W wierszu poleceń (upewnij się, że adb jest na twojej ścieżce, mój był w ~ / Library / Android / sdk / platform-tools / adb) i po podłączeniu urządzenia z Androidem i trybie debugowania USB uruchom:

 adb backup -f backup com.mypackage.myapp

Twoje urządzenie z systemem Android poprosi Cię o pozwolenie na wykonanie kopii zapasowej danych. Wybierz „ZAPISZ MOJE DANE”

Poczekaj chwilę.

Kopia zapasowa pliku pojawi się w katalogu, w którym uruchomiłeś adb.

Teraz biegnij:

dd if=backup bs=1 skip=24 | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" > backup.tar

Teraz masz plik backup.tar, który możesz rozpakować w następujący sposób:

 tar xvf backup.tar

Zobacz wszystkie pliki zapisane w aplikacji.


Twoja wersja na Maca działa! UWAGA: zarówno kroki, jak adb backupi ddkroki konwersji tar, nie zapewniają statusu podczas pracy i mogą zająć kilka minut, jeśli masz dużo danych. Bądź cierpliwy!
MechEthan

2
Otrzymuję: "zlib.error: Błąd -3 podczas dekompresji danych: nieprawidłowe sprawdzenie nagłówka" Moja kopia zapasowa prosi jednak o hasło do zaszyfrowania. Ta metoda w Pythonie nie wymaga podania hasła do odszyfrowania kopii zapasowej. Plik abe.jar w komentarzach w powyższym przykładzie prosi o hasło, ale nie otrzymałem wszystkich plików po rozpakowaniu przy użyciu tej metody.
Dave Thomas,

Moja druga próba z abe.jar na zaszyfrowanej kopii zapasowej zadziałała.
Dave Thomas,

7

Nowsze wersje Android Studio zawierają Eksplorator plików urządzeń, który uważam za przydatną metodę GUI do pobierania plików z mojego deweloperskiego Nexusa 7.

Musisz upewnić się, że masz włączone debugowanie USB na urządzeniu

  1. Kliknij Widok> Okna narzędzi> Eksplorator plików urządzenia lub kliknij przycisk Eksplorator plików urządzenia na pasku narzędzi, aby otworzyć Eksplorator plików urządzenia.
  2. Wybierz urządzenie z listy rozwijanej.
  3. Wejdź w interakcję z zawartością urządzenia w oknie eksploratora plików. Kliknij prawym przyciskiem myszy plik lub katalog, aby utworzyć nowy plik lub katalog, zapisz wybrany plik lub katalog na komputerze, prześlij, usuń lub zsynchronizuj. Kliknij dwukrotnie plik, aby otworzyć go w Android Studio.

    Android Studio zapisuje otwierane w ten sposób pliki w katalogu tymczasowym poza Twoim projektem. Jeśli dokonasz modyfikacji w pliku otwartym za pomocą Eksploratora plików urządzenia i chcesz zapisać zmiany z powrotem na urządzeniu, musisz ręcznie przesłać zmodyfikowaną wersję pliku do urządzenia.

przeglądarka plików

Pełna dokumentacja


6

Możesz użyć tego skryptu powłoki poniżej. Jest w stanie również pobierać pliki z pamięci podręcznej aplikacji, a nie tak jak to adb backupnarzędzie:

#!/bin/sh

if [ -z "$1" ]; then 
    echo "Sorry script requires an argument for the file you want to pull."
    exit 1
fi

adb shell "run-as com.corp.appName cat '/data/data/com.corp.appNamepp/$1' > '/sdcard/$1'"
adb pull "/sdcard/$1"
adb shell "rm '/sdcard/$1'"

Następnie możesz go użyć w ten sposób:

./pull.sh files/myFile.txt
./pull.sh cache/someCachedData.txt

10
Najlepsze jest to, że nie podajesz argumentów, a potem je rm /sdcard/zastępujesz, na szczęście tak nie jest -rf.
TWiStErRob

3
Możesz po prostu przenieść się bezpośrednio do pliku na hoście: "powłoka adb run-as com.cokolwiek.Fnord cat /data/data/com.whokolwiek.Fnord/databases/logging.db> / tmp / foo" (gdzie / tmp / foo to plik na maszynie hosta, a nie na urządzeniu z Androidem)
James Moore

Właśnie teraz zdałem sobie sprawę, że @ dave-thomas naprawił problem jakiś czas temu. Usuwam mój głos przeciw.
Don Hatch

Lub nie :-( "Twój głos jest teraz zablokowany, chyba że ta odpowiedź zostanie zmieniona."
Don Hatch

TBH Nie rozumiem tego zamieszania. (Oryginalny) skrypt nigdy nie usunąłby katalogu (brak przełącznika -rf), chyba że byłby pusty. Nie sprawdzałem, ale nawet jeśli katalog jest pusty, wątpię, czy skrypt usuwa katalog, ponieważ jest to punkt montowania. Scenariusz wyglądał niebezpiecznie, ale nigdy nie był ...
Tamas

5

Jeśli używasz komputera Mac i telefonu Samsung, musisz to zrobić (ponieważ run-as nie działa na Samsungu i zlib nie działa na Macu)

  1. Zrób kopię zapasową katalogu danych aplikacji adb backup -f /Users/username/Desktop/data.ab com.example

  2. Zostaniesz poproszony o podanie hasła do zaszyfrowania w telefonie, nie wprowadzaj żadnego. Po prostu dotknij „Utwórz kopię zapasową moich danych”. Zobacz Jak wziąć BackUp?

  3. Po pomyślnym utworzeniu kopii zapasowej zobaczysz data.abplik na pulpicie. Teraz musimy przekonwertować to na tarformat.

  4. Użyj do tego programu Android Backup Extractor . Pobierz | Kod źródłowy

  5. Pobierz go, a zobaczysz abe.jarplik. Dodaj to do zmiennej PATH.

  6. Wykonaj to, aby wygenerować plik tar :java -jar abe.jar unpack /Users/username/Desktop/data.ab /Users/username/Desktop/data.tar

  7. Wyodrębnij plik data.tar , aby uzyskać dostęp do wszystkich plików


2
Postępowałem dokładnie zgodnie z tym i po data.tarprostu wyodrębniłem do data.tar.cpgz@henry
user-

2

Ta odpowiedź jest oparta na moim doświadczeniu z innymi odpowiedziami i komentarzami w odpowiedziach. Mam nadzieję, że pomogę komuś w podobnej sytuacji.

Robię to na OSX przez terminal.

Wcześniej odpowiedź Viniciusa Avellara działała dla mnie świetnie. Tylko przez większość czasu potrzebowałem bazy danych z urządzenia z aplikacji do debugowania.

Dzisiaj miałem przypadek użycia, w którym potrzebowałem wielu prywatnych plików . Skończyło się na dwóch rozwiązaniach, które działały dobrze w tym przypadku.

  1. Użyj zaakceptowanej odpowiedzi wraz z konkretnymi komentarzami Someone Somewhere OSX. Utwórz kopię zapasową i użyj rozwiązania innej firmy, sourceforge.net/projects/adbextractor/files/?source=navbar, aby rozpakować do formatu tar. O moim doświadczeniu z tym rozwiązaniem napiszę więcej na dole odpowiedzi. Przewiń w dół, jeśli tego właśnie szukasz.

  2. Szybsze rozwiązanie, z którym się zdecydowałem. Stworzyłem skrypt do pobierania wielu plików, podobnie jak odpowiedź Tamasa. Jestem w stanie to zrobić w ten sposób, ponieważ moja aplikacja jest aplikacją do debugowania i mam dostęp do działania na moim urządzeniu. Jeśli nie masz dostępu do uruchamiania, ta metoda nie zadziała na OSX.

Oto mój skrypt do pobierania wielu prywatnych plików, którymi podzielę się z Tobą, czytelnikiem, który również bada to niesamowite pytanie;):

#!/bin/bash
#
# Strict mode: http://redsymbol.net/articles/unofficial-bash-strict-mode/
set -euo pipefail
IFS=$'\n\t'

# 
# Usage: script -f fileToPull -p packageName
# 

# This script is for pulling private files from an Android device
# using run-as. Note: not all devices have run-as access, and
# application must be a debug version for run-as to work.
# 
# If run-as is deactivated on your device use one of the
# alternative methods here:
# http://stackoverflow.com/questions/15558353/how-can-one-pull-the-private-data-of-ones-own-android-app
# 
# If you have encrypted backup files use:
# sourceforge.net/projects/adbextractor/files/?source=navbar 
# From comments in the accepted answer in the above SO question
# 
# If your files aren't encrypted use the accepted answer 
# ( see comments and other answers for OSX compatibility )
# 
# This script is open to expansions to allow selecting 
# device used. Currently first selected device from
# adb shell will be used.

#Check we have one connected device
adb devices -l | grep -e 'device\b' > /dev/null

if [ $? -gt 0 ]; then
    echo "No device connected to adb."
    exit 1
fi

# Set filename or directory to pull from device
# Set package name we will run as
while getopts f:p: opt; do
    case $opt in
        f)
            fileToPull=$OPTARG
            ;;
        p)
            packageName=$OPTARG
            ;;
    esac
done;

# Block file arg from being blank
if [ -z "$fileToPull" ]; then
    echo "Please specify file or folder to pull with -f argument"
    exit 1
fi

# Block package name arg from being blank
if [ -z "$packageName" ]; then
    echo "Please specify package name to run as when pulling file"
    exit 1
fi

# Check package exists
adb shell pm list packages | grep "$packageName" > /dev/null
if [ $? -gt 0 ]; then
    echo "Package name $packageName does not exist on device"
    exit 1
fi

# Check file exists and has permission with run-as
fileCheck=`adb shell "run-as $packageName ls $fileToPull"`
if [[ $fileCheck =~ "Permission denied" ]] || [[ $fileCheck =~ "No such file or directory" ]]; then
    echo "Error: $fileCheck"
    echo "With file -> $fileToPull"
    exit 1
fi

# Function to pull private file
#
# param 1 = package name
# param 2 = file to pull
# param 3 = output file
function pull_private_file () {

    mkdir -p `dirname $3`

    echo -e "\033[0;35m***" >&2
    echo -e "\033[0;36m Coping file $2 -> $3" >&2
    echo -e "\033[0;35m***\033[0m" >&2

    adb shell "run-as $1 cat $2" > $3
}

# Check if a file is a directory
# 
# param 1 = directory to check
function is_file_dir() {

    adb shell "if [ -d \"$1\" ]; then echo TRUE; fi"
}

# Check if a file is a symbolic link
# 
# param 1 = directory to check
function is_file_symlink() {

    adb shell "if [ -L \"$1\" ]; then echo TRUE; fi"
}

# recursively pull files from device connected to adb
# 
# param 1 = package name
# param 2 = file to pull
# param 3 = output file
function recurse_pull_private_files() {

    is_dir=`is_file_dir "$2"`
    is_symlink=`is_file_symlink "$2"`

    if [ -n "$is_dir" ]; then

        files=`adb shell "run-as $1 ls \"$2\""`

        # Handle the case where directory is a symbolic link
        if [ -n "$is_symlink" ]; then
            correctPath=`adb shell "run-as $1 ls -l \"$2\"" | sed 's/.*-> //' | tr -d '\r'`
            files=`adb shell "run-as $1 ls \"$correctPath\""`
        fi

        for i in $files; do

            # Android adds nasty carriage return that screws with bash vars
            # This removes it. Otherwise weird behavior happens
            fileName=`echo "$i" | tr -d '\r'` 

            nextFile="$2/$fileName"
            nextOutput="$3/$fileName"
            recurse_pull_private_files "$1" "$nextFile" "$nextOutput"
        done
    else

        pull_private_file "$1" "$2" "$3"
    fi
}

recurse_pull_private_files "$packageName" "$fileToPull" "`basename "$fileToPull"`"

Streszczenie: https://gist.github.com/davethomas11/6c88f92c6221ffe6bc26de7335107dd4


Wróć do metody 1 , odszyfrowanie kopii zapasowej za pomocą Android Backup Extractor

Oto kroki, które podjąłem na komputerze Mac, i napotkane problemy:

Najpierw ustawiłem kopię zapasową w kolejce (i ustawiłem hasło do zaszyfrowania kopii zapasowej, wymagało tego moje urządzenie):

adb backup -f myAndroidBackup.ab  com.corp.appName

Po drugie pobrałem tylko abe.jar stąd: https://sourceforge.net/projects/adbextractor/files/abe.jar/download

Następnie pobiegłem:

java -jar ./abe.jar unpack myAndroidBackup.ab myAndroidBackup.tar

W tym momencie pojawił się komunikat o błędzie. Ponieważ moje archiwum jest zaszyfrowane, java wyświetlił mi błąd, którego potrzebowałem, aby zainstalować niektóre biblioteki strategii bezpieczeństwa.

  • Poszedłem więc do http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html i pobrałem pliki jars z polityką bezpieczeństwa, których potrzebowałem. Teraz w moim przypadku instrukcje instalacji mówiły mi o złej lokalizacji do umieszczenia plików jar. Mówi, że właściwa lokalizacja to <java-home> / lib / security . Umieściłem je tam jako pierwszy i nadal otrzymuję komunikat o błędzie. Sprawdziłem więc i na moim Macu z Javą 1.8 poprawnym miejscem do ich umieszczenia było: <java-home> / jre / lib / security . Zrobiłem kopię zapasową oryginalnych słoików polis i umieściłem je tam. Vola Udało mi się wprowadzić hasło w pliku abe.jar i odszyfrować do pliku tar.

Wreszcie po prostu pobiegłem ( po ponownym uruchomieniu poprzedniego polecenia )

tar xvf myAndroidBackup.tar

Teraz ważne jest, aby pamiętać, że jeśli możesz po prostu biegać jako kot, jest to znacznie szybsze. Po pierwsze, dostajesz tylko żądane pliki, a nie całą aplikację. Po drugie, im więcej plików (+ dla mnie szyfrowanie), tym wolniejszy jest transfer. Tak więc wiedza o tym, jak zrobić to w ten sposób, jest ważna, jeśli nie masz uruchomionego jako na OSX, ale skrypt powinien być najpierw gotowy do debugowania aplikacji.

Pamiętaj, że właśnie napisałem go dzisiaj i przetestowałem kilka razy, więc informuj mnie o wszelkich błędach!


1
Dzięki Twojej odpowiedzi z metodą nr 1 mogłem uzyskać i zbadać kopię zapasową pakietu z aplikacji docelowej debugowania zainstalowanej na nierootowanym urządzeniu produkcyjnym, ale kopia zapasowa zawiera tylko plik manifestu. Metodą nr 2 pobrałem wszystkie dane aplikacji, ale pliki binarne (tj. Pliki SQLite) są nieczytelne. Dodaję rozwiązanie oparte na Twoim skrypcie, które działało dla mnie.
Paolone,

1

Po ustawieniu odpowiednich uprawnień poprzez dodanie następującego kodu:

File myFile = ...;
myFile.setReadable(true, false); // readable, not only for the owner

adb pull działa zgodnie z życzeniem.

zobacz File.setReadable ()


1
Zmiana uprawnień podczas debugowania jest w porządku, ale w pewnym momencie w pobliżu wydania może to zniweczyć ochronę oferowaną domyślnie (aby uniemożliwić innym aplikacjom dostęp / zepsucie plików). Dlatego bardziej pożądany jest sposób, aby programiści mieli dostęp do plików, nawet jeśli są one tylko do odczytu / zapisu przez użytkownika.
Calaf

1

Zaczynając od skryptu Dave Thomas, byłem w stanie napisać własne rozwiązanie, aby rozwiązać 2 problemy:

  1. moja kopia zapasowa zawierała tylko plik manifestu
  2. Pliki binarne otrzymane z Dave Thomasem były nieczytelne

To jest mój skrypt, który kopiuje dane aplikacji do sdcard, a następnie je pobiera

#Check we have one connected device
adb devices -l | grep -e 'device\b' > /dev/null

if [ $? -gt 0 ]; then
    echo "No device connected to adb."
    exit 1
fi

# Set filename or directory to pull from device
# Set package name we will run as
while getopts f:p: opt; do
    case $opt in
        f)
            fileToPull=$OPTARG
            ;;
        p)
            packageName=$OPTARG
            ;;
    esac
done;

# Block package name arg from being blank
if [ -z "$packageName" ]; then
    echo "Please specify package name to run as when pulling file"
    exit 1
fi

# Check package exists
adb shell pm list packages | grep "$packageName" > /dev/null
if [ $? -gt 0 ]; then
    echo "Package name $packageName does not exist on device"
    exit 1
fi

    adb shell "run-as $packageName cp -r /data/data/$packageName/ /sdcard/$packageName"
    adb pull /sdcard/$packageName
    adb shell rm -rf /sdcard/$packageName

1

Podobnie jak w przypadku odpowiedzi Tamasa , tutaj jest jedna linijka dla Mac OS X, aby pobrać wszystkie pliki aplikacji z your.app.idurządzenia i zapisać je (w tym przypadku) ~/Desktop/your.app.id:

(
    id=your.app.id &&
    dest=~/Desktop &&
    adb shell "run-as $id cp -r /data/data/$id /sdcard" &&
    adb -d pull "/sdcard/$id" "$dest" &&
    if [ -n "$id" ]; then adb shell "rm -rf /sdcard/$id"; fi
)
  • Wyklucz -d do ściągnięcia z emulatora
  • Nie tępi zmiennych sesji
  • Możesz wkleić cały blok do Terminal.app (lub w razie potrzeby usunąć znaki nowej linii)

0

Kopia zapasowa danych gry za pomocą apk . Nougat Oneplus 2.

**adb backup "-apk com.nekki.shadowfight" -f "c:\myapk\samsung2.ab"**

adb backup -f myapp.ab -apk com.myapp # backup on one device adb restore myapp.ab # restore to the same or any other device
Steven Linn,

0

Czy to oznacza, że ​​można chmodować katalog od world: - x do world: rx na tyle długo, aby móc pobrać pliki?

Tak, dokładnie. Co dziwne, potrzebujesz również pliku, aby xustawić bit. (przynajmniej na Androidzie 2.3)

chmod 755 cały czas działał, aby skopiować plik (ale później powinieneś cofnąć uprawnienia, jeśli planujesz nadal korzystać z urządzenia).


0

możesz to zrobić:

adb pull / storage / emulated / 0 / Android / data //


2
Nie zrozum mnie źle, ale czy dobrze przeczytałeś pytanie? OP prosi o
pobranie
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.