Android应用基础开发入门

本文写给Android小白,起步入门参考,不过还是喜欢从原理上尽量多讲一点东西。

本文从以下四个方面展开,重点介绍前3节:

第一节:什么是apk?

第二节:android开发 工具介绍

第三节:我们开发中常用的一些方法

第四节:使用手机调试的方法

第五节:学习方法

 

第一节:什么是apk?

1,APK:AndroidPackage的缩写,即Android安装包。

2,apk本质上就是一个zip文件,将apk后缀名改为zip,解压以后如下:

Android应用基础开发入门_第1张图片

提前爆料一下,java文件会被编译为.dex文件,因为Android虚拟机的可执行文件为dex格式。

xml文件会被转化成二进制文件,因为

(1) 二进制格式的XML文件占用空间更小。

(2) 二进制格式的XML文件解析速度更快。

所以你是无法直接通过解压apk直接看里面的代码或者xml的。图片等资源是可以的,assets下面的资源也是没问题的,具体下面再详细的说。

下面是编译前的源码目录:

Android应用基础开发入门_第2张图片

apk解压后的文件与编译前源码比较还是能看出一些大概来。

3,问题来了,一个apk到底是怎么生成的呢?IDE工具(eclipse或者Android Studio)或者mm命令 做了哪些事情呢?

 

Android应用基础开发入门_第3张图片

这个图是google给出的apk打包过程,也就是IDE为我们做的事情。

(1)打包资源文件。

(2)处理aidl文件,生成相应java 文件。对于没有使用到aidl的android工程,可以跳过此步骤。

(3)编译工程源代码,生成相应class 文件。

这一步调用了javac编译工程src目录下所有的java源文件,生成的class文件位于工程的bin\classes目录下,上图假定编译工程源代码时程序是基于android SDK开发的,实际开发过程中,也有可能会使用android NDK来编译native代码,因此,如果可能的话,这一步还需要使用android NDK编译C/C++代码,当然,编译C/C++代码的步骤也可以提前到第一步或第二步。通过Java Compiler编译R.java、Java接口文件、Java源文件,生成.class文件。

(4)转换所有class文件,生成classes.dex文件。Android虚拟机的可执行文件为dex格式,所以需要此步骤。

(5)打包生成apk。打包后的res文件夹(除res/raw资源被原装不动地打包进APK之外)、打包后类文件(.dex文件)、libs文件(包括.so文件,当然很多工程都没有这样的文件,如果你不使用C/C++开发的话)、resources.arsc、assets、AndroidManifest.xml打包成apk文件。

(6)对apk文件进行签名。

(7)对签名后的apk文件进行处理。在 Android SDK 中包含一个名为 “zipalign” 的工具,它能够对打包后的 app 进行优化。 即对签名后的apk进行对齐处理。

 

       理论上来说,你可以不借助IDE,只用linux工具和命令完成整个android的打包过程。感兴趣的同学可以试一试,如果你能成功,相信你对apk的打包过程已经有了十分清晰的认识。

      一般来说,你可以替换一些资源而不需要源码,这是被允许的。但资源仅限于打包的时候没有做转化的,比如res下面的一些图片或者视频,音乐等资源,或者asserts下面的所有资源。步骤如下:apk改名为zip,并解压,替换同样规格的资源,将zip改名为apk。将apk重新进行签名。此时这个apk就是被篡改过的apk。有同学会问,如果我想修改一些代码中的逻辑可以么,这样我就可以在别人的应用中植入自己的广告了?可以的,这就需要修改其中的.dex文件,但是这个文件修改不是那么容易的,需要比较深入一些的android逆向技术。已经超过《Android应用基础开发入门》的大纲。如果大家对这方面感兴趣,可以作为一个课题专项研究。关于android逆向,大神写的文章,有兴趣的可以学习一下:https://www.52pojie.cn/thread-732298-1-1.html

 

第二节:android开发 工具介绍

       Google官方的IDE仅仅支持Android Studio,原来的时候eclipse也可以,但是在15年左右,google已经停止对eclipse的支持,这意味着,对于最新版的SDK,有可能用eclipse因为某些工具版本问题,是编译不过去的且得不到官方的支持。

       对于我们来说,就是尽量的不要用eclipse编译,但是有一些源码中的工程结果是eclipse的工程结构,并且还是无法用eclipse编译的,只能用源码mm进行编译,这种情况依然建议使用eclipse作为编辑器,因为操作比较方便,链接的比较准确。在使用eclipse的时候,即使编译不过,也请在右键-->>Propertytiews中选择Android,选择一个Android版本,这样会能链接到一些Android的一些api。提高编程效率。

Android应用基础开发入门_第4张图片

 

      Android Studio是谷歌出品,在Android开发上有一些先天优势,在查找类等平时开发工作中点点滴滴都会觉得方便,大家用的多了就能体会到优势。Studio查看源码也是非常方便,不加留意你甚至都分不清那些类自己的,那些类时Android的。下面着重介绍一下Android studio的一些用法:

       为了更加全面的介绍,我用我自己实现的一些demo进行演示

1,Android Studio非常的依赖网络,可以说,没有网络,AndroidStudio寸步难行。生活体验,有网络2分钟能搞定的事情,如果studio由于某些原因无法直接连接网络,那么工作量直接变为3天。而平时我们编译工程遇到最多的问题,也是下载某个模块卡住下载不动,下载超时等的编译问题。

2,之所以出现上面的网络的问题,根本原因在于AndroidStudio使用了gradle作为它的打包管理工具。喜欢gradle的人赞誉真方便,不喜欢它的人会抱怨gradle好诡异,怎么弄都不行,正所谓成也萧何,败也萧何。何为gradle?gradle在apk编译过程中做了那些事情?

      简单的说,Gradle是一个构建工具,它是用来帮助我们构建app的,构建包括编译、打包等过程。有时候

我们要自己在系统默认构建规则上做一些修改。这时候我们就要自己向Gradle”下命令“了,这时候我们就需要用Gradle能听懂的话了,也就是Groovy。Groovy是一种基于JVM的动态语言。

      关于gradle还是比较复杂的,刚接触android studio的同学会有被折磨的感觉,要学习的话也有很多的内容需要学习,这里不去系统的学习,只将我们最常用的一些代码做简单讲解。

 

buildscript {

repositories {

jcenter() //构建脚本中所依赖的库都在jcenter仓库下载

}

dependencies {

//指定了gradle插件的版本

classpath 'com.android.tools.build:gradle:1.5.0'

   }

}

 

allprojects{

repositories{

google()

jcenter()

 

maven{

url"https://maven.google.com"

}

gradle.projectsEvaluated{

tasks.withType(JavaCompile){

options.compilerArgs.add('-Xbootclasspath/p:app/sdk/android.jar');

}

}

 

}

}

 

//指定应用插件,也就指定了编译类型,是app还是jar,aar包

applyplugin:'com.android.application'

 

android{

compileSdkVersion23

buildToolsVersion"28.0.2"

useLibrary'org.apache.http.legacy'

defaultConfig{

applicationId"com.kingboard.settings"

minSdkVersion21

targetSdkVersion23

versionCode1

versionName"1.0"

}

signingConfigs{

release{

storeFilefile('../tools/platform_debug.keystore')

keyAlias'androiddebugkey'

keyPassword'android'

storePassword'android'

}

 

debug{

storeFilefile('../tools/platform_debug.keystore')

keyAlias'androiddebugkey'

keyPassword'android'

storePassword'android'

}

}

buildTypes{

release{

//混淆

minifyEnabledtrue

//移除无用的resource文件

shrinkResourcestrue

//Zipalign优化

zipAlignEnabledtrue

proguardFilesgetDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'

signingConfigsigningConfigs.release

}

 

debug{

minifyEnabledtrue

shrinkResourcestrue

zipAlignEnabledtrue

proguardFilesgetDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'

signingConfigsigningConfigs.debug

}

}

 

}

 

defgetLayoutLibPath(){

return"${android.getSdkDirectory().getAbsolutePath()}"+"/platforms/"+android.compileSdkVersion+"/data/layoutlib.jar"

}

 

dependencies{

implementationfileTree(dir:'libs',include:['*.jar'])

compileOnlyfiles('sdk/android.jar')

//implementation'com.android.support:support-v4:23.1.0'

implementation'com.android.support:support-v4:25.3.0'

implementation'com.android.support:appcompat-v7:23.1.0'

implementation'com.android.support:leanback-v17:23.1.0'

implementation'com.android.support:design:23.1.0'

implementation'com.jakewharton:butterknife:8.8.1'

annotationProcessor'com.jakewharton:butterknife-compiler:8.8.1'

implementation'me.yokeyword:fragmentation:1.3.6'

//implementationfiles('libs/mstar.jar')

//implementationfiles('libs/klog.jar')

}

 

      在这里面修改最多的,无疑就是导包了,一般来说,一个android的app,会依赖很多很多的包,很多的项目,而引用方式是极其简单。

         Android studio版本更新至3.0,更新中,连带着com.android.tools.build:gradle 工具也升级到了3.0.0,在3.0.0中使用了最新的Gralde 4.0 里程碑版本作为gradle的编译版本,该版本gradle编译速度有所加速,更加欣喜的是,完全支持Java8。当然,对于Kotlin的支持,在这个版本也有所体现,Kotlin插件默认是安装的。

Android应用基础开发入门_第5张图片

 

Android应用基础开发入门_第6张图片

 

     

        Android studio3.0中,compile依赖关系已被弃用,被implementation和api替代,provided被compile only替代,apk被runtime only替代,剩下的看名字就知道了。

    

implementation:只能在内部使用此模块,比如我在一个libiary中使用implementation依赖了gson库,然后我的主项目依赖了这个libiary,那么,我的主项目就无法访问gson库中的方法。这样的好处是编译速度会加快,推荐使用implementation的方式去依赖,如果你需要提供给外部访问,那么就使用api依赖即可。如果你懒得搞懂这个关系,那么简单,你在implementation和API之中,永远选择implementation,除非因为这个包编译不过,再改为API。

compile(api)

api:跟2.x版本的 compile完全相同。用api指令编译,libiary内部依赖对app Module 是可见的,app Module也可以使用Library内部依赖。这种是我们最常用的方式,使用该方式依赖的库将会参与编译和打包。

 

provided(compileOnly)

只在编译时有效,不会参与打包 

可以在自己的moudle中使用该方式依赖一些比如com.android.support,gson这些使用者常用的库,避免冲突。

 

apk(runtimeOnly)

只在生成apk的时候参与打包,编译时不会参与,很少用。

 

testCompile(testImplementation)

testCompile 只在单元测试代码的编译以及最终打包测试apk时有效。

 

debugCompile(debugImplementation)

debugCompile 只在debug模式的编译和最终的debug apk打包时有效

 

releaseCompile(releaseImplementation)

Release compile 仅仅针对Release 模式的编译和最终的Release apk打包。

3,Android studio有非常清晰的工程Project和模块Module的概念,看一下工程结构。

查看代码,studio提供了这么几种方式,我们最常用的是Android和project两种方式。

Android应用基础开发入门_第7张图片

Android:为android开发提供的浏览方式,好处是开发android比较方便,找文件很容易找到。

Project:这个就是文件的物理存储路径,有的时候也非常有用。

    

      我们切换到Android视图,其中的build.gradle有一个是project,其他的每一个module对应着一个。混淆规则,proguard-rules.pro每个module对应一个。

其他的文件很简单,一看便知。除此以外,就是没有module的具体代码了。

 

Android应用基础开发入门_第8张图片

4,Android Studio 常用的快捷键

双击shift : 查找文件

Alt+Enter: 提示,自动补全

Ctrl+E : 最近使用的文件

Ctrl+X: 删除一行

 

 

第三节:我们开发中常用的一些方法

 

1,adb命令

    adb devices

     adb root

     adb pull 电视目录   电脑目录

    adb ush  电脑目录 电视目录

     mount -o remount,rw /system

   cp:拷贝替换apk

   adb install -r 电脑目录

2,PackageManager方法 ActivityManager方法

   pm install -r 电脑目录

    pm disable/enable com.jbd.tvwizard/.PagerActivity

    am start  包名

    am start -n 包名/类名

     am start -a action

    am broadcast -a action --ei(es) key value

  3, dumpsys方法

        dumpsys package

         dumpsys meminfo

         dumpsys activity activities | grep -E "Hist #|Stack #|Task id #"

         dumpsys |grep BroadcastRecord

        dumpsys input可以查看输入设备使用的keylayout文件

        dumpsys window | grep mCurrentFocus

     shareuserid android:sharedUserId="android.uid.system"

    4,app标志

       applicationId+签名

5,apk安装过程

         PackageManagerService是管理者,Settings中保存了应用中的各种包,整个逻辑很复杂,这里只从我们日常需要接触的地方上,简单了解一下apk的安装过程。

 

1,应用安装涉及到的目录

/system/app:系统自带的应用程序,获得adb root 权限才能删除//其他系统应用路径

/data/app:用户程序安装的目录。安装时把apk文件复制到此目录

/data/data:存放应用程序的数据

/data/dalvik-cache:将apk中的dex文件安装到dalvik-cache目录下(dex文件是dalvik虚拟机的可执行文件,当然,ART-Android Runtime的可执行文件格式为.oat,启动ART时,系统会执行dex文件转换至oat文件)

/data/system:该目录下的packages.xml文件。类似于Window的注册表,这个文件是解析apk时由writeLP()创建的,里面记录了系统的permissons,以及每个apk的name,codePath,flag,ts,version,userid等信息,这些信息主要通过apk的AndroidManifest解析获取,解析完apk后将更新信息写入这个文件并保存到flash,下次开机的时候直接从里面读取相关信息并添加到内存相关列表中。当有apk升级,安装或删除时会更新这个文件。
-/data/system/package.xml与/data/system/package.list:packages.list指定了应用的默认存储位置/data/data/com.xxx.xxx;package.xml中包含了该应用申请的权限、签名和代码所在的位置等信息系,并且两者都有同一个userld。之所以每个应用都要一个userId,是因为Android在系统设计上把每个应用当做Linux系统上的一个用户对待,这样就可以利用已有的Linux用户管理机制来设计Android应用,比如应用目录,应用权限,应用进程管理等。

 

2,应用安装总体流程

1:拷贝文件到指定的目录:
在Android系统中,apk安装文件是会被保存起来的,默认情况下,用户安装的apk首先会被拷贝到/data/app目录下,/data/app目录是用户有权限访问的目录,在安装apk的时候会自动选择该目录存放用户安装的文件,而系统出场的apk文件则被放到了/system分区下,包括/system/app,/system/vendor/app,以及/system/priv-app等等,该分区只有ROOT权限的用户才能访问,这也就是为什么在没有Root手机之前,我们没法删除系统出场的app的原因了。

2:解压缩apk,创建应用的数据目录
为了加快app的启动速度,apk在安装的时候,会首先将app的可执行文件dex拷贝到/data/dalvik-cache目录,缓存起来。然后,在/data/data/目录下创建应用程序的数据目录(以应用的包名命名),存放在应用的相关数据,如数据库、xml文件、cache、二进制的so动态库等。

由于DEX字节码位于apk压缩包中,因此,如果程序启动的时候,每次都要从apk文件中解压提取DEX字节码,明显效率不高,因此,Android系统设计了如下策略:

(1) 创建一个"dalvik-cache"文件夹,专门存放DEX字节码,具体位于/data/dalvik-cache

(2) 系统第一次启动时,扫描所有的预装apk文件,提取程序的DEX字节码,经过优化后,存放到dalvik-cache目录中

(3) 每次安装新的apk的时候,也同样提取DEX字节码,优化后放入dalvik-cache目录中

(4) 用户点击应用图标后,直接从dalvik-cache目录中快速加载优化过的DEX字节码,这样程序就可以很快的启动了。

因此Android正在优化的过程,也是就是提取字节码DEX的过程。

3:解析apk的AndroidManifest.xml文件

4:显示快捷方式。

 

第四节:使用手机调试的方法

1,适用场景:

      UI实现

      个别android接口验证

2,方法步骤:

      a,安装驱动,手机型号不是太久,一般不需要这一步

        b,设置或者安全关键等,打开允许安装其他来源的应用,手机型号比较新的一般需要这一步。

        c,设置-》关于手机-》版本号 点击6次,进入开发者模式。

      d,在开发者选项中打开开发者选项开关和允许USB调试的开关。

      e,adb devices 查看连接状态。

第五节:学习方法

    github 上面有大量的可以学习的程序源码,各个种类的都有,对于想学android开发时很有帮助的。

    android提供的demo: google为自己的api提供的一些验证demo,在开发中对接口使用方法上很有帮助,时原生的android的官方api的demo,是最具权威的。目录/development/samples/

 

参考链接:

https://www.jianshu.com/p/d29c37dda256

https://blog.csdn.net/lyc088456/article/details/82415369

https://www.jianshu.com/p/f47e45602ad2

你可能感兴趣的:(android,android,android,tv,移动开发,tvos)