Android应用安装

Android通过PackageManagerService(后面简称Pms)进行包管理,其主要功能包括:用户ID分配、包解析、包的安装卸载等。本文不对Pms进行分析,主要目的是探讨一下包安装。在本文中主要探讨包安装的相关操作,卸载作为安装的逆过程,实现类似,不再赘述。

Android中APK的安装方式

在Android中APK的安装有三种方式:

1、开机Pms初始化时,扫描包安装目录。

@/frameworks/base/services/java/com/android/server/SystemServer.java


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

public void initAndLoop() {

    ......

    

    IPackageManager pm = null;

    

    ......

    

    try {

        ......

        

        pm = PackageManagerService.main(context, installer,

                factoryTest != SystemServer.FACTORY_TEST_OFF,

                onlyCore);

        ......

    catch (RuntimeException e) {

        Slog.e("System""******************************************");

        Slog.e("System""************ Failure starting core service", e);

    }

    ......

}

@/frameworks/base/services/java/com/android/server/pm/PackageManagerService.java


1

2

3

4

5

6

7

public static final IPackageManager main(Context context, Installer installer,

        boolean factoryTest, boolean onlyCore) {

    PackageManagerService m = new PackageManagerService(context, installer,

            factoryTest, onlyCore);

    ServiceManager.addService("package", m);

    return m;

}

下面是Pms构造函数的实现:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

public PackageManagerService(Context context, Installer installer,

        boolean factoryTest, boolean onlyCore) {

    ......

    

    synchronized (mInstallLock) {

    // writer

    synchronized (mPackages) {

        ......

        

        File dataDir = Environment.getDataDirectory();

        mAppDataDir = new File(dataDir, "data");

        mAppInstallDir = new File(dataDir, "app");

        mAppLibInstallDir = new File(dataDir, "app-lib");

        mAsecInternalPath = new File(dataDir, "app-asec").getPath();

        mUserAppDataDir = new File(dataDir, "user");

        mDrmAppPrivateInstallDir = new File(dataDir, "app-private");

        ......

        

        // Find base frameworks (resource packages without code).

        mFrameworkInstallObserver = new AppDirObserver(

            frameworkDir.getPath(), OBSERVER_EVENTS, truefalse);

        mFrameworkInstallObserver.startWatching();

        scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM

                | PackageParser.PARSE_IS_SYSTEM_DIR,

                scanMode | SCAN_NO_DEX, 0);

        // Collected privileged system packages.

        File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");

        mPrivilegedInstallObserver = new AppDirObserver(

                privilegedAppDir.getPath(), OBSERVER_EVENTS, truetrue);

        mPrivilegedInstallObserver.startWatching();

            scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM

                    | PackageParser.PARSE_IS_SYSTEM_DIR

                    | PackageParser.PARSE_IS_PRIVILEGED, scanMode, 0);

        // Collect ordinary system packages.

        File systemAppDir = new File(Environment.getRootDirectory(), "app");

        mSystemInstallObserver = new AppDirObserver(

            systemAppDir.getPath(), OBSERVER_EVENTS, truefalse);

        mSystemInstallObserver.startWatching();

        scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM

                | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);

        // Collect all vendor packages.

        File vendorAppDir = new File("/vendor/app");

        mVendorInstallObserver = new AppDirObserver(

            vendorAppDir.getPath(), OBSERVER_EVENTS, truefalse);

        mVendorInstallObserver.startWatching();

        scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM

                | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);

        ......

        if (!mOnlyCore) {

            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,

                    SystemClock.uptimeMillis());

            mAppInstallObserver = new AppDirObserver(

                mAppInstallDir.getPath(), OBSERVER_EVENTS, falsefalse);

            mAppInstallObserver.startWatching();

            scanDirLI(mAppInstallDir, 0, scanMode, 0);

            mDrmAppInstallObserver = new AppDirObserver(

                mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, falsefalse);

            mDrmAppInstallObserver.startWatching();

            scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,

                    scanMode, 0);

            ......

    // synchronized (mPackages)

    // synchronized (mInstallLock)

}

通过Pms的构造函数可以看出,Pms在初始化时会扫描/system/app、vender/app、/data/app、/data/app-private四个应用安装目录,然后调用sanDirLI方法进行安装。Pms通过AppDirObserver对这四个应用安装目录进行监控,一旦发现APK格式的文件则会调用scanPackageLI进行安装。

2、通过包安装器PackageInstaller安装

Android提供了一个默认的包安装器,位于/package/app/PackageInstaller目录。通过其Manifest文件可以看出,PackageInstaller会对我们安装应用发出的Intent进行处理,这里PackageInstaller提供了两种处理方式,分别是:file方式和package方式。

@/package/app/PackageInstaller/AndroidManifest.xml


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

<activity android:name=".PackageInstallerActivity"

        android:configChanges="orientation|keyboardHidden|screenSize"

        android:excludeFromRecents="true">

    <intent-filter>

        <action android:name="android.intent.action.VIEW" />

        <action android:name="android.intent.action.INSTALL_PACKAGE" />

        <category android:name="android.intent.category.DEFAULT" />

        <data android:scheme="file" />

        <data android:mimeType="application/vnd.android.package-archive" />

    </intent-filter>

    <intent-filter>

        <action android:name="android.intent.action.INSTALL_PACKAGE" />

        <category android:name="android.intent.category.DEFAULT" />

        <data android:scheme="file" />

        <data android:scheme="package" />

    </intent-filter>

</activity>

@/package/app/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java


1

2

3

4

5

6

7

8

@Override

protected void onCreate(Bundle icicle) {

    super.onCreate(icicle);

    ......

    

    initiateInstall();

}


1

2

3

4

5

private void initiateInstall() {

    ......

    startInstallConfirm();

}

在startInstallConfirm方法中点击“确认”后,会发出一个Intent,接收者为InstallAppProgress。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

public void onClick(View v) {

    if(v == mOk) {

        if (mOkCanInstall || mScrollView == null) {

            // Start subactivity to actually install the application

            mInstallFlowAnalytics.setInstallButtonClicked();

            Intent newIntent = new Intent();

            newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,

                    mPkgInfo.applicationInfo);

            newIntent.setData(mPackageURI);

            newIntent.setClass(this, InstallAppProgress.class);

            ......

            

            startActivity(newIntent);

            finish();

        else {

            mScrollView.pageScroll(View.FOCUS_DOWN);

        }

    else if(v == mCancel) {

        ......

    }

}

@/package/app/PackageInstaller/src/com/android/packageinstaller/InstallAppProgress.java


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

public void initView() {

    setContentView(R.layout.op_progress);

    int installFlags = 0;

    PackageManager pm = getPackageManager();

    

    ......

    

    String installerPackageName = getIntent().getStringExtra(

            Intent.EXTRA_INSTALLER_PACKAGE_NAME);

    Uri originatingURI = getIntent().getParcelableExtra(Intent.EXTRA_ORIGINATING_URI);

    Uri referrer = getIntent().getParcelableExtra(Intent.EXTRA_REFERRER);

    int originatingUid = getIntent().getIntExtra(Intent.EXTRA_ORIGINATING_UID,

            VerificationParams.NO_UID);

    ManifestDigest manifestDigest = getIntent().getParcelableExtra(EXTRA_MANIFEST_DIGEST);

    VerificationParams verificationParams = new VerificationParams(null, originatingURI,

            referrer, originatingUid, manifestDigest);

    PackageInstallObserver observer = new PackageInstallObserver();

    if ("package".equals(mPackageURI.getScheme())) {

        try {

            pm.installExistingPackage(mAppInfo.packageName);

            observer.packageInstalled(mAppInfo.packageName,

                    PackageManager.INSTALL_SUCCEEDED);

        catch (PackageManager.NameNotFoundException e) {

            observer.packageInstalled(mAppInfo.packageName,

                    PackageManager.INSTALL_FAILED_INVALID_APK);

        }

    else {

        pm.installPackageWithVerificationAndEncryption(mPackageURI, observer, installFlags,

                installerPackageName, verificationParams, null);

    }

}

InstallAppProgress即应用安装过程中的进度条界面。通过上面的代码可以看到在initView方法的最后会调用Pms的installPackageWithVerificationAndEncryption方法进行安装。

3、通过adb命令安装

adb命令pm是Pms的Shell客户端,通过pm可以进行包相关的一些操作,包括安装和卸载。pm命令的用法如下:

pm的代码实现在Pm.java中,如下:

@/frameworks/base/cmds/pm/src/com/android/commands/pm/Pm.java


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

public static void main(String[] args) {

    new Pm().run(args);

}

public void run(String[] args) {

    ......

    

    mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));

    

    ......

    if ("install".equals(op)) {

        runInstall();

        return;

    }

    if ("uninstall".equals(op)) {

        runUninstall();

        return;

    }

    ......

}

在run方法中初始化了一个Pms的客户端代理对象mPm,后续的相关操作将有mPm完成。下面看一下Pm中负责安装的方法runInstall的代码实现:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

private void runInstall() {

    int installFlags = PackageManager.INSTALL_ALL_USERS;

    

    ......

    

    while ((opt=nextOption()) != null) {

        if (opt.equals("-l")) {

            installFlags |= PackageManager.INSTALL_FORWARD_LOCK;

        else if (opt.equals("-r")) {

            installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;

        else if (opt.equals("-i")) {

            installerPackageName = nextOptionData();

            if (installerPackageName == null) {

                System.err.println("Error: no value specified for -i");

                return;

            }

        else if (opt.equals("-t")) {

            installFlags |= PackageManager.INSTALL_ALLOW_TEST;

        else if (opt.equals("-s")) {

            // Override if -s option is specified.

            installFlags |= PackageManager.INSTALL_EXTERNAL;

        else if (opt.equals("-f")) {

            // Override if -s option is specified.

            installFlags |= PackageManager.INSTALL_INTERNAL;

        else if (opt.equals("-d")) {

            installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;

        ......   

            

    PackageInstallObserver obs = new PackageInstallObserver();

    try {

        VerificationParams verificationParams = new VerificationParams(verificationURI,

                originatingURI, referrerURI, VerificationParams.NO_UID, null);

        mPm.installPackageWithVerificationAndEncryption(apkURI, obs, installFlags,

                installerPackageName, verificationParams, encryptionParams);

        synchronized (obs) {

            while (!obs.finished) {

                try {

                    obs.wait();

                catch (InterruptedException e) {

                }

            }

            if (obs.result == PackageManager.INSTALL_SUCCEEDED) {

                System.out.println("Success");

            else {

                System.err.println("Failure ["

                        + installFailureToString(obs.result)

                        "]");

            }

        }

    catch (RemoteException e) {

        System.err.println(e.toString());

        System.err.println(PM_NOT_RUNNING_ERR);

    }

}

可以看出runInstall最终会调用Pms的installPackageWithVerificationAndEncryption方法进行安装。通过pm安装时,安装成功的返回信息为“Success”,安装失败的返回信息为”Failure[失败信息]"。

静默安装实现

在了解了Android中包安装的方式后,接下来探讨一些如何实现”静默安装“。所谓静默安装即跳过安装界面和进度条,在不被用户察觉的情况下载后台安装。下面针对上面的三种安装方式分别来分析如何实现静默安装。

1、push安装包到应用安装目录的方式

在Pms初始化时安装包的流程中,我们知道Pms会监控/system/app、vender/app、/data/app、/data/app-private这四个应用安装目录。因此如果能够将APK文件push进应用安装目录不就可以触发AppDirObserver中的包安装逻辑了了吗?所以这种思路理论上是行得通的,但有两个局限:

  • 局限一:如下图所示,/system/app的访问权限为root,这就要求在push到/system/app目录时必须具有root权限。

    而/data/app的访问权限为system。要获得system权限就要求使用这种方式的应用程序必须签名为platform并且sharedUserId制定为“android.uid.system”。

  • 局限二:系统应用(/system/app)与普通应用(/data/app)的安装方式是不同的,对于系统应用,所有资源都包含在apk这个zip包中,而且其在/system/app不必以包名命名(理论上可以随便起名)。

    而对于普通应用安装后,它的dex、lib、资源文件(安装包)分别存放在不同的目录,并且安装后以packagename-x.apk的形式保存在/data/app目录下。?

那这种安装方式是不是就没有用了呢?非也。

网上有些电子市场或管家类软件实现的”秒装“功能应该就是安装这个思路实现的,当然这里只是猜测,需要进一步研究。

2、调用Pm隐藏API

Android实现了一个应用安装器的APK负责包的安装工作,在上面的分析中我们知道,PackageInstaller的工作实际上只是安装界面、权限确认、进度显示等,真正的安装工作依然是调用Pms实现的。到这里我们就有了第二种思路,能不能绕过安装界面,直接调用Pms里面的相应方法呢?当然可以,PackageManager类中就提供了这样的方法:

@/frameworks/base/core/java/android/content/pm/PackageManager.java


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

/**

 * @hide

 *

 * Install a package. Since this may take a little while, the result will

 * be posted back to the given observer.  An installation will fail if the calling context

 * lacks the {@link android.Manifest.permission#INSTALL_PACKAGES} permission, if the

 * package named in the package file‘s manifest is already installed, or if there‘s no space

 * available on the device.

 *

 * @param packageURI The location of the package file to install.  This can be a ‘file:‘ or a

 * ‘content:‘ URI.

 * @param observer An observer callback to get notified when the package installation is

 * complete. {@link IPackageInstallObserver#packageInstalled(String, int)} will be

 * called when that happens.  observer may be null to indicate that no callback is desired.

 * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},

 * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.

 * @param installerPackageName Optional package name of the application that is performing the

 * installation. This identifies which market the package came from.

 */

public abstract void installPackage(

        Uri packageURI, IPackageInstallObserver observer, int flags,

        String installerPackageName);

可以看出,这个方法是hide的,因此在应用开发时如果要使用,必须通过反射。

这里的IPackageInstallObserver是installPackage方法的一个回调接口通知,其实现在IPackageInstallObserver.aidl中,如下:

@/frameworks/base/core/java/com/android/content/pm/IPackageInstallObserver.aidl


1

2

3

4

5

6

7

8

9

package android.content.pm;

/**

 * API for installation callbacks from the Package Manager.

 * @hide

 */

oneway interface IPackageInstallObserver {

    void packageInstalled(in String packageName, int returnCode);

}

使用Android内置未公开API有两种方法:一种是通过反射的方式实现;另一种是在工程目录下建立与所引用系统类相同的类和方法,这里只要求类和方法名相同,不需要实现,只保证编译时不报错就可以了,根据Java的类加载机制,在运行时,会去加载系统类。下面是采用第二种方法时的两段示例代码:

实现接口回调的代码如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

class MyPakcageInstallObserver extends IPackageInstallObserver.Stub
{

        Context
cxt;

        String
appName;

        String
filename;

        String
pkname;

        public MyPakcageInstallObserver(Context
c, String appName,

                 String
filename,String packagename) {

            this.cxt
= c;

            this.appName
= appName;

            this.filename
= filename;

            this.pkname
= packagename;

        }

        @Override

        public void packageInstalled(String
packageName, 
int returnCode)
{

            Log.i(TAG, "returnCode
= "
 +
returnCode);
//
返回1代表安装成功

                        if (returnCode
== 
1)
{

                            //TODO

                        }

            Intent
it = 
new Intent();

            it.setAction(CustomAction.INSTALL_ACTION);

            it.putExtra("install_returnCode",
returnCode);

            it.putExtra("install_packageName",
packageName);

            it.putExtra("install_appName",
appName); cxt.sendBroadcast(it);

        }

    }

调用PackageManager.java隐藏方法,代码如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

/**

     *
静默安装

     *
*/

    public static void autoInstallApk(Context
context, String fileName,

            String
packageName, String APPName) {

        Log.d(TAG, "jing
mo an zhuang:"
 +
packageName + 
",fileName:" +
fileName);

        File
file = 
new File(fileName);

        int installFlags
0;

        if (!file.exists())

            return;

        installFlags
|= PackageManager.INSTALL_REPLACE_EXISTING;

        if (hasSdcard())
{

            installFlags
|= PackageManager.INSTALL_EXTERNAL;

        }

        PackageManager
pm = context.getPackageManager();

        try {

            IPackageInstallObserver
observer = 
new MyPakcageInstallObserver(

                    context,
APPName, appId, fileName,packageName,type_name);

            Log.i(TAG, "########installFlags:" +
installFlags+
"packagename:"+packageName);

            pm.installPackage(Uri.fromFile(file),
observer, installFlags,

                    packageName);

        catch (Exception
e) {

            

        }

    }

这种方法也有一定的限制:

首先,要在AndroidManifest.xml中声明”android.permission.INSTALL_PACKAGES”权限;

其次,应用需要system权限。

3、调用pm命令进行安装

在adb窗口通过pm install安装包本来就是没有安装界面的,这不正是我们想要的吗?通过pm的安装方式需要取得root或system权限。

pm的安装方式有两种,一种需要root权限,示例代码如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

new Thread()
{

    public void run()
{

    Process
process = 
null;

    OutputStream
out = 
null;

    InputStream
in = 
null;

    try {

    //
请求root

    process
= Runtime.getRuntime().exec(
"su");

    out
= process.getOutputStream();

    //
调用安装

    out.write(("pm
install -r "
 +
currentTempFilePath + 
"\n").getBytes());

    in
= process.getInputStream();

    int len
0;

    byte[]
bs = 
new byte[256];

    while (-1 !=
(len = in.read(bs))) {

    String
state = 
new String(bs, 0,
len);

    if (state.equals("Success\n"))
{

       //安装成功后的操作

         }

       }

    catch (IOException
e) {

        e.printStackTrace();

    catch (Exception
e) {

        e.printStackTrace();

    finally {

        try {

            if (out
!= 
null)
{

                out.flush();

                out.close();

            }

            if (in
!= 
null)
{

                in.close();

            }

        catch (IOException
e) {

            e.printStackTrace();

        }

    }

  }

}.start();

另一钟需要system权限,示例如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

new Thread() {

    public void run() {

    Process process = null;

    InputStream in = null;

    try {

    // 请求root

    process = Runtime.getRuntime().exec("pm install -r " + currentTempFilePath + "\n"); 

    in = process.getInputStream();

    int len = 0;

    byte[] bs = new byte[256];

    while (-1 != (len = in.read(bs))) {

    String state = new String(bs, 0, len);

    if (state.equals("Success\n")) {

       //安装成功后的操作

         }

       }

    catch (IOException e) {

        e.printStackTrace();

    catch (Exception e) {

        e.printStackTrace();

    finally {

        try {

            if (in != null) {

                in.close();

            }

        catch (IOException e) {

            e.printStackTrace();

        }

    }

  }

}.start();

关于system权限的获取在介绍push方式的安装时已做介绍。上面的代码只给出了比较核心的部分,在实际实现中,对返回结果的处理同样重要。

Android应用安装

时间: 2024-09-20 15:27:00

Android应用安装的相关文章

Android Studio 安装及常见问题

今年放假比去年早了一些,就提前回来了.感觉挺爽,结果教研室电脑没有带回来,悲剧是导师让我维护一下以前的项目,只能屁颠屁颠的搞起呀.只能用自己的笔记本搭建android开发环境.由于前阶段听说Android Studio用着爽歪歪,于是尝试在超卡的笔记本上跑Android Studio.哇咔咔,费了九牛二虎之力终于将Android Studio玩转了.先上个图,快过年了,祝大家新年快乐! Android官网也开始推广Android Studio了,以前官网好像提供Eclipse和ADT打包下载,现

【转】Android Studio安装配置学习教程指南 下载和安装--不错

背景 相信大家对Android Studio已经不陌生了,Android Studio是Google于2013 I/O大会针对Android开发推出的新的开发工具,目前很多开源项目都已经在采用,Google的更新速度也很快,明显能感觉到这是Android开发的未来,那么我们还有什么理由不去拥抱未来呢? 虽然推出了很久,但是国内貌似普及的程度并不高,鉴于很多朋友求studio的详细教程,那么今天我就手把手教大家下载.安装.使用,Studio之路从这里开始. Android Studio VS Ec

Ubuntu下 Android NDK安装

method 1. 1.google上直接下载NDK源码解压即可,目前版本为 android-ndk-r9d 配置$NDK_HOME 和 $PATH export NDK_HOME=/XXX/android-ndk-r9dexport PATH=$NDK_HOME:$PATH 2.提取toolchain 参考:docs/STANDALONE-TOOLCHAIN.html a.查看目标 指令集 arm or x86 or mipsb.配置gcc编译时所用头文件和根文件的目录 $SYSROOT SY

Android studio 安装中遇到一些问题的解决办法,分享一下

从eclipse转到android studio也是很无耐,刚开始总是会遇到很多难题,但是都不要轻言放弃. 以下是我遇到的问题,并通过搜索引擎找到的解决办法,善用工具,善用头脑,勿为伸手之人. Android Studio需要JDK 1.7+才可以安装,不过这个时候也要升级到1.7了. 安装完成之后第一次启动的时候会首先显示Fetching Android SDK component information,等一会儿在Setup Wizard - Downloading Components界面

Android Studio安装后Fetching android sdk component information超时的解决方案

问题描述: Android Studio 是一个全新的 Android 开发环境,基于IntelliJ IDEA. 类似 Eclipse ADT,Android Studio 提供了集成的 Android 开发工具用于开发和调试. Android Studio安装完成后,如果直接启动,Android Studio会去获取 android sdk 组件信息,这个过程相当慢,还经常加载失败,导致Android Studio启动不起开.解决办法就是不去获取android sdk 组件信息. 解决方法:

关于android 如何安装 assets文件下的apk

在自己的app中安装assets目录下的apk文件 public class MainActivity extends Activity { Context mContext; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mContext = this; //Toa

Qt on Android: Android SDK安装

之前我在 <Windows下Qt 5.2 for Android开发入门>一文中介绍了 Windows 下 Qt on Android 开发环境的搭建,略过了 Android SDK 的安装,实际还是有一些朋友会在这里遇到问题.这里再专门介绍一下 Android SDK 的安装. 版权全部,转载请注明出处:http://blog.csdn.net/foruok Android SDK 能够到这里下载:http://developer.android.com/sdk/index.html . 假

解决Android应用安装快完毕时提示签名冲突

最近开发了一个Android手机应用,自己用Eclipse调试安装没问题,使用其他人调试生成的bin下的apk就会出现问题,安装到最后提示"安装签名冲突"错误,想了一下估计是没有给apk统一签名导致,以下说一下如何解决这个问题. 生成keystore文件 命令:keytool -genkey -v -keystore "c:\android\release\relase.keystore" -alias androidbook –storepass paxxword

Android开发安装实战教程

InstallAndroid安装 Android 开发工具Android 提供免费而且跨平台的整合开发环境,只要电脑能连接上网路,我们随时都能下载相关工具下来,并开始开发Android 应用程序.有了轻便易用的开发工具,我们可以把心力专注于如何将想法实现到应用程序上.系统需求撰写Android 的应用程序,需要一套个人电脑系统.至于操作系统的部份,几个主流操作系统都有支援.支援的操作系统如下:* Windows XP 或Vista* Mac OS X 10.4.8 或之后版本(适用x86 架构的

window7 64位下Android studio 安装genymotion模拟器

1.登录genymotion官网注册一个账号才能下载,注册号之后 2.点击buy genymotion   3.选择free免费 点击download 4. 选择系统,点击get genymotion 可以选择没有vituaiBox,如果你安装有 之后便进行下载了 5.下载好之后双击安装即可 6.根据提示下载一个版本的手机镜像文件,便可以运行 7.点击start便可以运行了   二.Android studio 安装 genymotion插件 1.(1)在Android Studio中选择Fil