5月 162015
 

  因为在国内无法访问android的官方网站以及dl-ssl.google.com,所以在Eclipse中使用Help->Install New Software,然后在Work with里输入插件地址安装Android adt的办法根本行不通。

  那么我们只能通过下载adt的插件包,然后手动添加的方式进行添加,下面将详细办法介绍如下:

  1. 首先需要下载adt离线包,一般为zip压缩包文件

  2. 同时下载android sdk的压缩包

  2. 打开Eclipse,点击菜单Help->Install New Software进入插件安装窗口

  3. 点击”Work with”最右侧的”Add…”按钮

20151216205441

  4. 在弹出的窗口中,点击”Archive…”按钮,选择下载的adt离线包文件,在”Name:”框中输入名字,比如”android_adt”,点 “OK”按钮

20151216225801

 

  5. 这时Install New Software窗口中间的列表框就显示可安装的插件了,选中要安装的插件,然后点”Next”按钮。

  6. 选择”I accept the terms of the license agreements”,然后点击”Finish”按钮,等候安装完成。

20151216233518

  7. 安装过程中可能提示这个安全警告,点击”OK”按钮即可。

20151216233941

  8. 安装完成,提示重启Eclipse,点击”Yes”按钮重启Eclipse

20151216234055

  9. 重启完成后,选择菜单Help->Install New Software,在弹出的窗口中选择链接”already installed”

20151216234246

  10. 这时在弹出的窗口中就可以看到安装好的插件了,如下图所示

20151216234438

  11. adt插件的安装过程就完成了,下面设置android sdk的路径,加到Eclipse主界面,选择菜单Window->Preferences,弹出下面的窗口,在左边的导航栏中选”Android”,在右边的SDK Location中输入下载好的android sdk的路径,点击”OK”按钮,重启Eclipse,根据提示打开SDK Manager更新android sdk就可以了

20151216234930

  12. 关于sdk更新的提醒,如果无法下载可以更改SDK Manager一些选项试一下,在SDK Manager中选择菜单Tools->Options

20151216235158

  13. 选项中的设置可以根据下图设置,代理服务器使用mirrors.neusoft.edu.cn,端口80;”Force https:// sources to be fetched using http://”选项打上勾,修改后重启SDK Manger进行尝试

20151216235335

5月 132015
 

  App Widget是Android中可以用于显示在桌面或者锁屏中的便捷显示组件,对于一些应用来说,比如天气预报、音乐播放器、股票行情等应用,开发相应的组件放到桌面上可以让用户更快捷高效的查看内容,提高用户的效率,增强用户的体验,让应用更加受用户欢迎。

一、插件原理介绍

  因为小插件要长期在桌面上,所以小插件不能通过应用的形式来长期运行,那样会消耗很多的系统资源,所在在安卓系统中,插件是作为插件宿主的一部分而存在,而不是一个应用程序,而插件宿主由安卓系统来控制,这时插件和应用之间的数据传输就不能像Activity之间一样单纯的用Intent来控制了。那么插件的数据是通过什么形式传输的呢?答案是使用的广播的方式来传输数据,插件本身是一个BroadcastReceiver,接收到消息或数据后再进行显示。由此可见,插件并没有Activity,只是一个BroadcastReceiver,而用于处理界面的对象则是RemoteViews而不是View对象。

  Android中的桌面插件虽然拥有和Activity基本一样的布局,但插件中的组件却不能直接通过组件对象直接操作,比如在Activity中我们要改变一个TextView显示的文字,我们只需要用findViewById找到这个对象并赋给一个定义好的TextView对象,然后用这个对象的setText方法修改显示文字即可。但是在插件中却不可以这样操作,因为他本身并不存在Activity,不提供findViewById这样的方法来寻找对象。具体如何操作以后会讲到,下面我们先来看看要创建一个组件所必须的几个对象。

二、三个必要组件

  通过上面的描述我们可以知道,一个小插件至少要有两个对象才可以存在,第一就是一个可用于接收消息的BroadcastReceiver对象,在安卓中又针对插件做了一次封装,那我们需要使用的就是继承自AppWidgetProvider类;另外一个,很显而易见的就是要有一个基本的布局,一个layout对象。那么还没完,我们还需要一个对象来描述这个Provider,这就是第三个基本组件AppWidgetProviderInfo对象,一个xml描述文件。下面我们就对这三个对象进行详细描述。

1、AppWidgetProvider类

  AppWidgetProvider继承自BroadcastReceiver对象,其实就是一个广播接收对象类,它自身又实现了几个用于处理插件被更新、变可用、变不可用、被删除时的方法。下面是一个示例文件:

1) onReceive: 此方法实际上是覆盖了父类BroadcastReceiver中的onReceive方法,用于接收广播消息并根据不同的消息内容执行不同的操作。在AppWidgetProvider中已经对更新、删除等消息内容做了处理,并新建了onUpdate、onDeleted等方法用于给开发者响应消息。需要注意的是:开发者可以自定义广播消息,并在onReceive中接收并做相应的操作。
2) onAppWidgetOptionsChanged: 应该是当插件对应的配置页面更改时触发此方法
3) onUpdate: 此方法就是响应设定的定时更新触发时的消息了,用于更新界面内容。

创建方法:在项目中新建一个类,父类设置为AppWidgetProvider即可

2. AppWidgetProviderInfo对象

AppWidgetProviderInfo对象其实就是一个xml文件,存储在resxml目录下,用于定义组件的宽度、高度、组件内容更新频率、初始化布局等信息,系统会根据这些信息创建并调整组件的显示。下面是一个示例文件:

1) minWidth: 用于设置组件的最小宽度,系统会根据此值计算出插件横向所要占据的网格数量
2) minHeight: 用于设置组件的最小高度,系统会根据此值计算出插件纵向所要占据的网格数量
3) minResizeWidth: 插件缩放时允许的最小宽度
4) minResizeHeight: 插件缩放时允许的最小高度
5) updatePeriodMillis: 插件的更新频率,单位ms,此值小于半个小时的时候将按半小时计算,因为android不允许小插件过于频率的更新以节省资源和电池用量,对于更新频率要小于半个小时的情况,我们会在后面讲述如何处理
6) initialLayout: 用于指定插件所使用的布局文件
7) initialKeyguardLayout: 用于指定在锁屏界面上插件所使用的布局文件
8) configure: 用于指定插件设置窗口所使用的布局文件
9) previewImage: 用于指定添加插件页面中,插件所使用的预览图像
10) resizeMode: 用于指定插件允许的缩放模式,可选择横向、纵向或者不能缩放
11) widgetCategory: 用于指定插件都在哪个地方显示,可选择在桌面、锁屏界面或者搜索界面。

创建方法:在项目中新建一个xml文件,xml文件的类型为appwidget-provider,生成的文件将自动存储到resxml目录下

3、Widget布局文件

  首先来说,它是一个布局文件,和Activity的布局文件一样,存储在reslayout目录下,所不同的是,插件布局中并不支持所有的组件。

  可支持的部局组件如下:

  • FrameLayout
  • LinearLayout
  • RelativeLayout
  • GridLayout

  支持的内容组件如下:

  • AnalogClock
  • Button
  • Chronometer
  • ImageButton
  • ImageView
  • ProgressBar
  • TextView
  • ViewFlipper
  • ListView
  • GridView
  • StackView
  • AdapterViewFlipper

  注意:不可以支持以上组件的子类。

  创建方法:新建一个layout文件

三、使自己的第一个小组件生效

  在创建了上文所述的三个对象后,我们还需要在Android Manifest文件中对WidgetProvider对象进行一下声明,这样才可以在插件管理器中看到我们要创建的插件,所用代码如下:

  receiver 节点中的内容即为对SimpleWidgetProvider的定义,intent-filter和meta-data节点都必须添加上才可以使插件生效。

5月 112015
 

我们可以从以下方面考虑Android应用的优化

  1. 如果广播只针对应用内部发送和接收,使用LocalBroadcastManager进行广播,避免发送系统级的广播
  2. 使用Lint工具检查部局文件的合理性,减少不必要的嵌套,提高应用的性能
  3. 使用monkey和monkey runner进行自动化测试
  4. 优化业务逻辑,减少不必要的操作,如在不必要的时候减少网络的请求
 Posted by on 2015-05-11
4月 272015
 

  获取外部存储路径的代码为:

  这个代码开始在htc、三星等机器上工作正常,但是后来发现在小米、华为等一些机器上不能操作外部存储设置上的文件,本来以为是需要特殊权限的问题,在网上查了半天没查到解决办法。后来才发现,原来并不是机器的问题,而是在创建文件夹的时候调用的函数不对,我是使用mkdir去创建文件夹的,但是mkdir不能创建多层目录,所以就造成了后边的文件不能访问。

  不知道有mkdirs为什么还要有mkdir函数,留着迷惑人啊!

4月 192015
 

一、为什么要使用多线程?

  默认情况下,当一个Android应用启动后,应用内部运行的线程只有一个,就是应用的UI线程,负责界面的展示以后用户和屏幕元素的互动。那么当我们需要进行网络下载、图片加载、复杂运算等比较耗时的操作时,如果也要主线程中进行,UI界面就没有足够的CPU时钟进行处理了,就会造成界面卡死的情况,这就是我们所说的ANR(Application Not Responding)。所以,为了防止出现这种情况,像这些耗时的操作我就需要开一个子线程去进行处理。

二、Runnable接口

  我们在网上看线程的讲解的时候经常会看到Runnable这个接口的使用,其实Runnable只声明了一个接口函数,就是run()函数,它的作用就是给各种的线程类去继承并实现run方法。比如:FutureTask<V>、Thread、TimerTask等都实现了这个接口。我们只要记住它是一个只声明了run()函数的接口就好了。

三、使用Thread类实现多线程

  上面是一个Thread线程的例子,在这里要注意:

  1. Thread启动的线程不能直接访问UI组件,要通过组件的.post方法访问,如上面的textView.post(new Runnable() {})
  2. 要使用start()方法启动线程,不可以使用run()方法

四、使用AsyncTask实现多线程

上面是一个AsyncTask的例子,

  • onPreExecute:doInBackground运行之前的函数,可以操作UI的组件
  • doInBackground: 耗时的操作(网络下载、图像处理等)放到这个函数里
  • onPostExecute:doInBackground运行之后的函数,可以操作UI的组件
  • onProgressUpdate:用于在UI显示运算进度,需要在doInBackground里调用publishProgress

AsyncTask的优点:

  1. 结构清晰,易于理解
  2. 可显示进度
  3. 可方便操作UI组件

AsyncTask的缺点:

  1. 不能多个实例同时运行,每次要创建一个新的实例,比如myTask.execute(“OK”);就会抛异常

五、HandlerThread

  HandlerThread适用于在一个线程中执行多个实时性不高的操作.具体参考下面的链接

  对HandlerThread的理解

六、ExectuorService线程池

七、Handler的post、postDelayed的执行方法并不是在子线程中执行,而是在主线程中执行

八、FutureTask、TimerTask继承自Runnable接口,并不是实现多线程的类,只是实现多线程的辅助类,如new Thread(futureTask).start();这样的。他们与直接使用Runnable接口的差别如下:

  1. FutureTask可以取消,可以返回结果
  2. TimerTask可以定时执行

 

4月 172015
 

一般Android的默认图片编辑器是支持对图片进行剪裁操作的,所以如果我们的应用需要对图片进行剪裁操作,调用系统的图片编辑器即可,代码如下:

如果输出到文件(设置MediaStore.EXTRA_OUTPUT的值):

如果在Activity中处理返回的图片流(return-data的值为true):

 

 

2月 262015
 

  Home键:默认情况下,android中的home键只是切换到系统的home界面,并不会销毁当前的activity,即不会执行activity中的ondestroy方法,从任务栈中恢复那个应用的话,activity中的数据不会丢失

  Back键:而android中的back键,则先销毁当前activity,然后回到之前的应用界面中,而且此时activity中的数据都丢失了。

  如果我们想在按back键的时候,不销毁当前的activity,保留它的数据和状态的话,我们可以改写源码中对back键的处理来达到这个目的,代码如下:

  当然这样做的缺点时,之前打开的应用全部都被关闭掉了,比如用户在用浏览器看新闻,通过通知栏消息打开了你的应用,在你的应用中按back键就回到了home界面,前面的浏览器也被关掉了。

12月 252014
 

  SharedPreferences貌似很简单的一个类,却也存在着陷阱,如下面,我们写了几行简单的保存配置的代码,但却隐含着bug

  那么为什么这段代码不能保存runcount的数据呢,因为prefs.edit()每次返回一个新的Editor对象,所以执行两次prefs.edit()其实调用的是两个Editor对象,如下adnroid源码中的解释

  因此,我们应该先将prefs.edit()赋值给一个Editor对象,然后由该对象进行存值和提交操作,如下:

 

12月 212014
 

  出现此问题的原因是你的项目使用到的android的appcompat支持库,但你目前的开发环境中并没有引用此支持库。下面图文介绍如何下载并引用该类库。

  1、首先需要在android sdk manager中下载Android Support Library,在Eclipse中打开菜单Window->Android SDK Manager,在sdk manager窗口中看你是否已经下载了Android Support Library,在最下面的Extras的节点中有此项,如果没有则选中此项并下载,如下图

Download Android Support Library

  类库将会下载到你的sdk子目录中,路径为<sdk目录>extrasandroidsupport。如果你使用的Android Studio开发环境,则需要下载Android Support Respository。

  2、将类库项目导入到开发环境中。在Eclipse菜单中打开File->New->Project,选择Android Project From Existing Code

Create Project From Existing Code

  3、点击”Browser…”按钮选择appcompat所在的路径,<sdk目录>extrasandroidsupportv7appcompat,勾选Copy projects into workspace,最后点击“Finish”按钮,导入项目成功。

Import android v7 appcompat

  4、将appcompat库引用到你的项目中。在你的项目上右键选择属性菜单,在左侧的导航列表中选择“Android”,在右侧内容最下的Library区域点击“Add”按钮,将导入的类库项目添加进来就完成了。

Add android v7 appcompat reference

  5、重新Clean你的项目。点击Eclipse的菜单Project->Clean…,在弹出的窗口中选择你要清除的项目,点击ok,清除结束后上述问题应该就可以解决了。

  关于Android支持库的其他特性可以点击这里查询。

 

12月 012014
 

  在有些APP中我们需要实现一个悬浮按钮,比如图片浏览应用左右翻页功能,比如左侧悬浮功能按钮。我们要实现此功能时,最开始想到的就是用FrameLayout来实现,但是如果把按钮简单的放到FrameLayout中,按钮只能在布局的左上角,并不能达到我们的要求。

  那么如何才能让按钮放到布局的左侧中间位置呢,开始时想把按钮高度设置成match_parent,然后图片垂直居中,但是这样整个最左侧的部分都是按钮了,显然会影响其他功能的使用,后来想哪个组件才能自由的让子控件放到想放的位置呢,这个得是RelativeLayout了吧。于是在FrameLayout中放了一个RelavtiveLayout中,然后把按钮放到里面,Layout Parameters中的Align Parent Left设置成true,Center Vertical设置成true,再看一下,一个居中的悬浮按钮就弄好了。

  同样的方式可以设置其他需要的悬浮按钮了。

 

 Posted by on 2014-12-01