在上一篇的基础上,我们已经将安卓应用的数据库文件拷贝到了公共文件夹下,接下来,我们需要把这个数据库文件拷贝到Pc端。手机上的数据怎么拷贝到PC上呢,笨办法,连数据线、蓝牙等,自己手动拷,但程序猿的工作不就是将无聊的重复性工作想办法交给电脑么,所以让我们放弃这个蠢笨的办法。
相信大家在安卓的开发中,使用过adb将文件从你的模拟器或者手机上pull到电脑上进行查看,那么,点子来了,让我们也尝试这种方式。
我们首先将adb的exe和相关组件dll统一放到我们的WPF工程目录下,这样就可以直接通过相对路径的方式启动adb,而不需要用户手动启动了,如下图所示:

然后呢,在程序中通过通过命令来启动这个我们的Adb,如下图所示:
/// <summary>
/// adb.exe文件的路径,默认相对于当前应用程序目录取。
/// </summary>
public static string AdbExePath
{
get
{
return Path.Combine(PathUtils.GetProjectRootPath(), "AdbBin\\adb.exe");
}
}
/// <summary>
/// 启动ADB服务
/// </summary>
/// <returns></returns>
public static bool StartServer()
{
return ProcessHelper.Run(AdbExePath, "start-server").Success;
}服务启动之后,我们就可以操作adb的进程,完成你在开发安卓时,对adb的一切操作。这里摘抄了部分代码,更多的功能你可以查看adb shell相关命令,然后解析结果即可。
/// <summary>
/// 获取设备列表
/// </summary>
/// <returns></returns>
public static string[] GetDevices()
{
var result = ProcessHelper.Run(AdbExePath, "devices");
var itemsString = result.OutputString;
var items = itemsString.Split(new[] { "$", "#", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
var itemsList = new List<String>();
foreach (var item in items)
{
var tmp = item.Trim();
//第一行不含\t所以排除
if (tmp.IndexOf("\t") == -1)
continue;
var tmps = item.Split('\t');
itemsList.Add(tmps[0]);
}
itemsList.Sort();
return itemsList.ToArray();
}
/// <summary>
/// 列举ls /data/data目录下的文件和目录
/// </summary>
/// <returns></returns>
public static List<string> ListDataFolder(string deviceNo)
{
var moreArgs = new[] { "su", "ls /data/data", "exit", "exit" };
var result = ProcessHelper.RunAsContinueMode(AdbExePath, string.Format("-s {0} shell", deviceNo), moreArgs);
var itemsString = result.MoreOutputString[1];
var items = itemsString.Split(new[] { "$", "#", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
var itemsList = new List<String>();
foreach (var item in items)
{
var tmp = item.Trim();
//移除第一行,输入的命令
if (tmp.Contains(moreArgs[1]))
continue;
//移除空白行
if (string.IsNullOrEmpty(tmp))
continue;
//移除最后两行的root@android
if (tmp.ToLower().Contains("root@"))
continue;
itemsList.Add(tmp);
}
itemsList.Sort();
return itemsList;
}以上整体的思路就是我们首先启动adb的服务,然后通过向adb服务写命令行的方式,得到结果,解析这个结果,得到我们想要的相关数据,那怎么把安卓上的文件pull到电脑上呢,核心代码如下:
/// <summary>
/// 拷贝文件到PC上
/// </summary>
/// <param name="deviceNo"></param>
/// <param name="devPath"></param>
/// <param name="pcPath"></param>
/// <returns></returns>
public static bool CopyFromDevice(string deviceNo, string devPath, string pcPath)
{
//使用Pull命令将数据库拷贝到Pc上
//adb pull [-p] [-a] <remote> [<local>]
var result = ProcessHelper.Run(AdbExePath, string.Format("-s {0} pull {1} {2}", deviceNo, devPath, pcPath));
m_log.Info("推送PC时结果:" + result.ToString());
if (!result.Success
|| result.ExitCode != 0
|| (result.OutputString != null && result.OutputString.Contains("failed")))
{
return false;
throw new Exception("pull 执行返回的结果异常:" + result.OutputString);
}
return true;
}到此,我们已经将安卓应用下的db数据库文件,拷贝到了电脑上,接下来,让我们解析它~解析的方式这里就不做啰嗦,可以查看我的这篇文章WPF中使用SqLite数据库,这里我直接往下做,使用SqlLite-net-pcl这个ORM框架进行数据读取操作。
首先新建一个UserDbModel的类,对应着数据库中的usermodel表。
[Table("usermodel")]
public class UserDbModel
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string Username { get; set; }
}再创建一个AndroidDb,继承自SQLiteConnection类,将初始化UserDbModel的方法写在里面。
public class AndroidDb : SQLiteConnection
{
//定义属性,便于外部访问数据表
public TableQuery<UserDbModel> Users { get { return this.Table<UserDbModel>(); } }
public AndroidDb(string dbPath) : base(dbPath)
{
//创建数据表
CreateTable<UserDbModel>();
}
}接下来,直接读取数据库中的User表数据。
//本地数据库地址
string path = strPCFilePath + "\\" + dbName;//数据库所在路径
//使用SQLite.Net-PCL访问数据库
using (var db = new AndroidDb(path))
{
List<UserDbModel> users = db.Users.Where(m => true).ToList();
}到此,我们已经完成了pc读取手机应用内部数据库的功能啦,来,欣赏一下吧~

















