I have a SQLite Database on my Android Device (My own App). Now i want to see the SQLite Database on my Computer.
Is there any solution ( easy way ) to get the Database without root rights and without a SD-Card on my Computer?
I tried to google it but i can't find any solution for this problem....
Edit: I'm using not the Emulator ( need the Camera on my Device).
if phone is not rooted you cant access directly your DB, but you can copy it to download folder, then, copy to PC
public static void copyAppDbToDownloadFolder(Activity ctx) throws IOException {
File backupDB = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
"databse_name.db"); // for example "my_data_backup.db"
File currentDB = getApplicationContext().getDatabasePath("databasename.db");
if (currentDB.exists()) {
FileChannel src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
}
}
This method worked for my unrooted device.
# check if your device connected
adb devices
adb shell
run-as your.package.name
chmod 777 databases/your.database.name
exit
cp /data/data/your.package.name/your.database.name /mnt/sdcard/
exit
adb pull /mnt/sdcard/your.database.name
If you are saving Sqlite DB in default location , you can find the same in path like following
/data/data/com.dev.myapplication/databases/mydb.db
You can find the same using Android Device Monitor, through which you can navigate to both internal and external memory.
Once you find the database file, extract the same and save in desktop after connecting through USB cable. You can use option "Pull a file from device"
Once you have extracted file to desktop, use any tools similar to Mozilla Firefox SQLite viewer to view database.
Related
I have a Custom Launcher .apk that I ADB Sideload. I can simply copy the .apk into /system/app or /system/priv-app, set the appropriate permissions (rw-r-r, root:root) and then do a reboot. That's it. The App is considered a System-App.
adb root
adb push <path/file.apk> /system/app/
adb shell
chmod 644 /system/app/HelloWorld.apk
reboot
The App is a "System-App" and should remain one after updating. How can I update it without using Google Play Store? It is a KIOSK Application and it should be updatable from the APP itself.
Android kiosks are customer facing Android devices that serve a single purpose by running only a single app.
What are my Options here?/What I have already found
Can I just install .apk programmatically from within my App? (Will it still be installed inside /System/app?)
Do I have to use over-the-air (OTA) updates?
OTA updates are designed to upgrade the underlying operating system, the read-only apps installed on the system partition.
What other Options do I have?
Android:
minSdkVersion: 29
targetSdkVersion: 31
The app can't update itself from within itself. You would need to create a separate updater app, and put it on the system partition as well.
That updater app can use this technique, but unless the device is rooted, it'll prompt the user to allow app installs from your updater app.
And yes, you could also set up OTA updates, but that assumes that you actually have the signing keys for the OS on that device, and I think it's way more complex that just creating a separate updater app
Conclusion
It is possible to Update a System App with the PackageInstaller or Intent Method IF it was firstly installed as a System App. Here is everything I tried and a full overview on all Methods to install an apk.
Approach
My first goal was to find all possible ways on how to install .apks programmatically on android. The most popular method was the Intent method which is basically deprecated starting from API 21 followed by the PackageInstaller , using the shell method which requires super user (root) permissions or the OTA Updates. I quickly describe all methods and explain some pros and cons.
Methods
1. Package Installer API
(from api 21 recommended to use from api 29)
Summary: pros and cons
still considered a System App with all System Permissions
the app will no longer be under the /system/ path (after updating) since it is a read-only storage under Android
APKs must have the exact same package name, version code, and signing
certificates
app must already be a system app, only then updating and keeping System Permissions is possible.
it is possible to update within the .apk itself or from another .apk doesn't matter (we are basically an AppStore)
PackageInstaller is designed for more complex scenarios,
including dealing with split APKs, where a single app might require more
than one APK to completely install. As a result, it has a convoluted
API, to go along with the typical skimpy documentation. Keeping track of version etc is no problem unlike with the Intent method.
Source Code, Tutorial used
PackageInstaller Tutorial
See Source Code Example here
PackageInstaller API Documentation
My Approach and Conclusion
I first checked if my app is correctly installed as a /system application
package:/system/app/AndroidCarHmi.apk=com.crossware.androidcarhmi
I used AppInstaller choosed new .apk and updated the System App
After PackageInstaller Update( inside /data/ )
package:/data/app/com.crossware.androidcarhmi-7eF4dQkhk2iA0OeDt0kXyA==/base.apk=com.crossware.androidcarhmi
After restart (Still Considered a System App)
package:/data/app/com.crossware.androidcarhmi-7eF4dQkhk2iA0OeDt0kXyA==/base.apk=com.crossware.androidcarhmi
After Research I found that it doesn't have to be inside the system directories for android to consider it a system app SOURCES:
1
see first comment on answer
3)
I tried to confirm it myself if it still is a System App using ADB command list with parameter -s which only prints System Apps. (Conclusion ADB itself still considers it a SystemApp)
//List all System Packages with location
adb shell pm list packages -s -f
Printing a dumpsys of my apk package and check what permissions are granted.
adb shell dumpsys package my.package.name
ADB itself considers it a System App.
dumpsys.txt shows all permissions are still present.
2. Intent API
Same as above but for API smaller than 22
Add provider to AndroidManifest.xml
<application
........
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
.........
</application>
Create the missing provider_paths.xml file inside of res/xml/
provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="Download" path="/" />
</paths>
Choose the correct Provider path mapping. Example: If you are using Environment.getExternalStorageDirectory() the correct mapping is <external-path>
All Mappings
<files-path/> --> Context.getFilesDir()
<cache-path/> --> Context.getCacheDir()
<external-path/> --> Environment.getExternalStorageDirectory()
<external-files-path/> --> Context.getExternalFilesDir(String)
<external-cache-path/> --> Context.getExternalCacheDir()
<external-media-path/> --> Context.getExternalMediaDirs()
Make sure under App-> Permission -> Allow management of all files! TODO ask for permission programmatically!
Source Code (Java)
//Context context = MainActivity.this;
File download_directory = new File(Environment.getExternalStorageDirectory(), "Download");
File apk_file = new File(download_directory, "app-debug.apk");
String file_path_apk = apk_file.getPath();
try {
Uri apkUri = FileProvider.getUriForFile(MainActivity.this, MainActivity.this.getPackageName() + ".provider", apk_file);
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
intent.setData(apkUri);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
MainActivity.this.startActivity(intent);
} catch (IOException e) {
Log.e("Exception ", e.toString());
}
\pagebreak
3. Super User Application
requires Rooted Device and application has to receive Super User permissions
Give Application Super User Permissions and use Shell exactly as ADB sideloading
Example:
Process process = Runtime.getRuntime().exec("same command as adb just copy the .apk into /system/app set permissions to (rw-r-r) and reboot");
\pagebreak
4. ADB Sideloading
You can simply copy the .apk into /system/app or /system/priv-app, set the appropriate permissions (rw-r-r, root:root) and then do a reboot. That's it. The App is considered a System App.
//make the file system writable first--- Currently only for Emulator/test on physical device
emulator -writable-system #name_of_emulator
adb root
adb shell avbctl disable-verification
adb reboot
adb root
adb remount
adb push <Path\to\app.apk> /system/app
//set correct file permissions
adb shell
chmod 644 /system/app/<app.apk>
reboot
//Check if it is installed correctly
adb shell
cd system/app/
ls
4.5 System Updates/OTA Updates(Over-the-Air)
If you want to update a System App according to the Android Developer Site this is the correct way.
OTA updates are designed to upgrade the underlying operating system, the read-only apps installed on the system partition.
Needs signing keys for the Operating System on that device
A/B (Seamless) system update
Picture Source
See Source Code Example Here
Will you please help me with this problem.
I'm inserting values to my Sqlite database.
How can I check or view the inserted data.
Is there is any tool or other techniques to show the data ?
If You Want to Show a data on Log try below code :
for (Contact cn : contacts) {
String log = "Id: "+cn.getID()+" ,Name: " + cn.getName() + " ,Phone: " + cn.getPhoneNumber();
// Writing Contacts to log
Log.d("Name: ", log);
Other Way to show a database see below steps:
Go to Tools -> DDMS or click the Device Monitor icon next to SDK Manager in Tool bar.
Device Monitor window will open. In File Explorer tab, click data -> data -> your project name. After that your databases file will open. Click pull a file from device icon. Save the file using .db extension.
Open FireFox, Press Alt , Tools -> SQLiteManager.
Follow Database -> connect to Database -> browse your database file and click ok. Your SQLite file will opened now.
If you Download a database on DDMS then You download
DB.Browser.for.SQLite-3.10.1-win64
and put the database file on this software and you get the data.
NEW UPDATE OF DDMS
I'll Update My Answer becoz now a days Android Studio update in Android Studio 3.1 or up to other like now 3.2 in this Studio DDMS function is not available but Don't Worry i have another solution.
In your android Studio See right side Bottom Corner there is one Option like Device File Explorer Click on this button
After that you can see like below image is open on your screen :
Now select data -> data -> your project name. :)
I can't believe no one's mentioned this but what you are probably looking for is Android Debug Database
Works great with Android Room as well and you can view, edit tables and records.
Although you approved Cassius Clay's answer, if you need to process the raw data
root is not needed ( if it's not on the sdcard follow #Ankit 's answer )
import os
import sys
import subprocess
import sqlite3
import pandas as pd
arg_folder = sys.argv[1] # root folder to recursively search db files from
output_lines = subprocess.check_output(['adb', 'shell', ('ls -R %s' % arg_folder)]).decode('utf-8').splitlines()
db_files = []
current_folder = ''
for line in output_lines:
"""
Output example for 'ls -R /data/data':
/data/data/org.fdroid.fdroid/files/fdroid/repo/icons:
/data/data/org.fdroid.fdroid/shared_prefs:
apks-pending-install.xml
org.fdroid.fdroid_preferences.xml
/data/data/ru.meefik.busybox:
cache
files
lib
shared_prefs
if line contains '/' it's a directory, we want to extract the full path for '.db' files
"""
if line.__contains__('/'):
current_folder = line
elif line.endswith('.db'):
db_files.append('%s/%s' % (current_folder[:-1], line))
print("Listing databases..")
while True:
try:
for idx, full_path in enumerate(db_files):
print("{}) {}".format(idx + 1, full_path))
i = input("Enter database number : ")
db = db_files[int(i) - 1] # selected database
subprocess.check_output(['adb', 'pull', db]) # pulling the .db file from device to local
db = db.split('/')[-1] # "/data/data/com.app/folder/private.db".split('/')[-1] = private
conn = sqlite3.connect(db)
# getting list of current database tables
tables = conn.execute("SELECT name FROM sqlite_master WHERE type='table';").fetchall()
for table in tables:
table = table[0] # little fix, it comes as a tuple
print('%s%s' % (db[:-2], table))
with pd.option_context('display.width', 1000): # setting terminal width to view all table columns inline
print(pd.read_sql_query("SELECT * FROM %s" % table, conn)) # print table content
print('- ' * 50) # table print separator
# cleanup
if input('remove database file (from local) [y/N] ? ').lower() == 'y':
print('removing ', db)
os.remove(db)
# repeat
c = input("Press ENTER to continue or CTRL+C to Quit..")
except KeyboardInterrupt:
exit(0)
Here is a less human-friendly very-long-one-liner
read -p "enter root folder to recursively search db files from: " f;dbs=( $(adb shell ls -R $f |
while read line
do
line=$(echo $line | tr -d '\r')
if [[ "$line" =~ ^/.*:$ ]]
then
dir=${line%:}
elif [[ "$line" = "opendir failed" ]]
then
echo "$dir - permission denied"
else
if [[ "$dir" = "/" ]]; then dir=""; fi
echo "$dir/$line" | grep '\.db$'
fi
done)
);echo ${dbs[#]}; dbs+=(exit);select db in "${dbs[#]}"; do
[[ $db == exit ]] && break
echo "You have chosen $db"
adb pull $db
python -c 'import sqlite3;import pandas as pd;db=sqlite3.connect("'${db##*/}'");tables=db.cursor().execute("SELECT name FROM sqlite_master WHERE type=\"table\";").fetchall();print([pd.read_sql_query("SELECT * FROM %s" % t[0], db) for t in tables]);'
done
GIF because I'm too lazy to document
DDMS approach is not working in non rooted device
I follow How to check database on not rooted android device to import the Sqlite DB from device to PC.
Follow the given steps:
Open the terminal in Android Studio
Change default directory to your_path_to>SDK>platform-tools>
adb shell run-as [package] chmod 777 /data/data/[package]/databases/
adb shell run-as [package] chmod 777 /data/data/[package]/databases/[db_file_name]
adb shell run-as [package] cp /data/data/[package]/databases/[db_file_name] /sdcard/
adb pull /sdcard/[db_file_name]
4.Check the pulled SQLite DB in folder sdk>platform-tools
Now you can use any SQLite Viewer to view the pulled database.
Note: Two permissions are required in Manifest file otherwise data will not copied in pulled DB
android.permission.WRITE_EXTERNAL_STORAGE
android.permission.READ_EXTERNAL_STORAGE
You can add,edit,check all your DB tables data including your sharedpreferences data with this library (Database debug database)
Follow this link to install.
All you need to do is to just put the dependency, compile and run the program ,you will find a link like (your_package_name D/DebugDB: Open http://172.16.6.117:8081 in your browser) in logcat which will show all your DB on browser
The best Sqlite debugging tool for android application is
Stetho By Facebook
http://facebook.github.io/stetho/
Stetho is a sophisticated debug bridge for Android applications. When enabled, developers have access to the Chrome Developer Tools feature natively part of the Chrome desktop browser. Developers can also choose to enable the optional dumpapp tool which offers a powerful command-line interface to application internals.
Download or Alternatively you can include Stetho from Maven Central via Gradle or Maven.
// Gradle dependency on Stetho
dependencies {
compile 'com.facebook.stetho:stetho:1.5.1'
}
<dependency>
<groupid>com.facebook.stetho</groupid>
<artifactid>stetho</artifactid>
<version>1.5.1</version>
</dependency>
Only the main stetho dependency is strictly required, however you may also wish to use one of the network helpers:
dependencies {
compile 'com.facebook.stetho:stetho-okhttp3:1.5.1'
}
Or
dependencies {
compile 'com.facebook.stetho:stetho-okhttp:1.5.1'
}
Or
dependencies {
compile 'com.facebook.stetho:stetho-urlconnection:1.5.1'
}
Integrations
Setup
Integrating with Stetho is intended to be seamless and straightforward for most existing Android applications. There is a simple initialization step which occurs in your Application class:
public class MyApplication extends Application {
public void onCreate() {
super.onCreate();
Stetho.initializeWithDefaults(this);
}
}
This brings up most of the default configuration but does not enable some additional hooks (most notably, network inspection). See below for specific details on individual subsystems.
Enable Network Inspection
If you are using the popular OkHttp library at the 2.2.x+ or 3.x release, you can use the Interceptors system to automatically hook into your existing stack. This is currently the simplest and most straightforward way to enable network inspection.
For OkHttp 2.x
OkHttpClient client = new OkHttpClient();
client.networkInterceptors().add(new StethoInterceptor());
For OkHttp 3.x
new OkHttpClient.Builder()
.addNetworkInterceptor(new StethoInterceptor())
.build();
As interceptors can modify the request and response, add the Stetho interceptor after all others to get an accurate view of the network traffic.
If you are using HttpURLConnection, you can use StethoURLConnectionManager to assist with integration though you should be aware that there are some caveats with this approach. In particular, you must explicitly add Accept-Encoding: gzip to the request headers and manually handle compressed responses in order for Stetho to report compressed payload sizes.
for more info please visit stetho
I am looking to manually add a [text] file to my Android emulated device, and then retrieve it as a file when I am running my program. I can access files in my own C drive in testing, but obviously I cannot access the C drive of my PC on my emulator.
I can get into my devide on file explorer [device].adk/data and the folder list is:
- app
- benchmarktest
- misc
- nativetest
And how I am trying to retrieve the file is through:
public static final String MY_FILE = "[directoryhere]";
My question is: which folder would I store my file in, and what directory would I retrieve it from?
Alternatively, I have tried to store it on my localhost and access the directory as:
public static final String MY_FILE = "http://[myip]/files/my.file";
however, when I try to retrieve it I get the following error:
java.io.FileNotFoundException: \\[myip]\files\my.file (The network name cannot be found)
Many thanks.
try these two methods to store your files in your emulator
the easiest way is that just do drag and drop i mean when u
start your emulator drag your file and drop it and it will save
it in your emulator than you can easily access that
you can use the ADB via Terminal to pass the file From Desktop to Emulator.
Copy from desktop to emulator:
adb push < local > < remote >
Copy from emulator to desktop:
adb pull < remote > < local >
Here < local > is path of file / folder on your desktop and < remote> is
path of file / folder on your emulator.
Here is an example:
adb push foo.txt /sdcard/foo.txt
foo.txt will be pushed (copied) to the emulator.
for more information
Android Debug Bridge
I have an application, mostly in Java' that controls an airborne infrared camera via a webpage GUI (served by the Ubuntu machine) which starts running automatically when the computer is powered up and towards the end of the boot. The application runs as a user, not root, even though the user is not logged in.
After a great many images are collected the data need to be archived by using rsync to a folder on the operator's USB drive. I need to have the USB drive mounted and know its name tag. The computer is headless and the operator, who is on the aircraft, cannot be expected to know Linux in any case.
On an Ubuntu I see that logged in and running the xfce4 GUI, and only then, the drives are listed in /media/user-name/drive-tag (I note that /media/username is owned by root but the folder named for the drive is owned by the user.) and are shown in /etc/mtab :
/dev/sdd1 /media/programmer/DATA-02-2TB vfat rw,nosuid,nodev,uid=1001,gid=1001,shortname=mixed,dmask=0077,utf8=1,showexec,flush,uhelper=udisks2 0 0
How can I, through Java or through a combination of Java and bash, detect and mount a USB storage device?
If that's not possible do I need to ask the user, through the GUI, to enter the device tag or name, e.g., 'DATA-02-2TB' and then create the mount point and mount the USB drive via a script using the information above?
First install usbmount, a Ubuntu tool.
sudo apt-get update
sudo apt-get install usbmount
Then edit the /etc/usbmount/usbmount.conf file:
sudo sed -i 's/MOUNTOPTIONS="/MOUNTOPTIONS="user,umask=000,/' /etc/usbmount/usbmount.conf
These steps are described at Serverfault. Note that only a subset of drive formats is supported including the ubiquitous VFAT.
With this in place USB external drives and thumb drives will mount in /media as /media/usb0 through /media/usb7 and will be listed in /etc/mtab.
/dev/sdc1 /media/usb0 vfat rw,noexec,nosuid,nodev,sync,noatime,nodiratime,umask=000 0 0
I've tested this on my 14.04 machine. Now if I could only get the drive label.
Edit: The sync option does not work well with flash drives. Read the /etc/usbmount/usbmount.conf file for details and remove "sync" from the appropriate line in that file. A full backup made with sync option ran for over an hour before I cancelled it but took only about 5 minutes with sync removed. Note the comment about using pumount to unmount the non-synched drive.
public static ArrayList<String> usbDriveList() throws FileNotFoundException {
final String MTB_ADDRESS = "/etc/mtab";
final String TARGET = "^/media/usb[0-7]$"; // REGEX
final File file = new File(MTB_ADDRESS);
final ArrayList<String> driveList = new ArrayList<String>();
try (Scanner in = new Scanner(file)) {
while (in.hasNext()) {
final String[] splitLine = in.nextLine().split(" ");
if (splitLine[1].matches(TARGET)) {
driveList.add(splitLine[1]); // got it!
}
}
} catch (final FileNotFoundException e) {
throw new FileNotFoundException();
}
return driveList;
}
I am working on an Android App where a file is given its location like the code given below.
The method is like this:
public boolean log(ApplicationInfo aplinfo)
{
ApplicationInfo objAppinfo;
objAppinfo = apinfo;
_strFilePath = objAppinfo.dataDir;
_strFilePath += "/";
}
Where Appicationinfo is my activity name.
When I see in logcat I am getting file path as
09-07 06:34:41.355: INFO/System.out(525):
FileName::::::::::/data/data/com.andr.activity/Info_SA1.txt
My doubt is where can I find this file, where does this file exist?
When I am trying to read the contents of this file, then the contents that are written in to this file are also visible. But I am not able to find the physical location of the file.
Where does data/data/com.andr.activity path exists?
Can anyone help me in sorting out this issue?
Thanks in Advance.
This lives in the android filesystem, which is different from your computer's file system. To view the files in android filesystem, use adb shell on the command prompt. Run:
adb shell ls /data/data/com.andr.activity. Make sure your device/emulator is connected before you do this.
Or if you are using eclipse, switch to DDMS view and check out the file explorer.
To View file:
adb shell
Inside shell use:
cd /data/data/com.andr.activity
cat filename
Or Use adb pull to copy file to your computer's local filesystem and then view it using any editor. Read more about adb pull here