由于Ubuntu手机平台安全的限制,在Ubuntu手机的应用中我们只能访问自己的空间.如果我们所需要访问的文件不存在于我们应用所在的空间,我们是没有办法访问到的.我们的应用只能访问系统提供的库.如果系统没有所需要的库的话,我们通过可以通过如下的方法实现:
- 在我的应用中把应用的所需要的第三方的源码放入到我的应用项目中,并形成plugin(通常是C++代码)从而被应用调用
- 在我们的应用中把第三方的库打包进我们的应用包中,并在我的plugin(通常是C++代码)中调用,进而被应用调用
我们可以选择Ubuntu SDK所提供的标准的带有C++ plugin的模版来实现.对于第二种情况,我们同样需要在我们的项目中加入所需要的文件,并打包到我们的应用中去.第二种方法对于一些不存在于Ubuntu SDK所提供的标准库里的情况是非常有用的.比如我们可以得到PDF reader的库的源码,并编译成为我们自己的库.最终我们可以把这些库一起打包并安装到我们的手机中使用.
在今天的这篇文章中,我们就第二种方法来详细介绍.
1)创建一个最小的shared库
我已经创建好了一个最基本的shared库.开发者可以通过如下的方式来下载我们的代码:
$ git clone https://github.com/liu-xiao-guo/studentlib_shared
我们的这个库非常地简单:
Student.h
#include<string> class Student{ private: std::string name; public: Student(std::string); virtual void display(); };
student.cpp
#include <iostream> #include "Student.h" using namespace std; Student::Student(string name):name(name){} void Student::display(){ cout << "A student with name " << this->name << endl; }
接下来,我们以armhf chroot为例,当然我们也可以对i386使用同样的方法.我们通过我们已经安装好的armhf chroot来编译我们的这个库.首先我们通过如下的方式进入到我的chroot:
$ click chroot -aarmhf -fubuntu-sdk-15.04 run
当我们进入到我买的chroot中后,我们就可以开始编译我们的应用库了.我们进入到我们的项目的根目录中,并打入如下的命令
$ mkdir build $ cd build $ cmake .. $ make
这样在我们的build子目录下就可以看到我们希望的库了.
(click-ubuntu-sdk-15.04-armhf)[email protected]:~/qml/studentlib_shared/build$ ls CMakeCache.txt CMakeFiles Makefile cmake_install.cmake libtestStudent.so (click-ubuntu-sdk-15.04-armhf)[email protected]:~/qml/studentlib_shared/build$
2)创建一个带有plugin的最基本的应用.
我们选择"QML App with C++ plugin (qmake)"模版来创建一个最基本的testplugin应用.在这个应用中,我们将展示如何使用我们上面已经创建好的shared库.
接下来,我们修改我们的mytype.cpp及mytype.h文件:
mytype.h
#ifndef MYTYPE_H #define MYTYPE_H #include <QObject> class MyType : public QObject { Q_OBJECT Q_PROPERTY( QString helloWorld READ helloWorld WRITE setHelloWorld NOTIFY helloWorldChanged ) public: explicit MyType(QObject *parent = 0); Q_INVOKABLE void testlib(); ~MyType(); Q_SIGNALS: void helloWorldChanged(); protected: QString helloWorld() { return m_message; } void setHelloWorld(QString msg) { m_message = msg; Q_EMIT helloWorldChanged(); } QString m_message; }; #endif // MYTYPE_H
mytype.cpp
#include "mytype.h" #include "Student.h" MyType::MyType(QObject *parent) : QObject(parent), m_message("") { } void MyType::testlib() { Student student("johnddfsfdfdfds"); student.display(); } MyType::~MyType() { }
在上面的代码中,我们已经使用了我们shared库中的display()方法.如果这个时候我们去运行我们的应用的话,我们会发现我们的应用肯定是有错误的.这是因为它根本找不到它所需要的库.在下面我们来尝试把我们的库打包到我们的项目中来.
我们首先在我们的项目中创建一个叫做libs的目录,并把我们的shared库考入到这个目录中.这样整个的项目的目录就像:
[email protected]:~/qml/testplugin$ tree -L 3 . ├── backend │ ├── Testplugin │ │ ├── backend.cpp │ │ ├── backend.h │ │ ├── mytype.cpp │ │ ├── mytype.h │ │ ├── qmldir │ │ └── Testplugin.pro │ └── tests │ └── unit ├── libs │ ├── libs.pro │ ├── libtestStudent.so │ └── Student.h ├── manifest.json.in ├── po │ └── testplugin.liu-xiao-guo.pot ├── testplugin │ ├── Main.qml │ ├── testplugin.apparmor │ ├── testplugin.desktop │ ├── testplugin.png │ ├── testplugin.pro │ └── tests │ ├── autopilot │ └── unit ├── testplugin.pro └── testplugin.pro.user
在上面的显示中,我们可以看到在libs目录中除了一个我们看到的那个libtestStudent.so及header文件外,还有一个叫做libs.pro的文件.它的内容如下:
libs.pro
TEMPLATE = lib load(ubuntu-click) filetypes = qml png svg js qmltheme jpg qmlproject desktop wav so OTHER_FILES = filetypes for(filetype, filetypes) { OTHER_FILES += *.$$filetype } other_files.path = $${UBUNTU_CLICK_PLUGIN_PATH} other_files.files = $$OTHER_FILES INSTALLS += other_files message(The project1 will be installed in $${UBUNTU_CLICK_PLUGIN_PATH})
在上面的文件中,我们可以通过上面的方法把我们需要的.so文件拷入到我们所需要的目录中.
最后在我们的"testplugin.pro"文件中需要加入我们的目录"libs".
SUBDIRS += testplugin backend/Testplugin libs
在我们的"TestPlugin.pro"中,我们需要加入如下的句子:
LIBS += -L$$PWD/../../libs/ -ltestStudent INCLUDEPATH += $$PWD/../../libs DEPENDPATH += $$PWD/../../libs
在我们的QML文件中,我们是这样来调用的:
Main.qml
... Button { anchors.centerIn: parent text: "Test lib" onClicked: { myType.testlib(); } } ...
最终,我们来编译并部署我们的应用到我们的手机上:
我们可以查看在我们手机中的安装文件.在我们的desktop中打入如下的命令:
$ adb shell
通过上面的命令进入到手机中,并进入到如下的目录:
/opt/click.ubuntu.com/testplugin.liu-xiao-guo/current/lib/arm-linux-gnueabihf/
我们可以看到我们所需要的文件已经被成功安装到该目录中:
当我们点击在应用中的按钮"Test lib"时,我们可以在我们的SDK IDE中看见输出:
上面输出的字符串就是我们利用我们的库来输出的:
Student student("johnddfsfdfdfds"); student.display();
整个项目的源码在https://github.com/liu-xiao-guo/testplugin