android面试题总结

来源:互联网 发布:csgo数据互换器永久 编辑:程序博客网 时间:2024/06/05 21:01

自我介绍:
您好,我是xxx,从事android开发也有好几年了,总共呆过两家公司,第一家是xx,干了1年,在这家公司做过3个项目,刚开始的时候主要写一些需求文档,用xmind整理项目功能,做一些简单的界面,大家都知道搞it的技术很重要,所以我在完成自己的工作之余就经常看其他模块的实现代码,尽快提升自己的技术,也积极参与同事的讨论,提出一些自己的想法,很快业务也熟悉了;我记得在第二个项目的时候就能独立完成一些模块的功能,(做完第三个项目的时候/xxxx年xx月的时候/一年后)后来为了有更好的发展,就来到了第二家公司;这家公司对我的提升很多,项目很多,做了5、6个吧,包括电商类的,金融类的,教育类的,医疗类的都有,其中大部分是团队开发,也有独立开发的,比如哪个哪个,在团队开发中,我主要担任的也是核心开发人员,负责框架的搭建,需求的整理和分析,项目任务的安排和进度的把控,及项目规范性和性能的把控;这家公司成长很多,挺感谢公司的,不过现在做的项目和之前的业务都差不多,公司组织架构也比较稳定了,觉得发展到了一个瓶颈,加上现在移动互联发展这么快,新技术天天在更新,智能家居,虚拟现实,vr,直播都是比较火的方向,我觉得也是以后的发展方向,it行业不跟着时代跟着技术进步,迟早会被淘汰,最近考虑了一下,还是决定离职,换个环境,周围的同事朋友也有劝我不要这么做的,我是一个不喜欢安逸的人,老这样也没意思,也为了以后的发展还是要大胆的尝试探索,投了一下简历,也算是和咱公司有缘分,就到这来面试了,说了这么多,口也渴了,停顿一秒。。。。面试官该说话了(当然前面随时会打断),应对问题,面试官一般问一些公司情况,个人情况,就会让介绍项目,那就开始项目介绍节奏。。。,如果没有让介绍项目,谈的不多,有空档就主动介绍项目(不要冷场,挺尴尬的),
项目介绍:这个项目是6月份开始做的,9月份第一版上线,

1.准备好录音笔,模拟面试的时候就使用(真正去面试的时候,第一次都会忘了录,或录音失败),面试录音诊断是找到面试问题的唯一利器
2.学历证(本科)和公司章提前买好,不要到了入职还没有,影响得之不易的offer,加急制作,费用高
3.改简历,投简历,开始每天150份,智联,51job,拉钩,boss,猎聘,100offer等,开始面试电话可能不多,耐心等待,如果投完900家,还是没有什么电话,可以重新注册一个账号再投
4.招聘信息共享,待会面试题,一个没成,后续的补上,有备而去,很重要
5.到了面试地点,去早了直接进去不要等,不能按时到,提前和人事说一下(如果能联系上)
6.见到了人事,寒暄几句(天冷天热,过来快慢,是否堵车,公司情况(位置好坏,好找不好找,办公区环境(大,宽敞,干净))),恰当的夸夸她(根据情况,不要生硬),询问技术面试官的职位和姓,见到时好打招呼,一定要起身,男的主动握手(女的就不要了,除非她先伸手)
7.如果两个或以上,确定哪个是头,主要和他交流,其他适当照顾到
8.自我介绍,介绍项目时,一定要自然,在回顾过去,眼睛可以平时或向上一点,不能左右顾盼

技术升级:算法,底层,项目技术要精(项目也许不在多),框架洗讲,直播,sdk开发,自定义view,RxJava,reactnative,插件化

1.下拉刷新时头部导航条的透明度会随着scrollview的滑动距离改变而改变,滑动到一定距离时,界面右下方会出现一个小火箭,点击它,界面会有一个置顶功能。首先我会自定义一个组件,继承LinearLayout,添加一个header view,保证是第一个添加到linearlayout的最上端,设置topMargin的值为负的header View高度,即将其隐藏在最上方,之后需要添加footer view,由于是线性布局可以直接添加,只要AdapterView的高度是MATCH_PARENT,那么footer view就会被添加到最后,并隐藏。下来刷新和上拉加载都要进行手指滑动距离的判断,当header view的topMargin>=0时,说明已经完全显示出来了,修改header view 的提示状态,footer 准备刷新,手指移动过程,还没有释放移动footer view高度同样和移动header view高度是一样,都是通过修改header view的topmargin的值来达到。为了实现偏移控制,一般自定义View/ViewGroup都需要重载computeScroll()方法,我会判断scrollview的滑动距离动态去给导航条的背景设置透明度,滑动渐变的效果,当滑到一定距离时,我会把小火箭显示出来,点击是会调用scrollview的scrollTo()方法,实现置顶功能。

2.图片的缓存处理
在加载图片的时候,如果图片比较大时而界面上只需要显示一小块,那么会造成内存浪费,继续加载更多也可能会出现内存溢出,这时使用缓存技术是必备的,这里我用的是IamgeLoader的LruCache类,首先将ImageLoader类设成单例,并在构造函数中初始化了LruCache类,把它的最大缓存容量设为最大可用内存的1/8。然后又提供了其它几个方法可以操作LruCache,以及对图片进行压缩和读取。首先自定义一个继承自ScrollView的类,这样就允许用户可以通过滚动的方式来浏览更多的图片。这里提供了一个loadMoreImages()方法,是专门用于加载下一页的图片的,因此在onLayout()方法中我们要先调用一次这个方法,以初始化第一页的图片。然后在onTouch方法中每当监听到手指离开屏幕的事件,就会通过一个handler来对当前ScrollView的滚动状态进行判断,如果发现已经滚动到了最底部,就会再次调用loadMoreImages()方法去加载图片。在这个方法中,使用了一个循环来加载这一页中的每一张图片,每次都会开启一个LoadImageTask,用于对图片进行异步加载。然后在LoadImageTask中,首先会先检查一下这张图片是不是已经存在于SD卡中了,如果还没存在,就从网络上下载,然后把这张图片存放在LruCache中。接着将这张图按照一定的比例进行压缩,并找出当前高度最小的一列,把压缩后的图片添加进去就可以了。另外,为了保证图片都能够合适地被回收,这里还加入了一个可见性检查的方法,即checkVisibility()方法。这个方法的核心思想就是检查目前照片墙上的所有图片,判断出哪些是可见的,哪些是不可见。然后将那些不可见的图片都替换成一张空图,这样就可以保证程序始终不会占用过高的内存。当这些图片又重新变为可见的时候,只需要再从LruCache中将这些图片重新取出即可。如果某张图片已经从LruCache中被移除了,就会开启一个LoadImageTask,将这张图片重新加载到内存中。

断点续传:
1:当用户点击下载按钮是就要把文件路径的信息传给后台由service的onstartcom的方法接受穿过来的参数,由于service和activity都是主线程不能做耗时操作所以要开启一个子线程去做耗时操作网络下载和把数据写到本地文件并且把进度信息本地文件保存到数据库并把进度传给activity通过广播发送网络文件

网络下载的关键点:

1:获取网络文件的长度2:在本地创建一个文件,设置其长度3:从数据库中获取上次下载的进度4:从上次下载的位置下载数据,同时保存进度到数据库5将下载进度回传activity6:下载完成后删除下载信息

3.流式布局的实现
自定义ViewGroup,重点重写下面两个方法
1)onMeasure:测量子view的宽高,设置自己的宽和高
2)onLayout:设置子view的位置,onMeasure:根据子view的布局文件中属性,来为子view设置测量模式和测量值
当这个流式布局在被加载如内存并显示在屏幕上这一过程中,首先会调用view.measure(w,h)这个方法,表示测量view的宽度与高度,其中参数w与h分别表示这个控件的父控件的宽高。在view.measure()方法的调用过程中又会调用view本身的一个回调方法,onMeasure(),这个是view自身的一个回调方法,用于让开发者在自定义View的时候重新计算自身的大小。一般会在这个方法中循环遍历,计算出这个控件的全部子孙控件的宽高。在View的宽高计算完成以后,考虑将这个控件显示到屏幕的指定位置上,此时view的onLayout()方法会被调用。 一般同时会在这个方法中计算出全部子孙控件在这个控件中的位置。在onMeasure()中首先通过循环,遍历这个控件的所有子控件,同时调用子控件的measure()方法,这时measure方法的两个参数是控件能给这个子控件的最大宽高这里getChildMeasureSpec()方法的作用是用来计算一个合适子视图的尺寸大小(宽度或者高度),结合我们从子视图的LayoutParams所给出的MeasureSpec信息来获取最合适的结果。比如,如果这个View知道自己的大小尺寸,并且子视图的大小恰好跟父窗口一样大,父窗口必须用给定的大小去layout子视图,通过循环遍历,控制每个item子控件的显示位置,如果当前行还能放得下一个item,就放到当前行,如果放不下就放到下一行的最左边。

4.支付功能:
微信支付:
1)从微信开放平台上下载微信支付的SDK,使用其libammsdk.jar包。
2)在微信开放平台注册我们的应用(应用需要填写包名,应用的签名等)可以获取到APPID和APPSecret,然后申请开通支付功能,提交企业以及银行账户资料等待审核,审核通过了在线签订合同,之后就可以进行微信支付了,同时商户会收到邮件获得财付通商户账户,支付秘钥key,财付通权限秘钥,财付通商户标示id等开发关键数据。
3)预付订单:当用户确定购买商品之后,首先请求微信服务器获取access_tocken,提交预付订单package,添加签名,提交预付订单后会获取微信服务器返回的prepayid,接着把请求参数返回给手机端。
4)发起支付:调用api.sendReq(req);发起支付,发起支付的时候需要传入支付相关信息,相关信息以KEY-VALUE键值对方式用&拼接组成。例如:订单信息(订单号,交易付款时间,购买数量等),商品信息(商品名称,商品单价,商品描述等),支付信息(支付金额等)和notify_url(这个是通知地址,也就是微信的服务器把支付后成功与否等结果信息同步给我们公司服务器时候使用的地址)等。还需要拼接一个重要的签名参数sign,sign的值是上述这些交易信息MD5加密签名后的结果。
5)支付信息提交后会提交到微信的服务器,微信服务器完成整个支付功能后会给用户(客户端和服务器分别提示)成功或者失败的提示。
支付宝支付:
1)首先从支付宝平台下载SDK,使用其中的alipay.jar包。
2)当用户确定购买商品之后,首先生成订单,我们订单生成的规则就是用两个2-9的随机数+当前时间的毫秒值作为订单号。
3)调用支付宝的接口:调用支付宝的支付方法(方法Alipay.pay(String info)),支付方法需要传入支付相关信息,相关信息以KEY-VALUE键值对方式用&拼接组成。订单信息(订单号,交易付款时间,购买数量等),商品信息(商品名称,商品单价,商品描述等),支付信息(买方,卖方支付宝账号信息,支付金额等)和notify_url(这个是通知地址,也就是支付宝的服务器把支付后成功与否等结果信息同步给我们公司服务器时候使用的地址)等。还需要拼接一个重要的签名参数sign,sign的值是上述这些交易信息RSA签名后的结果。
4)支付信息提交后会提交到支付宝的服务器,支付宝的服务器完成整个支付功能后会给用户成功或者失败的提示界面。这个过程都是支付宝的功能。支付宝支付完成后,也会把信息同步给我们的服务器(也就是通过前面的notify_url这个地址)。
5)我们的服务器处理完毕之后,调用pay方法的时候其实也会接到返回值。返回值是json格式里面有很多信息,我们主要从中取结果状态码(resultStatus),根据状态码的数值判断支付是否成功,除了支付宝本身的提示界面以外,我们也会给用户一个我们自己的提示。

5.xmpp实现聊天功能:
我项目中即时通讯主要使用XMPP实现的,它有一个开源项目androidpn,使用的时候客户端要用到asmack.jar包,这个jar包提供了通讯的功能,主要使用jar包中的XMPPConnection类。主要实现如下:
1)使用XMPPConnection类与服务器openfire建立持久连接
2)在持久连接基础上进行用户注册(用户注册之后服务器就会记录该用户的信息,下次就能够识别)
3)在连接基础上进行用户登录认证(登录之后服务端会知道当前用户的状态)服务端只要记录了该用户的信息,就可以往用户手机上发送推送的信息了。
实现通讯功能主要是使用jar包中的 Chat 类完成信息的发送,发送信息的时候要注意的是用户的格式是用户名称@域/命名空间(例如:要给loupengfei聊天的话地址为:loupengfei@127.0.0.1/AndroidpnClient),这样服务端就能够把信息转给响应名称的人。
接收信息:
1)在用户建立连接的时候就定义了一个指定命名空间的解析器provider(负责解析服务端发过来的xml格式的消息)
2)同时也注册一个包监听器PacketListener,当有信息发送过来的时候我们定义的解析器会收到信息,在解析中使用PULL解析方式把xml中信息解析出来然后封装成我们自定义的一个IQ的子类(就是消息Bean),然后带着消息进入到包监听类中,在包监听类中结合handler把聊天内容等更新到UI上。

6.自定义圆形头像:
1)首先通过setImageBitmap()方法设置图片Bitmap
2)进入构造函数CircleImageView()获取自定义参数,以及调用setup()函数
3)进入setup()函数(非常关键),进行图片画笔边界画笔(Paint)一些重绘参数初始化:构建渲染器BitmapShader用Bitmap来填充绘制区域,设置样式和内外圆半径计算等,以及调用updateShaderMatrix()函数和 invalidate()函数
4)进入updateShaderMatrix()函数,计算缩放比例和平移,设置BitmapShader的Matrix参数等
5)触发ondraw()函数完成最终的绘制,使用配置好的Paint先画出绘制内圆形来以后再画边界圆形。

7.瀑布流照片墙的实现
瀑布流的布局方式虽然看起来好像排列的很随意,其实它是有很科学的排列规则的。整个界面会根据屏幕的宽度划分成等宽的若干列,由于手机的屏幕不是很大,这里我就分成三列。每当需要添加一张图片时,会将这张图片的宽度压缩成和列一样宽,再按照同样的压缩比例对图片的高度进行压缩,然后在这三列中找出当前高度最小的一列,将图片添加到这一列中。之后每当需要添加一张新图片时,都去重复上面的操作,就会形成瀑布流格局的照片墙。

8.屏幕适配
1)比重适配,控件在其父布局中的显示权重,一般用于线性布局中,如果控件过多,且显示比例也不相同的时候,控制起来就比较麻烦了,毕竟反比不是那么好确定的。
2)多个布局文件适配,就是对不同大小的屏幕提供不同的layout。比如横竖屏的切换,可以在res目录下建立layout-port和layout-land两个目录,里面分别放置竖屏和横屏两种布局文件,以适应对横屏竖屏自动切换。
3)多个drawable适配(图片的适配),就是对不同密度的屏幕提供不同的图片。在进行开发的时候,我们需要把合适大小的图片放在合适的文件夹里面。应尽量使用.9格式的图片,如需对密度为low的屏幕提供合适的图片,需新建文件夹drawable-ldpi/,并放入合适大小的图片。相应的,medium对应drawable-mdpi/,high对应drawable-hdpi/,extra high对应drawable-xhdpi/。
4)多个values适配,为了优质的用户体验,需要去针对不同的dpi设置,编写多套数值文件,要把生成的所有values文件夹放到res目录下,当设计师把UI高清设计图给你之后,你就可以根据设计图上的尺寸,以某一个分辨率的机型为基础,找到对应像素数的单位,然后设置给控件。

9.内存优化
1)静态变量引起内存泄露
静态变量是类相关的变量,它的生命周期是从这个类被声明,到这个类彻底被垃圾回收器回收才会被销毁。所以,一般情况下,静态变量从所在的类被使用开始就要一直占用着内存空间,直到程序退出。如果不注意,静态变量引用了占用大量内存的资源,造成垃圾回收器无法对内存进行回收,就可能造成内存的浪费。
2)使用Application的Context
在Android中,Application Context的生命周期和应用的生命周期一样长,而不是取决于某个Activity的生命周期。如果想保持一个长期生命的对象,并且这个对象需要一个 Context,就可以使用Application对象。可以通过调用Context.getApplicationContext()方法或者 Activity.getApplication()方法来获得Application对象。
3)及时关闭资源
Cursor是Android查询数据后得到的一个管理数据集合的类。正常情况下,如 果我们没有关闭它,系统会在回收它时进行关闭,但是这样的效率特别低。如果查询得到的数据量较小时还好,如果Cursor的数据量非常大,特别是如果里面 有Blob信息时,就可能出现内存问题。所以一定要及时关闭Cursor。
4)避免使用浮点数
通常的经验是,在Android设备中,浮点数会比整型慢两倍。
5)使用实体类比接口好
按照传统的观点Map会更好些,因为这样你可以改变他的具体实现类,只要这个类继承自Map接口。传统的观点对于传统的程序是正确的,但是它并不适合嵌入式系统。调用一个接口的引用会比调用实体类的引用多花费一倍的时间。如果HashMap完全适合你的程序,那么使用Map就没有什么价值。如果有些地方你不能确定,先避免使用Map,剩下的交给IDE提供的重构功能好了。(当然公共API是一个例外:一个好的API常常会牺牲一些性能)
6)避免使用枚举
枚举变量非常方便,但不幸的是它会牺牲执行的速度和并大幅增加文件体积。
使用枚举变量可以让你的API更出色,并能提供编译时的检查。所以在通常的时候你毫无疑问应该为公共API选择枚举变量。但是当性能方面有所限制的时候,你就应该避免这种做法了。
7)使用Bitmap及时调用recycle()
Bitmap是内存消耗大户,绝大多数的OOM崩溃都是在操作Bitmap时产生的,我们需要根据需求去加载图片的大小,例如在列表中仅用于预览时加载缩略图,只有当用户点击具体条目想看详细信息的时候,这时另启动一个fragment/activity/对话框等等,去显示整个图片。直接使用ImageView显示bitmap会占用较多资源,特别是图片较大的时候,可能导致崩溃,使用BitmapFactory.Options设置inSampleSize, 这样做可以减少对系统资源的要求。使用Bitmap过后,就需要及时的调用Bitmap.recycle()方法来释放Bitmap占用的内存空间,而不要等Android系统来进行释放。
8)对Adapter进行优化
如果一个对象只具有软引用,那么如果内存空间足够,垃圾回收器就不会回收它;如果内存 空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。软引用可以和一个引用队 列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
如果一个对象只具有弱引用,那么在垃圾回收器线程扫描的过程中,一旦发现了只具有弱引 用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。弱 引用也可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联 的引用队列中。
弱引用与软引用的根本区别在于:只具有弱引用的对象拥有更短暂的生命周期,可能随时被回收。而只具有软引用的对象只有当内存不够的时候才被回收,在内存足够的时候,通常不被回收。

listview如何优化?
1)convertView复用,对convetView进行判空,当convertView不为空时重复使用,为空则初始化,从而减少了很多不必要的View的创建
2)定义一个ViewHolder,封装Listview Item条目中所有的组件,将convetView的tag设置为ViewHolder,不为空时通过ViewHolder的属性获取对应组件即可
3)当ListView加载数据量较大时可以采用分页加载和图片异步加载
handler的原理?
Handler主要用于线程间的通信。
一个Handler允许发送和处理Message和Runable对象,UI主线程会自动分配一个Looper(消息轮询器),每个Looper中封装着MessageQueue(消息队列),遵循先进先出原则。Looper负责不断的从自己的消息队列里取出队头的任务或消息执行。一般是在子线程执行完耗时操作之后,通过Handler的sendMessage或post方法将Message和Runable对象传递给MessageQueue,而且在这些对象离开MessageQueue时,Handler负责执行他们(用到handleMessage方法,主要执行刷新UI的代码)。
其中Message类就是定义了一个信息,这个信息中包含一个描述符和任意的数据对象,这个信息被用来传递给Handler.Message对象提供额外的两个int域和一个Object域。
Tcp和Udp的区别和联系?
TCP—传输控制协议,提供的是面向连接、可靠的字节流服务,传输数据前经过“三次握手”建立连接,保证数据传输的可靠性,但效率比较低。一般用于对于数据传输安全性较高的场合。
UDP—用户数据报协议,是一个简单的面向数据报的运输层协议,面向无连接。UDP不提供可靠性,数据传输可能发生错序,丢包,但效率较高。一般用于对于实时性要求较高的场合。
方法的重写和重载?
重写是子类的方法覆盖父类的方法,要求方法名和参数都相同 。
重载是在同一个类中的两个或两个以上的方法,拥有相同的方法名,但是参数却不相同,方法体也不相同,最常见的重载的例子就是类的构造函数。
ArrayList和LinkedList区别?
存数据,ArrayList数组存储数据,索引值以下标来搜索,查询比较方,删除增加比较麻烦,但是linkedList以链表式存储数据,对于增删比较方便。
Final ,finally,finalized,区别?
final用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。
finally是异常处理语句结构的一部分,表示总是执行。
finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。
加载大图、多图如何防止内存溢出?
大图:解析每张图片的时候都先检查一下图片的大小,确保图片不会超出内存大小,如果只需要加载一张比较小的图片展示出来,显然加载大图的原图是不值得的,可以通过设置BitmapFactory.Options中inSampleSize的值实现图片压缩。
多图:屏幕上显示的图片可以通过滑动屏幕等事件不断地增加,最终导致OOM,可以使用LruCache类,主要算法原理是把最近使用的对象用强引用存储在 LinkedHashMap 中,并且把最近最少使用的对象在缓存值达到预设定值之前从内存中移除。
如何人解决anr?forceclose(强制关闭)
(1) AsyncTask,其中doInBackground()和onPostExecute(Result)两个方法非常重要
doInBackground() 这个方法运行在后台线程中,主要负责执行那些很耗时的操作,如访问网络。该方法必须重写。
onPostExecute(Result) 这个方法运行于UI主线程,在doInBackground(Params…)方法执行后调用,该方法用于接收后台任务执行后返回的结果,刷新UI显示。
(2.)子线程 + handler
在子线程中执行完耗时操作需要刷新UI时,通过handler.sendMessage()发消息给主线程, 然后在主线程Handler中的handleMessage()方法中执行刷新UI操作
android中内存如何优化?
1)谨慎使用静态变量
2)使用Application的Context
3)及时关闭资源(io流、cursor对象)
4)使用Bitmap及时调用recycle()
5)对Adapter进行优化
冒泡排序:
for (int i = 0; i < score.length-1; i++){ //最多做n-1趟排序
for(int j = 0 ;j < score.length - i - 1; j++){
if(score[j] < score[j + 1]){ //把小的值交换到后面
int temp = score[j];
score[j] = score[j + 1];
score[j + 1] = temp;
}
}
}
微信支付:
1)从微信开放平台上下载微信支付的SDK,使用其libammsdk.jar包。
2)在微信开放平台注册我们的应用(应用需要填写包名,应用的签名等)可以获取到APPID和APPSecret,然后申请开通支付功能,提交企业以及银行账户资料等待审核,审核通过了在线签订合同,之后就可以进行微信支付了,同时商户会收到邮件获得财付通商户账户,支付秘钥key,财付通权限秘钥,财付通商户标示id等开发关键数据。
3)预付订单:当用户确定购买商品之后,首先请求微信服务器获取access_tocken,提交预付订单package,添加签名,提交预付订单后会获取微信服务器返回的prepayid,接着把请求参数返回给手机端。
4)发起支付:调用api.sendReq(req);发起支付,发起支付的时候需要传入支付相关信息,相关信息以KEY-VALUE键值对方式用&拼接组成。例如:订单信息(订单号,交易付款时间,购买数量等),商品信息(商品名称,商品单价,商品描述等),支付信息(支付金额等)和notify_url(这个是通知地址,也就是微信的服务器把支付后成功与否等结果信息同步给我们公司服务器时候使用的地址)等。还需要拼接一个重要的签名参数sign,sign的值是上述这些交易信息MD5加密签名后的结果。
5)支付信息提交后会提交到微信的服务器,微信服务器完成整个支付功能后会给用户(客户端和服务器分别提示)成功或者失败的提示。
支付宝支付:
1)首先从支付宝平台下载SDK,使用其中的alipay.jar包。
2)当用户确定购买商品之后,首先生成订单,我们订单生成的规则就是用两个2-9的随机数+当前时间的毫秒值作为订单号。
3)调用支付宝的接口:调用支付宝的支付方法(方法Alipay.pay(String info)),支付方法需要传入支付相关信息,相关信息以KEY-VALUE键值对方式用&拼接组成。订单信息(订单号,交易付款时间,购买数量等),商品信息(商品名称,商品单价,商品描述等),支付信息(买方,卖方支付宝账号信息,支付金额等)和notify_url(这个是通知地址,也就是支付宝的服务器把支付后成功与否等结果信息同步给我们公司服务器时候使用的地址)等。还需要拼接一个重要的签名参数sign,sign的值是上述这些交易信息RSA签名后的结果。(加密就是数字签名)
4)支付信息提交后会提交到支付宝的服务器,支付宝的服务器完成整个支付功能后会给用户成功或者失败的提示界面。这个过程都是支付宝的功能。支付宝支付完成后,也会把信息同步给我们的服务器(也就是通过前面的notify_url这个地址)。
5)我们的服务器处理完毕之后,调用pay方法的时候其实也会接到返回值。返回值是json格式里面有很多信息,我们主要从中取结果状态码(resultStatus),根据状态码的数值判断支付是否成功,除了支付宝本身的提示界面以外,我们也会给用户一个我们自己的提示。
xmpp实现聊天功能:
我项目中即时通讯主要使用XMPP实现的,它有一个开源项目androidpn,使用的时候客户端要用到asmack.jar包,这个jar包提供了通讯的功能,主要使用jar包中的XMPPConnection类。主要实现如下:
1)使用XMPPConnection类与服务器建立持久连接
2)在持久连接基础上进行用户注册(用户注册之后服务器就会记录该用户的信息,下次就能够识别)
3)在连接基础上进行用户登录认证(登录之后服务端会知道当前用户的状态)服务端只要记录了该用户的信息,就可以往用户手机上发送推送的信息了。
实现通讯功能主要是使用jar包中的Chat类完成信息的发送,发送信息的时候要注意的是用户的格式是用户名称@域/命名空间(例如:要给loupengfei聊天的话地址为:loupengfei@127.0.0.1/AndroidpnClient),这样服务端就能够把信息转给响应名称的人。
接收信息:
1)在用户建立连接的时候就定义了一个指定命名空间的解析器provider(负责解析服务端发过来的xml格式的消息)
2)同时也注册一个包监听器PacketListener,当有信息发送过来的时候我们定义的解析器会收到信息,在解析中使用PULL解析方式把xml中信息解析出来然后封装成我们自定义的一个IQ的子类(就是消息Bean),然后带着消息进入到包监听类中,在包监听类中结合handler把聊天内容等更新到UI上。
四大组件详细介绍:
Activity通常就是一个单独的屏幕,它上面可以显示一些控件也可以监听并处理用户的事件做出响应。
BroadcastReceive广播接收器:
Service 是一段长生命周期的,没有用户界面的程序,可以用来开发如监控类程序。
android平台提供了Content Provider使一个应用程序的指定数据集提供给其他应用程序。这些数据可以存储在文件系统中、在一个SQLite数据库、或以任何其他合理的方式,
其他应用可以通过ContentResolver类(见ContentProviderAccessApp例子)从该内容提供者中获取或存入数据.(相当于在应用外包了一层壳),
只有需要在多个应用程序间共享数据是才需要内容提供者。例如,通讯录数据被多个应用程序使用,且必须存储在一个内容提供者中
它的好处:统一数据访问方式。
java中异常处理:

Activity的启动模式:
standard:默认模式,可以不用写配置。在这个模式下,都会默认创建一个新的实例。因此,在这种模式下,可以有多个相同的实例,也允许多个相同Activity叠加。
singleTop:可以有多个实例,但是不允许多个相同Activity叠加。即,如果Activity在栈顶的时候,启动相同的Activity,不会创建新的实例,而会调用其onNewIntent方法。
singleTask:只有一个实例。在同一个应用程序中启动他的时候,若Activity不存在,则会在当前task创建一个新的实例,若存在,则会把task中在其之上的其它Activity destory掉并调用它的onNewIntent方法。
如果是在别的应用程序中启动它,则会新建一个task,并在该task中启动这个Activity,singleTask允许别的Activity与其在一个task中共存,也就是说,如果我在这个singleTask的实例中再打开新的Activity,这个新的Activity还是会在singleTask的实例的task中。
singleInstance:只有一个实例,并且这个实例独立运行在一个task中,这个task只有这个实例,不允许有别的Activity存在。
线程:被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元
webview的辅助类:
作用:
通过url地址加载互联网或本地网页
WebSettings
设置WebView的一些属性、状态等,例如允许使用javascript,允许使用缓存,允许使用内置的缩放组件
WebViewClient
主要帮助WebView处理各种通知、请求事件(例如,点击链接时候如何显示界面,页面开始加载,加载完毕之后有何动作等)
WebChromeClient
辅助WebView处理Javascript的对话框、网站图标、网站Title、加载进度等
java的反射机制原理以及应用场合:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有
属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态
获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
OSI七层模型:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层

常用的存储方式有哪些?
SQLite:
SQLite是一个轻量级的数据库,支持基本SQL语法,是常被采用的一种数据存储方式。Android为此数据库提供了一个名为SQLiteDatabase的类,封装了一些操作数据库的API。
SharedPreference:
除SQLite数据库外,另一种常用的数据存储方式,其本质就是一个xml文件,常用于存储较简单的参数设置。
File:
即常说的文件(I/O)存储方法,常用语存储大数量的数据,但是缺点是更新数据将是一件困难的事情。
ContentProvider:
Android 系统中能实现所有应用程序共享的一种数据存储方式,由于数据通常在各应用间的是互相私密的,所以此存储方式较少使用,但是其又是必不可少的一种存储方式。 例如音频,视频,图片和通讯录,一般都可以采用此种方式进行存储。每个ContentProvider都会对外提供一个公共的URI(包装成Uri对 象),如果应用程序有数据需要共享时,就需要使用ContentProvider为这些数据定义一个URI,然后其他的应用程序就通过 Content Provider传入这个URI来对数据进行操作。
网络存储:
从网络读取数据和写入数据。 Android提供了通过网络来实现数据的存储和获取的方法。 我们可以调用WebService返回的数据或是解析HTTP协议实现网络数据交互。

package org.rsa.util;

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.io.*;
import java.math.BigInteger;

/**
* RSA 工具类。提供加密,解密,生成密钥对等方法。
* 需要到http://www.bouncycastle.org下载bcprov-jdk14-123.jar。
* RSA加密原理概述
* RSA的安全性依赖于大数的分解,公钥和私钥都是两个大素数(大于100的十进制位)的函数。
* 据猜测,从一个密钥和密文推断出明文的难度等同于分解两个大素数的积
* ===================================================================
* (该算法的安全性未得到理论的证明)
* ===================================================================
* 密钥的产生:
* 1.选择两个大素数 p,q ,计算 n=p*q;
* 2.随机选择加密密钥 e ,要求 e 和 (p-1)*(q-1)互质 (最大公因数为1的两个数叫互质数)
* 3.利用 Euclid 算法计算解密密钥 d , 使其满足 e*d = 1(mod(p-1)*(q-1)) (其中 n,d 也要互质)
* 4:至此得出公钥为 (n,e) 私钥为 (n,d)
* ===================================================================
* 加解密方法:
* 1.首先将要加密的信息 m(二进制表示) 分成等长的数据块 m1,m2,…,mi 块长 s(尽可能大) ,其中 2^s

原创粉丝点击