android一些细节问题
1. Android的Btimap处理大图片解决方法
我们都知道Android的Dalvik VM为一个应用提供了大约16MB的内存,一般我们处理超过8MB的图片将会出现OutOfMemoryError异常,我们解码一个图片为了防止内存不足的异常我们可以使用BitmapFactory.Options 的udeinTempStorage属性解决,代码如下:
BitmapFactory.Options cwj = new BitmapFactory.Options();
cwj.inTempStorage = new byte[1024*1024*5]; //5MB的临时存储空间
Bitmap bm = BitmapFactory.decodeFile(inputStream,cwj); //这里cwj为Options属性
有关android.graphics.BitmapFactory.Options类的其他属性,可以参考下图:
2. Binder invocation to an incorrect interface错误
有时候我们可能发现Android的版本不同,有些AIDL的调用可能会爆出ERROR/AndroidRuntime(28520): java.lang.SecurityException: Binder invocation to an incorrect interface这样的错误,表面上看是安全问题,但出现Binder invocation to an incorrect interface这样的错误,可能是由于API变动导致了AIDL的声明有出入,为了防止执行意外出现空指针,Android平台默认保护了进一步的执行,从错误的提示来看就是不正确的接口异常,一般我们检查时可以查看源代码参考解决.
3.MATCH_PARENT是什么类型的布局
有网友表示对于很多工程中的MATCH_PARENT出现在layout中感到不明白,过去只有FILL_PARENT和WRAP_CONTENT那么match_parent到底是什么类型呢? 其实从Android 2.2开始FILL_PARENT改名为MATCH_PARENT ,从API Level为8开始我们可以直接用MATCH_PARENT来代替FILL_PARENT,他们的定义本质是一样均为-1,只是换了个别名,可能为了更准确些,比如最终在SDK中的定义为:
fill_parent -1 The view should be as big as its parent (minus padding). This constant is deprecated starting from API Level 8 and is replaced by match_parent.
match_parent -1 The view should be as big as its parent (minus padding). Introduced in API Level 8.
wrap_content -2 The view should be only big enough to enclose its content (plus padding).
4.Android换行符变成方框的解决方法
我们都知道Android是基于Linux内核的,在处理换行符时使用的是\n而Windows服务器处理换行符为\r\n这样的方式,对于显示\r 即回车符在Android上面可能就变成了黑色的方框或者说方块,我们在Android的TextView或EditView等文本显示控件上将\r\n替换成\n即可。
5.View的显示状态GONE,VISIBLE和INVISIBLE区别
可能会发现View类的设置显示状态setVisibility方法有三种情况,分别为GONE、VISIBLE和INVISIBLE,它们之间到底有哪些区别呢? 举个简单的例子:有些Android应用的下面包含了AdMob或Adsense广告条,如果这个View我们设置为GONE则消失,该广告条看不见也不占用位置。而INVISIBLE则代表广告条那块是空白,但仍然沾着他布局高和宽的位置,而VISIBLE就是标准显示时的状态。
6.android单实例运行方法
我们都知道Android平台没有任务管理器,而内部App维护者一个Activity history stack来实现窗口显示和销毁,对于常规从快捷方式运行来看都是startActivity可能会使用FLAG_ACTIVITY_NEW_TASK标记来打开一个新窗口,比如Launcher,所以考虑单任务的实现方法比较简单,首先纠正下大家一种错误的方法就是直接在androidmanifest.xml的application节点中加入android:launchMode=”singleInstance”这句,其实这样将不会起到任何作用,Apps内部维护的历史栈作用于Activity,我们必须在activity节点中加入android:launchMode=”singleInstance” 这句才能保证单实例,当然一般均加在主程序启动窗口的Activity。
7.managedQuery和query的区别-数据库查询API
有人问道managedQuery和query的区别,我们都知道在Android系统中,SQLite数据库的相关操作方式被封装为内容提供Content Provider,可以帮助那些不会SQL语言的开发者快速实现Android平台上的数据库操作,但是平时我们在查询时一般返回的是Cursor对象,从本质上来看这两个API是不同的类提供的。比如 ContentResolver.query(),以及Activity.managedQuery()所以,我们看到一个是ContentResolver提供的查询方法,位于android.content.ContextWrapper.getContentResolver(),另一个则为Activity。
这两种方法的参数是一样的,但是Activity类的方法在整个声明周期中受Activity的影响,而常规我们处理数据逻辑可能单独分成一个类,直接使用Context对象传递实例句柄,同时建议大家,对于数据库查询操作如果数据较为庞大尽量使用异步的AsyncQueryHandler方法防止阻塞线程。
8.SystemClock.sleep和Thread.sleep的区别
在Java中我们处理线程同步问题时,处理延迟可能会使用Thread类的sleep方法,这里抛开concurrent类的一些方法,其实Android平台还提供了一个SystemClock.sleep方法,它们有什么区别呢?
我们每次调用Thread.sleep时可能会出现InterruptedException异常,而SystemClock.sleep方法则不会,在SDK上有这样的描述,它将会忽略中断异常。SystemClock.sleep(millis) is a utility function very similar to Thread.sleep(millis), but it ignores InterruptedException. 要提醒的是下面这句 Use this function for delays if you do not use Thread.interrupt(), as it will preserve the interrupted state of the thread.
9.APK文件安装代码实现
很多网友可能需要自己下载APK并实现安装,这里说下Android123早期的APK安装器中的APK文件安装代码实现,其实整个实现比较简单,但可以清晰说明Android平台的隐式Intent。在系统安装的底层常规的应用通过系统服务PackageInstaller来识别程序安装的Intent来执行安装。
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(“file://”+ “/sdcard/android123.com/cwj.apk”,”application/vnd.android.package-archive”);
startActivity(intent);
PackageInstaller服务将会在内部匹配MIME类型为application/vnd.android.package-archive的Intent,要说明的是setDataAndType的参数第一个为URI,其实URI内部的String对应为file://加上常规的路径,比如 file:///sdcard/android123.com/cwj.apk ,当然其他的Uri构造方法还可以Uri.fromFile(new File(sfileFullPath))。
10.ayout_weight的作用是什么
很多时候大家可能发现布局xml文件中有一个layout_weight属性,是的不是layout_height也不是layout_width,那么layout_weight是什么呢? 它的定义是一个比重。比如在一个LinearLayout中,有三个TextView控件,如果第一个设置layout_height为1,第二个为1,最后一个为2,这时候这三个TextView控件的大小为 1:1:2 。在Android开发中我们可能经常用到这个属性来排列一些控件
11.No marked region found along edge错误
如果在Android项目中使用Nine Patch资源,时候可能出现比如ERROR: 9-patch image android123.9.png malformed.或 No marked region found along edge.以及 Found along top edge.的错误主要是因为该图片没有四周的定位像素。
12.ListView在ScrollView中无法正常显示
对于ListView放在在ScrollView中时,目前Android平台仍然有些bug,状态是显示的ListView仅仅大约一行半(总Item肯定大于2行,比如10行),通过Layout布局属性设置目前仍然无法修正。通过分析ListView和ScrollView构造没有发现很好的解决方法,目前可以通过自己实现ListView来解决,Android123解决的方式重写ListView的onMeasure重新计算显示行数。希望在Android以后的版本,至少2.1以后能够改进。
13.APK文件为什么要签名才能发布?
很多开发人员不明白APK文件为什么必须签名才能发布,其实签名并非从Android平台开始,在过去从Symbian OS就开始需要签名才能发布,这样可以保证每个应用程序开发商合法ID,由于Android平台没有UID3的限制,部分开放商可能通过使用相同的Package Name来混淆替换已经安装的程序。不过目前比较好的是Android中所有的permission使用都是免费的,但从目前GIT项目中出现的CertInstaller.git包不知道是不是和证书有关,而近几年Symbian OS从v9.0开始如果应用程序涉及敏感操作需要Capability才能使其真机顺利安装,同时部分高级权限需要购买和Symbian Signed测试才能发布,保证系统的安全可靠性,而这点Android平台较为宽松。常规情况下从ADB比如Eclipse的ADT插件安装到模拟器或真机的测试程序经过DEBUG标记签名,所以我们签名是都需要先创建key公钥通过RSA运算才实现加密。
14.Android中动态改变ImageView大小
可能发现在layout.xml文件中定义了ImageView的绝对大小后,无法动态修改以后的大小显示,其实Android平台在设计UI控件时考虑到这个问题,为了适应不同的Drawable可以通过在xml的相关ImageView中加入android:scaleType=”fitXY” 这行即可,但因为使用了缩放可能会造成当前UI有所变形。使用的前提是限制ImageView所在的层,可以使用一个内嵌的方法限制显示。
15.Android平台显示单位px和dip以及sp的区别
在Android的layout文件中layout_width或layout_height有时候可能会指定具体的单位,比如有时候为px、dip或者sp等等。下面android123把常见的单位做下简单的介绍,比如说
px (pixels)像素 — 一般我们HVGA代表320×480像素,这个用的比较多。
dip或dp (device independent pixels)设备独立像素 — 这个和设备硬件有关,一般我们为了支持WVGA、HVGA和QVGA cwj推荐使用这个,不依赖像素。
sp (scaled pixels — best for text size)放大像素– 主要处理字体的大小。
16.Android中XML布局文件@+id/和@id/的区别
在Android平台中很多地方时新定义的,对于新手来说可能发现在layout.xml 这样的xml布局文件中发现了,类似@+id/和@id/到底有什么区别呢? 这里@我们可以理解为引用,而多出的+代表自己新声明的。大家可以多看看Android SDK中API Demos例子中涉及的众多资源。
17.如何判断Android手机当前是否联网?
如果拟开发一个网络应用的程序,首先考虑是否接入网络,在Android手机中判断是否联网可以通过 ConnectivityManager 类的isAvailable()方法判断,首先获取网络通讯类的实例 ConnectivityManager cwjManager=(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); ,使用cwjManager.getActiveNetworkInfo().isAvailable(); 来返回是否有效,如果为True则表示当前Android手机已经联网,可能是WiFi或GPRS、HSDPA等等,具体的可以通过ConnectivityManager 类的getActiveNetworkInfo() 方法判断详细的接入方式,需要注意的是有关调用需要加入
18.Asset限制文件大小UNCOMPRESS_DATA_MAX为1MB
在使用Android自带的Res\raw或使用Asset时都需要经过Asset Manager,这将会产生一个比较严重的问题,在Android模拟器测试时不存在问题,但放到真机G1时会面临多个问题,经过查看UNCOMPRESS_DATA_MAX的取值为1048576字节,除以1024不难发现是1MB。也就是说Android手机在处理资源文件时不能大于1mb的体积。由于标准的G1没有Root权限,无法访问data/data/package name下面的文件夹,使用raw或asset存放的文件大小不能超过1048576字节,否则会在logcat下看到获取到Debug类型的信息,tag为asset(pid): Data exceeds UNCOMPRESS_DATA_MAX (2580997 vs 1048576) 可以看到接下产生了一个系统的错误,System.err,会发生java.io.IOException的异常。
目前解决的方法只有将文件放入到sdcard,但这样除了microsd的读取IO效率和耗电量解决不是很好,同时sd卡移除时可能存在问题,解决的方法如果数据量大的化通过sqlite是一种解决方法,同时openFileOutput方式读取也是不错的选择,看来android操作系统中最安全控制的严格,但犯了一个不小的错误。
19.getIntentSender错误解决方法
在Android编码中会出现getIntentSender这样的方法不能用,或提示安全不允许,其实后面描述已经很清晰了,is not allowed to send as package android,getIntentSender这样的方法不允许从包中使用,通过一个服务调用即可。虽然Android平台提供了很多permission的限制,但是最终很多还是不给第三方开发者公开的。目前来说Google必需的强制签名似乎还没有起到很大的作用,仅仅是安装时提示有哪些危险操作,未来可能需要一些更严格的检测。
20.
很多网友抱怨官方的英文Android开发者网站(android developers)中国用户打不开,虽然被和谐了但Android123支招告诉大家决绝方法,其实Google Apps等服务的主服务器是在appspot.com这个域名上,对于Android SDK以及新的内容大家直接访问 http://androidappdocs-staging.appspot.com/reference/packages.html 即可,这个和developer.android.com是同步的。为了大家更好的记住本文章,该链接我们放到了 /android_kit.html 这页。
21.AsyncTask对比Thread加Handler
很多网友可能发现Android平台很多应用使用的都是AsyncTask,而并非Thread和Handler去更新UI,这里Android123给大家说下他们到底有什么区别,我们平时应该使用哪种解决方案。从Android 1.5开始系统将AsyncTask引入到android.os包中,过去在很早1.1和1.0 SDK时其实官方将其命名为UserTask,其内部是JDK 1.5开始新增的concurrent库,做过J2EE的网友可能明白并发库效率和强大性,比Java原始的Thread更灵活和强大,但对于轻量级的使用更为占用系统资源。Thread是Java早期为实现多线程而设计的,比较简单不支持concurrent中很多 特性在同步和线程池类中需要自己去实现很多的东西,对于分布式应用来说更需要自己写调度代码,而为了Android UI的刷新Google引入了Handler和Looper机制,它们均基于消息实现,有事可能消息队列阻塞或其他原因无法准确的使用。
Android开发网推荐大家使用AsyncTask代替Thread+Handler的方式,不仅调用上更为简单,经过实测更可靠一些,Google在Browser中大量使用了异步任务作为处理耗时的I/O操作,比如下载文件、读写数据库等等,它们在本质上都离不开消息,但是AsyncTask相比Thread加Handler更为可靠,更易于维护,但AsyncTask缺点也是有的比如一旦线程开启即dobackground方法执行后无法给线程发送消息,仅能通过预先设置好的标记来控制逻辑,当然可以通过线程的挂起等待标志位的改变来通讯,对于某些应用Thread和Handler以及Looper可能更灵活。
22.WebView下的JavaScript的传值问题:
在取到JavaScript传给Activity的值以后,直接给TextView会报错,异常提示“Only the original thread that created a view hierarchy can touch its views”,后来上网查了资料,需要用Handler处理赋值,具体如下:
很多网友在Android中使用多线程处理UI相关内容时可能会发现Logcat提示Only the original thread that created a view hierarchy can touch its views这样的错误,这主要是Android的相关View和控件不是线程安全的,我们必须做独立的处理这点比J2ME麻烦一些,这里Android给我们提供了很多方法,有关线程的,我们需要了解下J2ME中一些传统的线程创建方法,比如Runnable或直接new Thread(),大家需要了解UI线程、worker线程以及一些概念。今天android开发网说一种简单的方法除了异步任务AsyncTask外使用Handler可以很好的处理,和Win32的消息很像。
首先我们需要明白,主线程或者这里说的原始线程original thread 一般情况下是UI线程,当然UI线程并不一定是主线程,我们不能长时间的阻塞该应用,在Android平台上可能会产生类似Force close或Wait这样的对话框这里我们成为ANR,这里除了使用ProgressDialog方式给用一个动态的进度代表当前处理并没有中断可能需要一些时间,所以android123告诉大家相关的网络处理可以使用工作者线程,但是worker 线程不能处理显示元素即UI相关的View或Widget包中的高层的控件,所以通过一个Handler对象可以很好的传递Runnable或Message ,下面我们用一个简单的例子来描述
final Handler cwjHandler = new Handler();
final Runnable mUpdateResults = new Runnable() {
public void run() {
updateUI();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
NetworkOperation();//一个很费时间的I/O操作,比如网络或文件读写等等。
}
protected void NetworkOperation() {
Thread t = new Thread() {
public void run() {
doSomething(); //处理得到结果了,这里一些内容保存在主类的成员变量中
cwjHandler.post(mUpdateResults); //高速UI线程可以更新结果了
}
};
t.start();
}
private void updateUI() {
//详细的更新
}