android
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android相关的知识,希望对你有一定的参考价值。
Gradle中buildToolsVersion和TargetSdkVersion的区别是什么
compileSdkVersion, minSdkVersion 和 targetSdkVersion 的作用:他们分别控制可以使用哪些 API ,要求的 API 级别是什么,以及应用的兼容模式。TargetSdkVersion 设为21那么是按6.0设置的(运行时权限),小于21是按6.0以前的方式
binder是安卓中的一个类,它实现了IBinder接口,是安卓中跨进程通信的方式。当绑定服务的时候会返回一个binder对象,然后通过他进行多进程间的通信。
其实进程间通信就是为了实现数据共享。一个程序不同组件在不同进程也叫多进程,和俩个应用没有本质区别。使用process属性可以实现多进程,但是会带来很多麻烦,主要原因是共享数据会失败,弊端有:静态和单利失效,同步失效,sharedprefer可靠性减低等问题
Intent,Binder(AIDL),sharedpre、Messenger
- 使用intent的附加信息extras来传递,通过bundle,传递的是bundle支持的类型,比如基本数据类型、实现pracellable或serializeable的对象
- 使用文件共享,序列化或是sharedpre,不过不适用于读写并发的操作
- 通过message进行传递,在远程服务里创建message对像,在onbind里返回(message.getbinder)。在客户端绑定服务,拿着message对象发消息(可以用bundle)。在远程服务的handlermessage方法就会收到。他是一个个处理的,如果大量并发请求用aidl,mrssage底层就是aidl
- AIDL
- socket可以实现俩个终端通信,也可以在一个设备的俩个进程通信。需要在服务里创建服务端
- ContentProvider(进程间数据共享)和message一样,底层也是binder,除了oncreate方法其他方法(crud)都是运行在bindler线程里。所以在oncerate里不能做耗时操作。在其他应用访问通过uri(主机名),例如gercontentResolver.query(uri,null,null....)
- 有以上6种
使用多进程显而易见的好处就是分担主进程的内存压力。我们的应用越做越大,内存越来越多,将一些独立的组件放到不同的进程,它就不占用主进程的内存空间了。当然还有其他好处,有心人会发现android后台进程里有很多应用是多个进程的,因为它们要常驻后台,特别是即时通讯或者社交应用,不过现在多进程已经被用烂了。典型用法是在启动一个不可见的轻量级私有进程,在后台收发消息,或者做一些耗时的事情,或者开机启动这个进程,然后做监听等。还有就是防止主进程被杀守护进程,守护进程和主进程之间相互监视,有一方被杀就重新启动它。
AIDL的全称是什么?如何工作?
Android interface definition language (android接口定义语言) , 用来跨进程的访问方法。
应用场景:远程服务中的中间人对象,其他应用是拿不到的,那么在通过绑定服务获取中间人对象时,就无法强制转换,使用aidl,就可以在其他应用中拿到中间人类所实现的接口
Aidl使用注意:
客服路径一致 接口名和文件名一致,远程服务的中间人Bind是继承XXX.Sub
Aidl文件中不要有权限修饰符,在客户端也是强转成XXX.Sub
onBind()3种返回:
1.继承Binder用它的对象返回,客户端将bind对象强转成自定义Bind
2.new一个Messenger时用Handler对象作为参数,用Messenger.getBinder()返回,客户端将bind对象强转成Messenger对象,在发送消息
支付宝远程服务
- 定义支付宝的服务,在服务中定义pay方法
- 定义中间人对象,把pay方法抽取成接口
- 把抽取出来的接口后缀名改成aidl
- 在自动生成的PublicBusiness.java文件中,有一个静态抽象类Stub,它已经继承了binder类,实现了publicBusiness接口,这个类就是新的中间人
- 中间人对象直接继承Stub对象,然后在onbind方法中把它返回出去
- 注册这个支付宝服务,定义它的intent-Filter,这样其他应用才可以访问。
需要支付的应用
- 把刚才定义好的aidl文件拷贝过来,注意aidl文件所在的包名必须跟原包名一致
- 远程绑定支付宝的服务,通过onServiceConnected方法我们可以拿到中间人对象
- 把中间人对象通过Stub.asInterface方法强转成定义了pay方法的接口
- 调用中间人的pay方法
对称加密和非对称加密
对称加密,就是加密和解密数据都是使用同一个key,这方面的算法有DES。 非对称加密,加密和解密是使用不同的key。发送数据之前要先和服务端约定生成公钥和私钥,使用公钥加密的数据可以用私钥解密,反之。这方面的算法有RSA。ssh 和 ssl都是典型的非对称加密。
假设手机本地需要缓存数据,如何保证和服务器的数据统一?
比如有个网络更新的功能,activity可以每隔半小时开启service去访问服务器,获取最新的数据。
在缓存文件里面加入时间戳,根据实际情况在一定的时间差内再次访问网络数据、判断URL
在缓存的第一行写一个上当前时间,读的时候判断是不是过期,根据需求看需要多久跟新
分页怎么做的?
分页根据服务器接口参数决定每次加载多少,getviewtype,getitemview
分批处理 解决的是时间等待的问题,不能解决内存占用的问题。
要想解决内存占用问题,可以采用分页方式
Listview如何显示不同条目?
第一种:在getview方法里根据position 进行判断,比如,position等于0是,显示标题,否则显示数据,当然相应的setOnItemClickListener也要去判断
第二种:根据listview里的getItemViewType,getViewTypeCount方法显示不同条目
/** 根据位置 判断当前条目是什么类型 */
@Override
public int getItemViewType(int position) { //20
if (position == datas.size()) { // 当前是最后一个条目
return MORE_ITEM;
}
return getInnerItemViewType(position); // 如果不是最后一个条目 返回默认类型
}
private int getInnerItemViewType(int position) {
return DEFAULT_ITEM;
}
/** 当前ListView 有几种不同的条目类型 */
@Override
public int getViewTypeCount() {
return super.getViewTypeCount() + 1; // 2 有两种不同的类型
}
TextView 、ImageView ,Button,ImageButton他们之间的联系和区别
TextView 控件继承自 View 类。TextView控件的功能是向用户显示文本内容,TextView不允许编辑。
EditText控件继承自 TextView。EditText与TextView 最大的不同是 EditText是可以编辑的
ImageView 控件负责显示图片,其图片来源既可以是资源文件的id,也可以是Drawable对象或 Bitmap 对象,还可以是 内容提供者(Content Provider)的Uri.
Button控件继承自 TextView 类,Button 的用法比较简单,主要是为 Button 设置一个点击事件监听器,并在编写按钮点击事件的处理代码。
ImageButton 控件 继承自 ImageView。与Button相同之处:都用于响应按钮的点击事件
不同之处:ImageButton只能显示图片;Button用于显示文字
屏幕适配
- 开发时选取主流屏幕 1280*120 用相对布局和线性布局 还有权重
- 用dp sp不用px 开发后期在不同的分辨率上测试,没有太大问题可以上线
- 图片适配:切几套图 apk太大
- 布局适配:layout-800x180 针对某一种屏幕 工作量大
- 尺寸适配:dp=px/设备密度=getResource().getDisplayMetrice().dsnsity;
根据不同分辨率的屏幕建立不同的,比如valuse-1280x720,values里的dimens里算出dp,最后引用系统会自动匹配。
(约等于)320*240(0.5) 480*320(1) 480*800(1.5) 1280*720(2)就不用布局适配了
Density-independent pixel (dp)独立像素密度。标准是160dip.即1dp对应1个pixel,计算公式如:px = dp * (dpi / 160),屏幕密度越大,1dp对应 的像素点越多。
上面的公式中有个dpi,dpi为DPI是Dots Per Inch(每英寸所打印的点数),也就是当设备的dpi为160的时候1px=1dp;
mdpi、hdpi、xdpi、xxdpi
其实之前还有个ldpi,但是随着移动设备配置的不断升级,这个像素密度的设备已经很罕见了,所在现在适配时不需考虑。
mdpi、hdpi、xdpi、xxdpi用来修饰Android中的drawable文件夹及values文件夹,用来区分不同像素密度下的图片和dimen值。
那么如何区分呢?Google官方指定按照下列标准进行区分:
在进行开发的时候,我们需要把合适大小的图片放在合适的文件夹里面。下面以图标设计为例进行介绍。
在设计图标时,对于五种主流的像素密度(MDPI、HDPI、XHDPI、XXHDPI 和 XXXHDPI)应按照 2:3:4:6:8 的比例进行缩放。例如,一个启动图标的尺寸为48x48 dp,这表示在 MDPI 的屏幕上其实际尺寸应为 48x48 px,在 HDPI 的屏幕上其实际大小是 MDPI 的 1.5 倍 (72x72 px),在 XDPI 的屏幕上其实际大小是 MDPI 的 2 倍 (96x96 px),依此类推。
来源: http://www.cocoachina.com/android/20151030/13971.html
- 权重适配:weight 只有线性布局有
- 代码适配:getWindowManager().getDefaultDisplay().getWidth();获得屏幕的宽高
- 指定宽高的时候,采用 dip 的单位,dp单位动态匹配
- 尽量使用线性布局,相对布局,如果屏幕放不下了,可以使用 ScrollView(可以上下拖动)
请介绍下Android中常用的五种布局。
FrameLayout(帧布局),LinearLayout (线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局)
- FrameLayout:从屏幕的左上角开始布局,叠加显示, 实际应用 播放器的暂停按钮.
- LinearLayout:线性布局,他首先是一个一个从上往下罗列在屏幕上。每一个LinearLayout里面又可分为垂直布局、水平布局。当垂直布局时,每一行就只有一个元素,多个元素依次垂直往下;水平布局时,只有一行,每一个元素依次向右排列。
- AbsoluteLayout:用X,Y坐标来指定元素的位置android:layout_x="20px" ,android:layout_y="12px" ,指定平板机型的游戏开发、机顶盒开发中经常用到绝对布局
- RelativeLayout:在相对的布局中主要就进行避免覆盖的问题,就是组件1可能会覆盖在组件2上(屏幕适配),在相对的布局中主要就进行避免覆盖的问题,就是组件1可能会覆盖在组件2上
- TableLayout:有几行,就有几个<TableRow/>,有几列,那么在<TableRow>中就有几个<TestView>,TableRow的子节点的宽和高是包裹内容,不需要指定宽高
RelativeLayout和FrameLayout的区别
Padding和Margin有什么区别?
Padding 是控件内容的距离margin是控件和控件间的距离
对android主线程的运用和理解
主ui线程不能执行耗时的操作
什么Context
Android工程环境中像Activity、Service、BroadcastReceiver等系统组件,而这些组件并不是像一个普通的Java对象new一下就能创建实例的了,而是要有它们各自的上下文环境,这就是Context。可以这样讲,Context是维持Android程序中各组件能够正常工作的一个核心功能类。
Context功能很多,可以弹出Toast、启动Activity、启动Service、发送广播、操作数据库等等等等都需要用到Context。
Android程序与Java程序的区别?
Android程序用android sdk开发,java程序用javasdk开发.
Android SDK引用了大部分的Java SDK,少数部分被Android SDK抛弃,比如说界面部分,java.awt swing package除了java.awt.font被引用外,其他都被抛弃,在Android平台开发中不能使用。 android sdk 添加工具jar httpclient , pull opengl
dvm的进程和Linux的进程, 应用程序的进程是否为同一个概念
Dvm的进程是dalivk虚拟机进程,每个android程序都运行在自己的进程里面,
每个android程序系统都会给他分配一个单独的liunx uid(user id),
每个dvm都是linux里面的一个进程.所以说这两个进程是一个进程.
在不同的屏幕上显示内容不同的情况,其实这个问题我们往往是用滚动视图来解决的,也就是 ScrowView;需要
注意的是 ScrowView 中使用 layout_weight 是无效的,既然使用 ScrowView 了,就把它里面的控件的大小都设成固定的吧。
Android UI中的View如何刷新。
在主线程中 拿到view调用Invalide()方法,在子线程里面可以通过postInvalide()方法;
invalidate();//主线程,刷新当前视图 导致 执行onDraw执行
postInvalidate();//子线程
什么是ANR(异步加载) 如何避免它?
android在主线程是不能加载网络数据或图片、数据库查询、复杂业务逻辑处理以及费时任务操作,因为Android的UI操作并不是线程安全的,并且所有涉及UI的操作必须在UI线程中完成。Android应用在5s内无响应的话会导致ANR(Application Not Response),这就要求开发者必须遵循两条法则:1、不能阻塞UI线程,2、确保只在UI线程中访问Android UI工具包。
Activity 5秒 broadcast10秒,服务20秒,耗时的操作在主thread里面完成
解决办法:Thread + Handler + Message ,Thread + Handler + post,AsyncTask,intentservice
runOnUiThread(Runnable)在子线程中直接使用该方法,可以更新UI
Android中的动画有哪几类,它们的特点和区别是什么?
两种,一种是补间动画、还有一种是帧动画。
补间动画是放置到res/anim/下面
帧动画是放置到res/drawable/下面
补间动画
- 如果动画中的图像变换比较有规律时,可以才用自动生成中间图像的方式生成动画,例如图像的移动、旋转、缩放、透明度渐变、正方形变圆形等,这些图像变化过程中的图像都可以根据一定的算法自动生成,我们只需要指定动画的第一帧和最后一帧图像即可,这种自动生成中间图像的动画就是补间动画。
- 原形态变成新形态时为了过渡变形过程,生成的动画就叫补间动画
- 补间动画,只是一个动画效果,组件其实还在原来的位置上,xy没有改变
- 位移、旋转、缩放、透明
帧动画:传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影,一张张图片不断的切换,形成动画效果,要自己指定每一帧
在drawable目录下定义xml文件,子节点为animation-list,在这里定义要显示的图片和每张图片的显示时长
属性动画:动画的对象除了传统的View对象,还可以是Object对象,动画结束后,Object对象的属性值被实实在在的改变了
实现侧边栏、和指示器效果、页面滑动有几种方式
侧边栏:自定义、slidingmenu、DrawerLayout 、SlidingDrawer
指示器效果:自定义、viewpager里面的PagerTabStrip、ActionBar Tab标签、viewpagerindicate、FragmentTabHost、TabActivity、radiobutton
页面滑动:自定义、viewpager、手势识别器,其实就是onTouchEvent提供的简单工具类,onTouchEvent将触摸事件委托给了手势识别器
Android工程的目录结构
src:项目的java代码
assets:资源文件夹,存放视频或者音乐等较大的资源文件
bin:存放应用打包编译后的文件
res:资源文件夹,在这个文件夹中的所有资源,都会有资源id,读取时通过资源id就可以读取
资源id不能出现中文
如何缩减APK包大小
代码
保持良好的编程习惯,不要重复或者不用的代码,谨慎添加libs,移除使用不到的libs。 使用proguard混淆代码,它会对不用的代码做优化,并且混淆后也能够减少安装包的大小。 native code的部分,大多数情况下只需要支持armabi与x86的架构即可。如果非必须,可以考虑拿掉x86的部分。
资源
使用Lint工具查找没有使用到的资源。去除不使用的图片,String,XML等等。 assets目录下的资源请确保没有用不上的文件。 生成APK的时候,aapt工具本身会对png做优化,但是在此之前还可以使用其他工具如tinypng对图片进行进一步的压缩预处理。 jpeg还是png,根据需要做选择,在某些时候jpeg可以减少图片的体积。 对于9.png的图片,可拉伸区域尽量切小,另外可以通过使用9.png拉伸达到大图效果的时候尽量不要使用整张大图。
策略
有选择性的提供hdpi,xhdpi,xxhdpi的图片资源。建议优先提供xhdpi的图片,对于mdpi,ldpi与xxxhdpi根据需要提供有差异的部分即可。
尽可能的重用已有的图片资源。例如对称的图片,只需要提供一张,另外一张图片可以通过代码旋转的方式实现。
能用代码绘制实现的功能,尽量不要使用大量的图片。例如减少使用多张图片组成animate-list的AnimationDrawable,这种方式提供了多张图片很占空间。
多线程断点下载
单线程的话从输入流的第0个字节读取
原理:服务器CPU分配给每条线程的时间片相同,服务器带宽平均分配给每条线程,所以客户端开启的线程越多,就能抢占到更多的服务器资源。所以要用多线程去读取。
请求网络时首先获取资源长度设置被进度条,然后除以要开启的线程数,计算出每个线程应该下载多少字节。然后每个线程去请求网络读取数据。
//设置本次http请求所请求的数据的区间
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
//请求部分数据,相应码是206
if(conn.getResponseCode() == 206){
//流里此时只有1/3原文件的数据
InputStream is = conn.getInputStream();
int length = conn.getContentLength();
//设置本次http请求所请求的数据的区间
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
//请求部分数据,相应码是206
if(conn.getResponseCode() == 206){
//流里此时只有1/3原文件的数据
InputStream is = conn.getInputStream();
特别注意: 对于移动端来说,如果不是比较大的文件,不建议使用这种方式上传,因为断点续传是通过分片上传实现的,上传单个文件需要进行多次网络请求,效率不高。
coverview原理:
这个参数用于将之前加载好的布局进行缓存,以便之后可以进行重用,在 getView()方法中进行了判断,如果 convertView为空,则使用
LayoutInflater去加载布局,如果不为空则直接对 convertView进行重用
layout_weight(为t),屏幕适配经常用
等分的长度“先各自分配各自控件的长度,然后将剩余的长度按照权重的比例layout_weight的大小进行设置。
如果父类的组件的设置为vertical,那么layout_height=0(layout_weight=1)
如果父类的组件的设置为horionzal,那么layout_width=0(layout_weight=1)
android的启动流程
当程序启动Linux内核后,会加载各种驱动和数据结构,当有了驱动以后,开始启动Android系统同时会加载用户级别的第一个进程init(system\\core\\init.c),加载init.rc文件,会启动一个Zygote进程,此进程是Android系统的一个母进程,用来启动Android的其他服务进程,然后接着在里面启动各种硬件服务和activity。Android系统启动完成,打开了Luncher应用的Home界面。
Logcat
1. Log.v()
这个方法用于打印那些最为琐碎的,意义最小的日志信息。对应级别 verbose,是Android日志里面级别最低的一种。
2. Log.d()
这个方法用于打印一些调试信息, 这些信息对你调试程序和分析问题应该是有帮助的。对应级别 debug,比 verbose高一级。
3. Log.i()
这个方法用于打印一些比较重要的数据,这些数据应该是你非常想看到的,可以帮你分析用户行为的那种。对应级别 info,比 debug高一级。
4. Log.w()
这个方法用于打印一些警告信息,提示程序在这个地方可能会有潜在的风险,最好去修复一下这些出现警告的地方。对应级别 warn,比 info高一级。
5. Log.e()
这个方法用于打印程序中的错误信息,比如程序进入到了 catch语句当中。当有错误信息打印出来的时候,一般都代表你的程序出现严重问题了,必须尽快修复。对应级别 error,比 warn高一级.
推送
所有需要客户端被动接收信息的功能模块,都可以用推送实现,比如A想给B发消息,A调服务器接口,服务器只是存数据,它调推送的接口,推送去去找B。推送用的是xmpp协议, 是一种基于TCP/IP的协议, 这种协议更适合消息发送
- socket 套接字, 发送和接收网络请求
- 长连接 keep-alive, 服务器基于长连接找到设备,发送消息
- 心跳包 , 客户端会定时(30秒一次)向服务器发送一段极短的数据,作为心跳包, 服务器定时收到心跳,证明客户端或者,才会发消息.否则将消息保存起来,等客户端活了之后(重新连接),重新发送.
系统架构:
系统分层: (由下向上) 【如图】
1、安卓系统分为四层,分别是 Linux 内核层、Libraries 层、FrameWork层,以及 Applications 层:
- Linux 内核层:包含 Linux 内核和驱动模块(比如 USB、Camera、蓝牙等)
- Libraries 层:这一层提供动态库(也叫共享库) 、android 运行时库、Dalvik 虚拟机等。编程语言主要为 C 或 C++,所以可以简单的看成 Native 层。
- FrameWork层:这一层大部分用 java 语言编写,它是 android 平台上 Java 世界的基石。
- Applications 层:应用层
FrameWork层 -------- Java 世界
Libraries 层 -------- Native 世界
Linux 内核层 -------- Linux OS
Java 世界和 Native 世界间的通信是通过 JNI 层,JNI 层和 Native 世界都可以直接调用系统底层
2、Dalvik VM 和传统 JVM 的区别:
传统的 JVM:编写.java 文件→编译为.class 文件 → 打包成.jar 文件
Dalvik VM: 编写.java 文件 → 编译为.class 文件 → 打包成.dex文件 → 打包成.apk文件(通过 dx工具)
将所有的类整合到一个文件中,提高了效率。更适合在手机上运行
Android逆向工程是什么?
Android逆向工程主要是指反编译和二次打包,通过反编译可以破解一些有用信息,而通过二次打包则可以产生一些山寨应用。Android逆向工程是一个很有意思的话题,如果开发者对其感兴趣的话,推荐大家阅读下逆向相关的书籍,比如《Android软件安全与逆向分析》。
以上是关于android的主要内容,如果未能解决你的问题,请参考以下文章