魅族手机如何初始化初始化错误代码21001是什么意思?

魅族的app怎么一直初始化_百度知道
魅族的app怎么一直初始化
您的回答被采纳后将获得:
系统奖励20(财富值+经验值)+难题奖励30(财富值+经验值)
我有更好的答案
您好,请您清除数据之后升级系统固件再试,谢谢
其他类似问题
为您推荐:
初始化的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁想用小枫服务器免流,但我用的是魅族没有菜单键,不能全局初始化,怎么办?_百度知道
想用小枫服务器免流,但我用的是魅族没有菜单键,不能全局初始化,怎么办?
魅族不是有个小白点的吗,可以在那设置菜单键,设置好了是红点的
其他类似问题
为您推荐:
初始化的相关知识
其他1条回答
装虚拟按键吧
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁当前访客身份:游客 [
Cogito, ergo sum
:博主使用ZXing扫描二维码效果如何?我在安卓上使...
:好样的 节省了我们的时间 希望多多交流
:写的很好,正在学习.
:调整横屏为竖屏以后,扫描到的图像变形了(正方形...
:引用来自“droidwolf”的评论 反转扫描到的图形,...
:反转扫描到的图形,是什么原理?像素颠倒?
:引用来自“严希廉”的评论madmatrix 你好,你这个...
:madmatrix 你好,你这个例子写得很好。最近在学习...
:感觉启动好慢。
今日访问:1
昨日访问:30
本周访问:110
本月访问:669
所有访问:21554
列表模式: |
由于是从Eclipse上改用Intellij Idea的,因此在设置快捷键的时候直接复用了Eclipse的快捷键设置:
Preferences——keymap——在右侧面板中的Keymaps下拉选项中选择Eclipse(Mac OS X)。
经过了多年使用,自定义快捷键存在诸多不便:
重装环境,要重新设置;
在帮助别人check代码时,用不习惯对方的快捷键;
倘若一个项目中的人统一使用Eclipse预定义的快捷键,会省很多事。
下面列出常用的一些快捷键以及改键位置:&
快捷键含义
Intellij Idea中设置位置
快捷键组合
Main menu/Code/Completion/Basic
ctrl+Space?
Main menu/Code/Optimize imports
command+shift+o
格式化代码
Main menu/Code/Reformat code
command+shift+f
Main menu/Navigate/Declaration
?换成Mac版Eclipse之后,这个定义是Ctrl+鼠标左键,但这个不好用,会同时打开菜单。可以改成command+鼠标左键
Main menu/Refactor/Rename
?fn+shift+F6
Other/Show Intention Action
?command+1
进入并查看光标所在的类或方法
fn+F3 &或 ctrl+鼠标左键
删除当前行
Editor Actions/Delete Line
?command+d
复制当前行
Editor Actions/Duplicate Lines
command+ctrl+方向键下
当前行向下移动
Main menu/Code/Move Line Down
无预定义,设定为options+方向键下
当前行向上移动
Main menu/Code/Move Line Up
?无预定义,设定为options+方向键上
注释当前行
Main menu/Code/Comment with Line Comment
?command+/
Main menu/Run/Run
command+shift+fn+F11
跳转到某行
Main menu/Navigate/Line
?command+L
返回上一个浏览位置
Main menu/Navigate/Back
?command+[
跳转下一个浏览位置
Main menu/Navigate/Forward
?command+]
查看当前类结构
Main menu/Navigate/File Structure
?command+o
当前文件查找下一个
Main menu/Edit/Find/Find Word At Caret
无预定义,建议用command+k取代Find Word Next的默认值
当前文件查找上一个
Main menu/Edit/Find/Find Previous
?command+shift+k
高亮显示光标处的单词
Main menu/Edit/Find/Highlight Usages in File
无预定义,设定为command+ctrl+h
当前文件查找/替换
Main menu/Edit/Find/Replace
无预定义,设定为command+f
全局查找选中的文本(只是查找字符串)
Main menu/Edit/Find/Find in Path
全局查找选中的文本(带完整包名)
Main menu/Edit/Find/Find Usages
?command+shift+G
打开设置面板(Preferences)
?command+,
创建新文件
?ctrl+option+n
打开某个资源文件
Main menu/Navigate/File
command+shift+r
关闭当前tab
Main menu/Window/Editor Tabs/Close
?command+w
关闭所有tab
Main menu/Window/Editor Tabs/Close All
?command+shift+w
重新打开关闭的tab
Main menu/Window/Editor Tabs/Reopen Closed Tab
?无预定义,设定为command+r
光标跳转到当前行开始
Editor Actions/Move Cart To Line Start
Home(fn+方向左)
光标跳转到当前行末尾
Editor Actions/Move Cart To Line End
End(fn+方向右)
光标跳转到文件开始
Editor Actions/Move Cart To Text Start
?command+Home
光标跳转到文件末尾
Editor Actions/Move Cart To Text End
?command+End
最大化当前编辑器
Main menu/Window/Activie Tool Window/Hide All Tool Windows
?command+shift+fn+F1
对于Intellij Idea中的"自动导入"快捷键,其效果不像Eclipse中那么强大,只会清理掉无用的包引入语句,并不会将所需的包自动引入。这个问题可以间接用下面的方法来解决:
不要写完一行然后批量引入,而在需要引入的地方使用"快速修复"来逐个引入;
复制过来的代码,按照下面的方法设置一下,当粘贴时,Intellij Idea会自动引入正确的包:
Preferences——Editor——Auto Import,在右侧的界面中选中全部:
Eclipse中又一个很好用的功能,是查找光标所在的单词,在Intellij Idea中,对应的必须设置Find Word At&Caret&Next,而不要设置Find Word Next。
如果要向上查找当前单词,用Find Word Previous。
发布于 1年前,
阅读(1632) | 评论(0) |
投票(1) | 收藏(2)
Collections增加了更多实用的集合,是java.util.Collections的扩展。
官方网站:
常用的容器
对等Map——BidiMap
可通过key找到value,亦可通过value找到key&
BidiMap&bidi&=&new&TreeBidiMap();
bidi.put(&SIX&,&&6&);
bidi.get(&SIX&);&&//&returns&&6&
bidi.getKey(&6&);&&//&returns&&SIX&
bidi.removeValue(&6&);&&//&removes&the&mapping
BidiMap&inverse&=&bidi.inverseBidiMap();&&//&returns&a&map&with&keys&and&values&swapped
注意,getKey方法,对于存在有相同value的情况,只会返回最后放入map的key
BidiMap&bidi&=&new&TreeBidiMap();
bidi.put(&a&,&1);
bidi.put(&b&,&1);
bidi.put(&c&,&2);
String&key&=&(String)&bidi.getKey(1);
System.out.print(key);
上面代码返回c&
有序Map——OrderedMap&
接口为OrderedMap,有两种实现:LinkedMap、ListOrderedMap&
OrderedMap&map&=&new&LinkedMap();
map.put(&FIVE&,&&5&);
map.put(&SIX&,&&6&);
map.put(&SEVEN&,&&7&);
map.firstKey();&&//&returns&&FIVE&
map.nextKey(&FIVE&);&&//&returns&&SIX&
map.nextKey(&SIX&);&&//&returns&“SEVEN”
多值Map——MultiMap&
用于将多个值映射到一个key上,此时get返回的就是一个集合
String&key&=&&madmatrix&;
MultiMap&mhm&=&new&MultiValueMap();
mhm.put(key,&&A&);
mhm.put(key,&&B&);
mhm.put(key,&&C&);
Collection&String&&coll&=&(Collection)&mhm.get(key);
Iterator&String&&iter&=&coll.iterator();
while&(iter.hasNext())&{
&&&&System.out.println(iter.next());
CaseInsensitiveMap
key不区分大小写的map
Least Recently Used Map。该map在初始化的时候大小固定,如果满了,再往里加东西,会先删除最近最少被使用的键值对。
put和get操作会改变键值对在map中的位置。而查询的方法如containsKey、containsValue以及通过iteration均不会改变kv的位置。
MultiKeyMap
按照字面意思理解即可,支持多个key映射到一个value。
private&MultiKeyMap&cache&=&MultiKeyMap.multiKeyMap(new&LRUMap(50));
public&String&getAirlineName(String&code,&String&locale)&{
&&String&name&=&(String)&cache.get(code,&locale);
&&if&(name&==&null)&{
&&&&name&=&getAirlineNameFromDB(code,&locale);
&&&&cache.put(code,&locale,&name);
bag的使用场景是:存储多个集合的拷贝,并在需要的时候获取拷贝个数。
HashBag是Bag接口的一个标准实现。而BagUtils提供一组static的方法让调用者获取经过不同装饰后的Bag实例。
Bag&bag&=&new&HashBag();
bag.add(&ONE&,&6);&&//&add&6&copies&of&&ONE&
bag.remove(&ONE&,&2);&&//&removes&2&copies&of&&ONE&
bag.getCount(&ONE&);&&//&returns&4,&the&number&of&copies&in&the&bag&(6&-&2)
Iterator&String&&iter&=&bag.iterator&();
while&(iter.hasNext())&{
&&&&System.out.println(iter.next());
?输出4个ONE字符串&
Map迭代器——MapIterator&
替代使用Set和EntrySet遍历map的方式?
IterableMap&map&=&new&HashedMap();
MapIterator&it&=&map.mapIterator();
while&(it.hasNext())&{
&&Object&key&=&it.next();
&&Object&value&=&it.getValue();
&&it.setValue(newValue);
发布于 1年前,
阅读(38) | 评论(0) |
投票(0) | 收藏(0)
关于蓝牙模块的一些基础概念
蓝牙主机和从机
主机:能够主动发起扫描并匹配从机模块
从机:只能被扫描和匹配
一个模块可以即是主机也是从机
蓝牙的AT模式就理解为设置模式好了。在设置模式下,我们设置一个蓝牙的以下重要参数:
蓝牙模块名称。既你的蓝牙设备被别的设备扫描到时所显示的名字;
如果是主从一体模块,可在AT模式下设置其角色;
设置密码;
通信波特率。需要注意,AT模式和工作模式下的波特率是不同的。
AT模式下,蓝牙模块无法被扫描并匹配。
该模式下,蓝牙可以扫描、被扫描,匹配、被匹配。这是与AT模式相对的一个模式,该模式下就无法再对蓝牙模块进行设置了。
Zduino UNO R3
OpenJumper Bluetooth V2.0
OpenJumper Bluetooth V2.0介绍
OpenJumper Bluetooth V2.0核心模块属于HC系列蓝牙模块中的HC-05主从模块。即主从一体,通过AT设置可改变其角色;
该模块仅支持SPP(Serial Port Profile,串行端口规范)规范,因此也只能实现“无线串口”通信功能,而无法支持像蓝牙耳机或蓝牙键盘那样的功能;
为了正确连接该模块,需要了解下面的重要参数:
串口波特率:38400bps,停止位:1位,校验位:无
串口波特率:9600bps,停止位:1位,校验位:无
指示灯含义
该模块有两个LED:State,状态指示灯,Link,连接指示灯。他们的闪烁定义如下:
快闪(0.5s间隔):搜索状态或等待外部链接
慢闪(1s间隔):蓝牙设置模式
双闪(间隔0.5s亮2次,灭3s):配对成功,可以通信,需要补充
常亮:配对成功,可以通信
1. 编写AT指令设置程序如下;
&*&OpenJumper&Bluetooth&v2.0&AT模式设置代码
&*&updated&by&madmatrix
#define&LED&13
void&setup()
&&&&&&&pinMode(LED,OUTPUT);
&&&&&&&Serial.begin(38400);&//&AT模式下的波特率必须为该值,否则会设置失败
&&&&&&&delay(100);
&&&&&&&Serial.println(&AT&);
&&&&&&&delay(100);
&&&&&&&Serial.println(&AT+NAME=My&Bluetooth&Test&);//命名模块名
&&&&&&&delay(100);
&&&&&&&Serial.println(&AT+ROLE=0&);//设置主从模式:0从机,1主机
&&&&&&&delay(100);
&&&&&&&Serial.println(&AT+PSWD=1234&);//设置配对密码
&&&&&&&delay(100);
&&&&&&&Serial.println(&AT+UART=&);//&设置工作模式下的波特率为9600,停止位1,校验位无
&&&&&&&delay(100);
&&&&&&&Serial.println(&AT+RMAAD&);//清空配对列表
void&loop()
&&&&&&&digitalWrite(LED,&HIGH);
&&&&&&&//&可以在每次上传该程序的时候调整一下这里的延时
&&&&&&&//&通过观察LED闪烁间隔来确认程序是否已经完成上传至arduino
&&&&&&&delay(1000);&
&&&&&&&digitalWrite(LED,&LOW);
&&&&&&&delay(1000);
2. 在未连接蓝牙模块的情况下上传程序至arduino;
如果此时蓝牙通电,并且串口线与arduino的串口相连,将占用arduino uno唯一的串口(0和1号引脚),程序将无法上传到arduino;
虽然电脑与arduino是通过usb连接,但实际上usb通过arduino上的一块转换芯片连接至串口,所以本质上仍然是电脑通过串口与arduino相连。
3. 连接蓝牙与arduino,注意要将蓝牙模块的AT引脚连接至vcc(高电平),此时蓝牙模块的State灯慢闪(间隔1s),表示进入AT模式。连接好后,按下Arduino复位键。等待arduino上的RX和TX指示灯不再闪烁,此时蓝牙模块已经设置好。注意State指示灯闪烁频率不变;
也可以不按复位键,将usb拔了再插上。这个过程等于按下复位键。他们都会使arduino重新启动,将已经上传至控制板中的程序再运行一遍;
此时由于蓝牙模块与arduino通过串口相连,那么程序中的Serial.println的输出都通过串口发送至蓝牙模块,从而达到了设置蓝牙的目的;
在第一步中,我们设置的波特率为38400bps,此时的作用就是为了与处于AT设置模式下的蓝牙模块通信,如果设置为9600,设置将失败。
4. 拔下蓝牙模块的AT引脚和VCC引脚线,此时上传工作代码至arduino。
拔下AT引脚线,让AT引脚置空,下次蓝牙模块上电时将进入工作模式;
此时工作代码中的串口波特率应该设置为9600bps,这是蓝牙模块工作状态下的波特率,注意工作代码中的串口通信波特率也应该是9600bps。
5. 蓝牙模块上电(VCC引脚接通),但AT引脚保持悬空状态,此时蓝牙模块的State灯快闪(0.5s间隔),表示进入搜索状态,可使用手机进行配对。
1. 随便写一段简单的工作代码
#define&LED&13
void&setup()&{
&&Serial.begin(9600);
&&pinMode(LED,&OUTPUT);
void&loop()&{
&&val&=&Serial.read();
&&if&(val&!=&-1)&{
&&&&Serial.print(&Arduino&answer:&Cogito&Ergo&Sum!&);
&&digitalWrite(LED,&HIGH);
&&delay(2000);
&&digitalWrite(LED,&LOW);
&&delay(2000);
2. 在Android手机上下载一个叫做“蓝牙串口”的小软件,装好后,打开软件,然后看到下面的界面:
修改模式为“会话模式”
点击连接,在弹出的窗口中,点击“扫描设备”,不出意外,会看到你设置的蓝牙模块的名字,然后选中:
等待软件弹出“连接到xxx”的提示后,再看蓝牙模块的指示灯,此时Link等常亮,State灯进入双闪状态。
这样就可以开始“会话”了,随便输入一段文字,就可以得到我们代码中预先设置好的答复:
发布于 1年前,
阅读(624) | 评论(0) |
投票(0) | 收藏(0)
android-m2e插件与maven
自定义用户配置路径
不管插件还是maven,默认的用户配置路径是统一的:${user.home}/.m2/settings.xml
但是插件可以通过eclipse设置用户配置的路径(配置方法参考);而maven不能永久指定,只能在每次使用mvn命令时加上&-s 新路径&参数。
如果使用android-m2d,在eclipse中写好依赖配置(&dependency&),保存之后就会自动去仓库下载该插件。如果找不到就会用红线标出。
使用maven,只有在编译的时候才会去检查依赖。&
修改本地仓库默认路径
打开${M2_HOME}/conf/settings.xml,可以找到这句被注释的配置:
&!--&localRepository
&&&|&The&path&to&the&local&repository&maven&will&use&to&store&artifacts.
&&&|&Default:&${user.home}/.m2/repository
&&&localRepository&/path/to/local/repo&/localRepository&
将/path/to/local/repo替换为自己的路径即可。
如果使用android-m2e插件,直接在eclipse中设置即可。
配置代理仓库(私有库)的位置
代理仓库的配置可以放在pom.xml中,但放在用户配置中可以省去很多麻烦。配置好代理仓库后,本地工程依赖的构件都将从配置指定的远程仓库下载。但请注意,此配置仅用于下载构件,无法通过此配置发布构件。
配置文件内容参考:&
&&&&&&profiles&
&&&&&&&&&&&profile&
&&&&&&&&&&&&&&&&id&repository&/id&
&&&&&&&&&&&&&&&&repositories&
&&&&&&&&&&&&&&&&&&&&&repository&
&&&&&&&&&&&&&&&&&&&&&&&&&&id&REPOSITORY-ID&/id&
&&&&&&&&&&&&&&&&&&&&&&&&&&url&REPOSITORY-URL&/url&
&&&&&&&&&&&&&&&&&&&&&&&&&&releases&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&enabled&true&/enabled&
&&&&&&&&&&&&&&&&&&&&&&&&&&/releases&
&&&&&&&&&&&&&&&&&&&&&&&&&&snapshots&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&enabled&true&/enabled&
&&&&&&&&&&&&&&&&&&&&&&&&&&/snapshots&
&&&&&&&&&&&&&&&&&&&&&/repository&
&&&&&&&&&&&&&&&&/repositories&
&&&&&&&&&&&/profile&
&&&&&&/profiles&
&&&&&&activeProfiles&
&&&&&&&&&&&activeProfile&repository&/activeProfile&
&&&&&&/activeProfiles&
将以上配置添加到用户配置中,有几个重要元素
REPOSITORY-ID:远程仓库id
REPOSITORY-URL:指定远程仓库的url
&releases&:是否启用发布构件的下载
&snapshots&:是否启用快照构件的下载。对于快照版本,如果链接的是中央仓库,由于快照版本不稳定,所以一般会推荐禁用快照版本的下载。但对于代理仓库,在多人合作开发的时候快照版本是有必要开启的。&
对于&snapshots&元素,可以通过&updatePolicy&为其指定检查快照版本的策略。
默认情况下,maven每天检查一次快照版本的更新。&updatePolicy&的值有:
daily:每天检查一次,默认
never:从不检查
always:每次构建都会检查
interval:X 每隔X分钟检查一次,X为任意整数。
&snapshots&
&enabled&true&/enabled&
&updatePolicy&always&/updatePolicy&
&/snapshots&
发布构建所需的配置
远程仓库配置
该配置必须放在pom.xml中。在pom.xml中指定发布版和快照版仓库的位置:
&distributionManagement&
&&&&&&repository&
&&&&&&&&&&&id&发布版仓库&/id&
&&&&&&&&&&&name&发布版仓库名称&/name&
&&&&&&&&&&&url&发布版仓库url&/url&
&&&&&&/repository&
&&&&&&snapshotRepository&
&&&&&&&&&&&id&快照版仓库&/id&
&&&&&&&&&&&name&快照版仓库名称&/name&
&&&&&&&&&&&url&快照版仓库url&/url&
&&&&&&/snapshotRepository&
&/distributionManagement&
id和url构成了远程仓库的唯一标识,name只是方便阅读。&
配置认证信息
该配置要放在用户或全局配置中:
&&&&&&server&
&&&&&&&&&&!--&需要认证的仓库id&--&
&&&&&&&&&&&id&发布版仓库id&/id&
&&&&&&&&&&&username&admin&/username&
&&&&&&&&&&&password&123456&/password&
&&&&&&/server&
&&&&&&server&
&&&&&&&&&&&id&快照版仓库id&/id&
&&&&&&&&&&&username&admin&/username&
&&&&&&&&&&&password&123456&/password&
&&&&&&/server&
&/servers&
需要注意的是,认证信息中的&id&应该对应在pom.xml中配置的仓库&id&。
对于Jar的依赖
如果使用了android-m2e插件,无需自行下载和添加jar到classpath,只需在pom.xml中配置好依赖(&dependencies&),之后maven会增加一个Maven Dependencies:
然后就可以在代码中引用了。
对于库工程的依赖
同jar一样,直接在&denpencies&中配置好了。虽然执行maven命令可以直接编译通过,但是ADT本身不支持从Maven仓库中直接引用。因此不得不将库工程下载到workplace,导入eclipse,然后设置为library,再让自己的工程引用该library。
发布jar到本地仓库
工程中依赖的jar包,在中央仓库上不一定有自己想要的版本,可以将项目组所需的版本上传到代理仓库,个人的话在本地仓库安装一份也可以。
比如我们要基于API 11进行编译,需要android-11/android.jar,那么进入到${ANDROID_HOME}/platforms/android-11,执行下面的命令:
mvn&install:install-file&-Dfile=android.jar&-DgroupId=com.google.android&-DartifactId=android&-Dversion=3.0&-Dpackaging=jar
如此,在无需pom.xml文件的情况下将jar包发布到本地仓库中。这样我们就可以在pom.xml中配置新的android依赖。
对于install-file,各参数的含义非常好理解,其中-Dfile是将要发布到仓库的包的位置,剩余的则是maven坐标以及打包类型。
发布库工程到本地仓库
我们自己写的库工程,将&packaging&改为apklib,执行install命令就好了。
以support-v7为例,操作步骤如下:
1.&用SDK Manager将support-v7下载到本地;
2. 将${ANDROID_HOME}/extras/android/support/v7/appcompat代码导入eclipse,将工程转为maven工程;
3. 将工程依赖的两个jar包先安装到本地仓库,进入${ANDROID_HOME}/extras/android/support/v7/appcompat/libs目录:
mvn&install:install-file&-Dfile=android-support-v7-appcompat.jar&-DgroupId=com.google.android&-DartifactId=android-support-v7-appcompat&-Dversion=r7&-Dpackaging=jar
mvn&install:install-file&-Dfile=android-support-v4.jar&-DgroupId=com.google.android&-DartifactId=support-v4&-Dversion=r7&-Dpackaging=jar
4. 修改pom.xml文件,增加对上面两个jar包的依赖:
&dependency&
&groupId&com.google.android&/groupId&
&artifactId&android-support-v7-appcompat&/artifactId&
&version&r7&/version&
&/dependency&
&dependency&
&groupId&com.google.android&/groupId&
&artifactId&support-v4&/artifactId&
&version&r7&/version&
&/dependency&
5. 执行命令:mvn clean install
注意,再添加这两个依赖的时候,&scope&最好不要设置为provided。使用默认的compile可以使得这两个jar在依赖工程中可见,这样就无需再引用这两个jar
其他的库工程发布方法同上,接着是修改需要依赖support-v7的工程的pom.xml文件,增加依赖:
&dependency&
&groupId&com.google.android&/groupId&
&artifactId&support-v7-appcompat&/artifactId&
&version&r7&/version&
&type&apklib&/type&
&/dependency&
此时执行mvn clean install即可。
针对support-v7的简便安装方法
上面只是演示如何发布一个库工程,实际对于support-v7,可以不用建立maven工程,采用下面的方法更加简洁:
1.&进入${ANDROID_HOME}/extras/android/support/v7/appcompat,将目录下所有文件打包为support-v7-appcompat.zip,名字可以任意;
2.&执行命令:&
mvn&install:install-file&-Dfile=support-v7-appcompat.zip&-DgroupId=com.google.android&-DartifactId=support-v7-appcompat&-Dversion=r7&-Dpackaging=apklib
接下来执行上面的第3步安装好support-v7依赖的jar包,最后在自己的工程的pom.xml中需要添加如下依赖:
&&&&&dependency&
&&&&&&&&&groupId&com.google.android&/groupId&
&&&&&&&&&artifactId&support-v7-appcompat&/artifactId&
&&&&&&&&&version&r7&/version&
&&&&&&&&&type&apklib&/type&
&&&&&/dependency&
&&&&&dependency&
&&&&&&&&&groupId&com.google.android&/groupId&
&&&&&&&&&artifactId&support-v4&/artifactId&
&&&&&&&&&version&r7&/version&
&&&&&&&&&type&jar&/type&
&&&&&/dependency&
&&&&&dependency&
&&&&&&&&&groupId&com.google.android&/groupId&
&&&&&&&&&artifactId&support-v7-appcompat&/artifactId&
&&&&&&&&&version&r7&/version&
&&&&&&&&&type&jar&/type&
&&&&&/dependency&
编译版本与android-m2e依赖的sdk版本关系
下面的配置指明的sdk版本用于编译:
&dependency&
&&&&&groupId&com.google.android&/groupId&
&&&&&artifactId&android&/artifactId&
&&&&&version&4.1.1.4&/version&
&&&&&scope&provided&/scope&
&/dependency&
在maven执行的过程中,对应的阶段是:
maven-compiler-plugin:3.1:compile
在这一步实际调用了javac命令来编译源码,在命令行中,加上-X参数即可看到该阶段的执行命令。
在命令中找到Command line options:字样,从,-classpath中可以找到类似于下面的日志:
/Users/madmatrix/.m2/repository/com/google/android/android/4.1.1.4/android-4.1.1.4.jar
可以看到最后的android-4.1.1.4.jar即为&version&指定版本。
下面配置是android-maven-plugin插件的定义以及依赖的sdk版本:
&&&&&groupId&com.jayway.maven.plugins.android.generation2&/groupId&
&&&&&artifactId&android-maven-plugin&/artifactId&
&&&&&version&${android.plugin.version}&/version&
&&&&&configuration&
&&&&&&&&&sdk&
&&&&&&&&&&&&&platform&11&/platform&
&&&&&&&&&/sdk&
&&&&&&&&&zipalign&
&&&&&&&&&&&&&verbose&true&/verbose&
&&&&&&&&&/zipalign&
&&&&&&&&&undeployBeforeDeploy&false&/undeployBeforeDeploy&
&&&&&/configuration&
android-maven-plugin插件参与了下面的阶段:
android-maven-plugin:3.8.2:generate-sources
这一阶段是将assert、res等资源文件打包。实际调用的android命令是aapt(Android Asset Packaging Tool)
该命令需要某个平台的android.jar包:
${ANDORID_HOME}/build-tools/android-xxx/aapt package -f --no-crunch -I, ${ANDORID_HOME}/platforms/android-xx/android.jar。
上面命令红色标注的api level就是&platform&元素值。意思就是在打包资源的时候,依赖哪个api level的jar包。
可见,这两处的sdk版本虽然配置方式不同(一个用version,一个用api level),但应该统一。可以统一定义在&properties&,例如:
&properties&
&project.build.sourceEncoding&UTF-8&/project.build.sourceEncoding&
&platform.version&3.0&/platform.version&
&platform.api&11&/platform.api&
&android.plugin.version&3.8.2&/android.plugin.version&
&/properties&
发布于 1年前,
阅读(969) | 评论(0) |
投票(0) | 收藏(14)
Maven 3.1.1+
Eclipse Indigo(3.7)、Juno(4.2)以上版本
虽然m2e-android官方推荐Eclipse使用Indigo和Juno以上版本,但本文是基于Kepler(4.3)来分享安装过程的。并整理了Juno(4.2)安装遇到的一些问题,其他版本可能会遇到一些其他的问题。
下载地址:&
描述:就像ant一样的一套工具,稍后安装的插件需要依赖maven
安装:直接下载binary文件,解压即可。
我们的安装目标是m2e-android,但该插件依赖m2e(Maven Integration for Eclipse)。有两种策略:
* 直接安装m2e-android,在安装过程中自动检测依赖,选择依赖的的m2e即可;
* 先安装m2e,再安装m2e-android,这种适用于使用Juno版本的Eclipse,经过尝试,Juno无法直接安装m2e-android。
m2e-android(Android for Maven Eclipse)的安装
插件官方文档:
描述:专用于ADT的maven插件。由于m2e-android的update site已经失效,无法使用Install New Software安装,只能通过Marketplace(ADT默认是没有安装的)。该插件依赖maven。
安装:在Marketplace中搜索android m2e。在Kepler的Marketplace中,搜索的结果是Android for Maven Eclipse 1.0.1,点击Install,而在Juno中是Android for Maven Eclipse。
全部选中——Confirm。因为是直接安装的m2e-android,没有提前安装m2e,因此这里还需要选中依赖项m2e。
特别注意,这里的m2e是Maven Integration for Eclipse。适用于不同开发环境的m2e插件会带有前缀或后缀,例如m2e - WPT。
注:Juno可能会在这一步失败,可以先安装m2e - Maven Integration for Eclipse,然后安装android m2e - Android Maven Plugin,这是两个插件,只是在安装android m2e的时候会通过依赖项自动安装m2e。
忽略该提示,直接Yes
默认选中第一项,不用换选项——Confirm。接下来就Next,直到Finish。
安装Marketplace的方法(已安装略过)
Help——Install New Software,Work with选择All Available site,在过滤条件中搜索marketplace:
也就是说,Marketplace是包含在eclipse本身的update site中的,只是没有预装在ADT中。如果选择All Availabe sites显示比较慢,可以直接选择Eclipse自带的Update Site:Work with的下拉列表中选择那个以你Eclipse当前版本代号同名的site。比如我是Kepler,那么链接会是这样的:
如果是Juno,那么name部分就是Juno。
Marketplace客户端搜索速度很慢,并且插件卸载后,Marketplace里仍然显示已安装状态,导致无法重新安装。此时可以打开,然后找到要安装的插件,将Install连接直接拖到Eclipse中。
终端命令配置
如果习惯使用maven命令行,则需要配置好ANDROID_HOME、MAVEN_HOME并加入到PATH中
下面是一份配置例子:
ANDROID_HOME=/Users/madmatrix/Documents/adt/sdk
MAVEN_HOME=/Users/madmatrix/Documents/maven322
PATH=/usr/local/git/bin:$PATH:$ANDROID_HOME:$MAVEN_HOME/bin
export&MAVEN_HOME
export&ANDROID_HOME
export&PATH
m2e-android配置
关联ADT与外置Maven
Preferences——Maven——Installations,默认情况下,与Eclipse关联的是内置的Maven(Embed),我们需要与刚下载好的Maven关联。点击Add,然后选择刚下载好的Maven的目录——OK。
设置maven用户配置与本地仓库路径
Preferences——Maven——User Settings。第一次打开该界面会提示User settings file doesn’t exist,但是插件已经给出了用户配置应该存在的位置,我们现在这个位置上手动创建一个名为settings.xml的文件,然后再回到Eclipse的这个界面,会发现在User Settings的右边出现了一个open file的超链接,点击该链接即可在Eclipse中打开配置文件进行编辑。
在该界面会看到Local Repository,点击Reindex可以更改本地仓库的路径。
设置Android SDK路径
虽然设置了ANDROID_HOME,但是m2e-android插件依然无法获取到android sdk的路径,我们可以将其设置在用户配置中,pom.xml文件会自动引用。
下面是一份写好的配置:
&?xml&version=&1.0&&encoding=&UTF-8&?&
&settings&xmlns=&http://maven.apache.org/SETTINGS/1.0.0&
&&&&&&&&&&xmlns:xsi=&http://www.w3.org/2001/XMLSchema-instance&
&&&&&&&&&&xsi:schemaLocation=&http://maven.apache.org/SETTINGS/1.0.0&http://maven.apache.org/xsd/settings-1.0.0.xsd&&
&&&&&&profiles&
&&&&&&&&&profile&
&&&&&&&&&&&&&id&android-sdk&/id&
&&&&&&&&&&&&&properties&
&&&&&&&&&&&&&&&&&android.sdk.path&PATH-TO-ANDROID-SDK&/android.sdk.path&
&&&&&&&&&&&&&&&&/properties&
&&&&&&&&&/profile&
&&&&&/profiles&
&&&&&activeProfiles&
&&&&&&&&&activeProfile&android-sdk&/activeProfile&
&&&&&/activeProfiles&
&/settings&
将PATH-TO-ANDROID-SDK换成你自己的android sdk路径即可
创建Maven项目
新建Maven项目
New——Maven——Maven Project——Next——Next,在Select an Archetype界面,点击Add Archetype,然后在弹出的对话框中依次填写:
Archtype Group Id:de.akquinet.android.archetypes
Archtype Artifact Id:android-quickstart
Archtype Version:1.0.10
然后点击OK
在以后新建工程的时候,在这个界面无需上述操作,直接在Catalog中选择Android,列表中的第一项即为我们新增的Archtype,选择该项,点击Next
在New Maven Project界面,需要填写Maven坐标信息。package为项目包名。
创建好之后的目录结构大致如下:
转化现有项目
按照以前的方式创建工程;
拷贝一份pom文件到该工程目录下;
修改pom.xml文件的groupId、Artifact Id等坐标;
项目上单击右键,选择Configure——Convert to Maven Project
如果工程下没有pom.xml文件,此时直接转换会弹出对话框让用户输入坐标信息,所以要先拷贝pom.xml然后再转换,这样就无需再填写坐标信息
编译、运行
右键单击项目,Run as——Run Configurations——左侧双击Maven Build,在右侧依次更改
Name:任意名字Base directory:点击Browse Workspace选择项目的路径Goals:clean install android:deploy android:run
然后点击Run。&
Plugin execution not covered by lifecycle configuration&
初次安装好m2e-android插件,可能会遇到该错误,该错误不影响正常使用。可以在Problems视图中,右键单击该错误,选择Quick Fix,然后选择永久忽略。
关于该异常的具体原因,参考这里:
发布于 1年前,
阅读(1177) | 评论(0) |
投票(0) | 收藏(7)
先列出错误的用法
private&MyAdapter&mA
&*&包含数据的list
private&List&String&&mDataList1&=&new&ArrayList&String&();
错误用法一:
public&void&onItemClick(AdapterView&?&&adapterView,&View&view,&int&position,&long&id)&{
&&&&String&item&=&(String)&mDataList1.get(position);
&&&&//&doSomething...
错误用法二:
public&void&onItemClick(AdapterView&?&&adapterView,&View&view,&int&position,&long&id)&{
&&&&String&item&=&(String)&mAdapter.getItem(position);
&&&&//&doSomething...
当ListView没有包含HeaderView和FooterView的时候,上面的用法没有问题,一旦包含,那么获取的数据项可能不准。因为此时传入的position是包含了HeaderView和FooterView的索引的:
mListView.addHeaderView(headerView);
mListView.addFooterView(footerView);
mAdapter&=&new&MyAdapter();
mAdapter.setDataList1(mDataList1);
mListView.setAdapter(mAdapter);
mListView.setOnItemClickListener(this);
public&void&onItemClick(AdapterView&?&&adapterView,&View&view,&int&position,&long&id)&{
&&&&String&item&=&(String)&mAdapter.getItem(position);
&&&&//&当position=1的时候,取出的item是处在索引0位置的数据
如果按照上面的方式编码,则点击列表中的任意一项,获取的数据项始终是position-1项。即这里的position其实是一个包含了HeaderViews和FooterViews,以及我们的DataList的大List中的索引。
那么正确获取数据项的方法是:
public&void&onItemClick(AdapterView&?&&adapterView,&View&view,&int&position,&long&id)&{
&&&&String&item&=&(String)&adapterView.getItemAtPosition(position);
&&&&//&doSomething...
当然你可以用判断position==0,但是如果包含有多个HeaderView或者FooterView,这样判断既麻烦也容易出错。按照上面的方法做,无需关心position值是什么,都可以正确获取数据项,Android已经帮我们处理了所有的情况。
该方法的源码如下:
public&Object&getItemAtPosition(int&position)&{
&&&&T&adapter&=&getAdapter();
&&&&return&(adapter&==&null&||&position&&&0)&?&null&:&adapter.getItem(position);
因此,getItemAtPosition方法等效于getAdapter().getItem(position)。
看起来AdapterView.getAdapter().getItem()与Adapter.getItem()没什么不同,但实际上,当ListView包含了HeaderView的时候,AdapterView.getAdapter()获取的Adapter不是我们定义的Adapter。
为了避免下面各种adapter的混淆,命名我们的adapter为myAdapter。
来看下ListView.setAdapter的源码,看一下Android对我们的myAdapter做了什么:
//&ListView.java
&&&&&*&Sets&the&data&behind&this&ListView.
&&&&&*&The&adapter&passed&to&this&method&may&be&wrapped&by&a&{@link&WrapperListAdapter},
&&&&&*&depending&on&the&ListView&features&currently&in&use.&For&instance,&adding
&&&&&*&headers&and/or&footers&will&cause&the&adapter&to&be&wrapped.
&&&&&*&@param&adapter&The&ListAdapter&which&is&responsible&for&maintaining&the
&&&&&*&&&&&&&&data&backing&this&list&and&for&producing&a&view&to&represent&an
&&&&&*&&&&&&&&item&in&that&data&set.
&&&&&*&@see&#getAdapter()&
&&&&@Override
&&&&public&void&setAdapter(ListAdapter&adapter)&{
&&&&&&&&if&(mAdapter&!=&null&&&&mDataSetObserver&!=&null)&{
&&&&&&&&&&&&mAdapter.unregisterDataSetObserver(mDataSetObserver);
&&&&&&&&resetList();
&&&&&&&&mRecycler.clear();
&&&&&&&&if&(mHeaderViewInfos.size()&&&0||&mFooterViewInfos.size()&&&0)&{
&&&&&&&&&&&&mAdapter&=&new&HeaderViewListAdapter(mHeaderViewInfos,&mFooterViewInfos,&adapter);
&&&&&&&&}&else&{
&&&&&&&&&&&&mAdapter&=&
&&&&&&&&...
&&&&&&&&...
可以很清楚的看到,当调用ListView.setAdapter的时候,会先判断是否已经包含了HeaderView和FooterView,如果包含,则ListView新建一个包装类HeaderViewListAdapter,包含myAdapter,然后ListView内部的另一个adapter引用(AbsListView.mAdapter)指向这个对象,myAdapter并没有被真的改变。
那么当ListView包含了HeaderView的时候,调用的getItem方法又有什么不同?来看看HeaderViewListAdapter.getItem(),源码如下:
//&HeaderViewListAdapter.java
private&final&ListAdapter&mA
public&HeaderViewListAdapter(ArrayList&ListView.FixedViewInfo&&headerViewInfos,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ArrayList&ListView.FixedViewInfo&&footerViewInfos,
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ListAdapter&adapter)&{
&&&&mAdapter&=&
&&&&mIsFilterable&=&adapter&instanceof&F
&&&&if&(headerViewInfos&==&null)&{
&&&&&&&&mHeaderViewInfos&=&EMPTY_INFO_LIST;
&&&&}&else&{
&&&&&&&&mHeaderViewInfos&=&headerViewI
&&&&if&(footerViewInfos&==&null)&{
&&&&&&&&mFooterViewInfos&=&EMPTY_INFO_LIST;
&&&&}&else&{
&&&&&&&&mFooterViewInfos&=&footerViewI
&&&&mAreAllFixedViewsSelectable&=
&&&&&&&&&&&&areAllListInfosSelectable(mHeaderViewInfos)
&&&&&&&&&&&&&&&areAllListInfosSelectable(mFooterViewInfos);
public&Object&getItem(int&position)&{
&&&&//&Header&(negative&positions&will&throw&an&IndexOutOfBoundsException)
&&&&int&numHeaders&=&getHeadersCount();
&&&&if&(position&&&numHeaders)&{
&&&&&&&&return&mHeaderViewInfos.get(position).
&&&&//&Adapter
&&&&final&int&adjPosition&=&position&-&numH
&&&&int&adapterCount&=&0;
&&&&if&(mAdapter&!=&null)&{
&&&&&&&&adapterCount&=&mAdapter.getCount();
&&&&&&&&if&(adjPosition&&&adapterCount)&{
&&&&&&&&&&&&return&mAdapter.getItem(adjPosition);
&&&&//&Footer&(off-limits&positions&will&throw&an&IndexOutOfBoundsException)
&&&&return&mFooterViewInfos.get(adjPosition&-&adapterCount).
该方法对position的各种情况做了判断,如果包含有HeaderViews,则会先从position减掉HeaderView的size。看这一句:
return&mAdapter.getItem(adjPosition);
这里的mAdapter,通过构造函数HeaderViewListAdapter赋值,结合ListView.setAdapter()源码可以知道就是myAdapter,所以此时的mAdapter.getItem=myAdapter.getItem,传入的position范围是0~DataList.size()。
需要注意的是AdapterView.getCount()返回的数据是包含有HeaderView和FooterView的个数的:
public&int&getCount()&{
&&&&if&(mAdapter&!=&null)&{
&&&&&&&&return&getFootersCount()&+&getHeadersCount()&+&mAdapter.getCount();
&&&&}&else&{
&&&&&&&&return&getFootersCount()&+&getHeadersCount();
那么,在myAdapter中的getView,以及getItem传入的position为什么没有受到影响呢?原因是类似的。
ListView最终在渲染item布局的时候(具体流程不在这里解释),会调用mAdapter.getView,此处的mAdapter,包含HeaderView的时候是HeaderViewListAdapter,所以还是直接看HeaderViewListAdapter.getView的源码:
//&HeaderViewListAdapter.java
public&View&getView(int&position,&View&convertView,&ViewGroup&parent)&{
&&&&//&Header&(negative&positions&will&throw&an&IndexOutOfBoundsException)
&&&&int&numHeaders&=&getHeadersCount();
&&&&if&(position&&&numHeaders)&{
&&&&&&&&return&mHeaderViewInfos.get(position).
&&&&//&Adapter
&&&&final&int&adjPosition&=&position&-&numH
&&&&int&adapterCount&=&0;
&&&&if&(mAdapter&!=&null)&{
&&&&&&&&adapterCount&=&mAdapter.getCount();
&&&&&&&&if&(adjPosition&&&adapterCount)&{
&&&&&&&&&&&&return&mAdapter.getView(adjPosition,&convertView,&parent);
&&&&//&Footer&(off-limits&positions&will&throw&an&IndexOutOfBoundsException)
&&&&return&mFooterViewInfos.get(adjPosition&-&adapterCount).
对于position的处理同getItem(),所以原因也很明了了。
了解了position与HeaderView之间的关系后,在编写这部分代码的时候就应当特别注意一点:addHeaderView与addFooterView必须在setAdapter之前被调用。因为setAdapter中要对headers和footers做判断的!
不过即使你粗心了,Android也抛异常会提醒你:
Caused by: java.lang.IllegalStateException: Cannot add header view to list -- setAdapter has already been called.
发布于 1年前,
阅读(586) | 评论(0) |
投票(0) | 收藏(0)
Alarm结构的设计
应该有一个字段来存储触发时间,这个时间对于重复日也是固定的;
对于重复日,要有一个weekday的数组来存储一周内重复的星期;
将触发时间与重复日组合成一个触发时间队列,每到期一个时间,将该时间出队,再设置下一次定时任务。
触发时间的计算步骤
如果不重复,则执行2,否则到3;
则根据用户设置的触发小时和分,结合当天日期计算出完整的触发时间,判断该时间是否已经过期(与当前时间戳比较)如果过期,则加一天;
取出重复日的最后一天,计算出改天的触发时间,如果未过期,则计算出所有的触发时间并放入触发队列;
如果过期,则将所有的触发日加7天,相当于向后推一周。因为重复日都是以周为单位进行设置的;
每次到期后,将该时间出队,如果队列为空,则重复1~4步骤计算出下一周所有触发时间即可。
&*&初始化闹钟,计算触发时间
&*&@param&alarm
public&static&void&initAlarm(Alarm&alarm)&{
alarm.triggerTimeQueue.clear();
Calendar&today&=&Calendar.getInstance();
Calendar&setDay&=&Calendar.getInstance();
if&(alarm.isRepeat)&{
//&1.&判断所有重复时间是否过期,只需要判断最后一天触发时间是否过期即可
//&取出重复天中最后一天
Weekday&lastDay&=&alarm.weekdays.get(alarm.weekdays.size()&-&1);
setDay.set(Calendar.DAY_OF_WEEK,&lastDay.getValue());
//&设置时、分、秒
setDay.set(Calendar.HOUR_OF_DAY,&alarm.triggerTimeHour);
setDay.set(Calendar.MINUTE,&alarm.triggerTimeMinute);
//&触发时间去掉秒,因为设置到期时间的时候就没有选择秒
setDay.set(Calendar.SECOND,&0);&
//&如果最后一个重复时间在本周内已经过期,则将所有的重复时间向后推迟7天
if&(today.after(setDay))&{
setDay.add(Calendar.DAY_OF_MONTH,&7);
//&2.&将剩余的重复日转化为触发时间放入队列
StringBuilder&logsb&=&new&StringBuilder(64);
for&(Weekday&weekday&:&alarm.weekdays)&{
setDay.set(Calendar.DAY_OF_WEEK,&weekday.getValue());
if&(today.before(setDay))&{
alarm.triggerTimeQueue.offer(setDay.getTimeInMillis());
logsb.append(DateUtil.formatDateTime(setDay.getTimeInMillis())).append(&,&&);
//&log&out
logger.d(&alarm&inited,&triggerTimeQueue=&&+&logsb);
setDay.set(Calendar.HOUR_OF_DAY,&alarm.triggerTimeHour);
setDay.set(Calendar.MINUTE,&alarm.triggerTimeMinute);
setDay.set(Calendar.SECOND,&0);
//&如果时间已经过期,则将触发日向后推一天
if&(today.after(setDay))&{
setDay.add(Calendar.DAY_OF_MONTH,&1);
alarm.triggerTimeQueue.offer(setDay.getTimeInMillis());
启用Alarm的时机:
新增Alarm后会立即启用该Alarm,即设置其状态为enabled;
对处于disabled状态的alarm,如果用户重新设置了时间或者其他参数后,立即启用;
对处于enabled状态的alarm,如果用户设置了其部分参数,则取消之前的任务,以当前的参数重新设置一个定时任务。
&*&启用/禁用alarm。启用alarm后会重新计算触发时间;禁用alarm后则会清空所有的触发时间
&*&@param&context
&*&@param&alarm
&*&@param&isEnable
&*&@return
public&static&boolean&enableAlarm(Context&context,&Alarm&alarm,&boolean&isEnable)&{
alarm.isEnabled&=&isE
AlarmManager&manager&=&(AlarmManager)&context.getSystemService(Service.ALARM_SERVICE);
Intent&intent&=&new&Intent(context,&AlarmExpireActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if&(isEnable)&{
initAlarm(alarm);
intent.putExtra(&alarm&,&gson.toJson(alarm));
PendingIntent&pi&=&PendingIntent.getActivity(context,&alarm.id,&intent,&PendingIntent.FLAG_CANCEL_CURRENT);
manager.set(AlarmManager.RTC_WAKEUP,&alarm.triggerTimeQueue.peek(),&pi);
logger.i(&reset&alarm&successfully,&alarm&id=&&+&alarm.id&+&&,&time=&&+&getAlarmHint(alarm));
alarm.triggerTimeQueue.clear();
PendingIntent&pi&=&PendingIntent.getActivity(context,&alarm.id,&intent,&PendingIntent.FLAG_CANCEL_CURRENT);
manager.cancel(pi);
logger.i(&alarm&has&been&canceled,&alarm&id=&&+&alarm.id);
saveAlarm(context,&alarm);
Alarm到期的处理
到期后会启动一个Activity,然后做以下事:
解锁并点亮屏幕;
显示到期时间,闪烁字体;
显示备注信息;
出队当前触发时间,使用下个触发时间重置任务;
发送一个到期广播,通知主界面更新——如果该闹钟是一次性的,那么过期后应当自动禁用,所以闹钟列表中该闹钟的状态会变为disabled
&*&解锁屏幕
private&void&unlockScreen()&{
KeyguardManager&keyguardMgr&=&(KeyguardManager)&getSystemService(Context.KEYGUARD_SERVICE);
KeyguardLock&keyguardLock&=&keyguardMgr.newKeyguardLock(&unlock&);
keyguardLock.disableKeyguard();
&*&点亮屏幕
private&void&lightScreen()&{
PowerManager&powerMgr&=&(PowerManager)&getSystemService(Context.POWER_SERVICE);
mWakeLock&=&powerMgr.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK&|&PowerManager.ON_AFTER_RELEASE,&&[lightScreen]&);
mWakeLock.acquire();
开机后重置所有激活态闹钟
注册系统开机广播:
&uses-permission&android:name=&android.permission.RECEIVE_BOOT_COMPLETED&&/&
&receiver&android:name=&org.madmatrix.galarm.BootBroadcastReceiver&&&
&&&&&intent-filter&
&&&&&&&&&action&android:name=&android.intent.action.BOOT_COMPLETED&&/&
&&&&&&&&&category&android:name=&android.intent.category.HOME&&/&
&&&&&/intent-filter&
&/receiver&
然后载入所有处在enabled态的闹钟,重置当前任务。
&*&监听开机,重启所有活动状态闹钟
&*&@author&madmatrix
public&class&BootBroadcastReceiver&extends&BroadcastReceiver&{
public&void&onReceive(Context&context,&Intent&intent)&{
List&Alarm&&activeAlarmList&=&GAlarmManager.loadAllActiveAlarms(context);
for&(Alarm&alarm&:&activeAlarmList)&{
if&(!alarm.isEnabled)&{
//&重置当前任务
GAlarmManager.resetAlarm(context,&alarm,&false);
注意,此处重置的是当前正在运行但由于关机被中断的任务,GAlarmManager.resetAlarm此时要做的是仍使用对头的时间戳而不是下一个时间戳来重置当前任务:
&*&默认用触发队列中处于对头的时间戳重置当前任务。如果resetNext为true,则对头时间出队,使用下一个时间重置当前任务
&*&注意:该方法只能重置处于enabled状态的闹钟
&*&@param&context
&*&@param&alarm
&*&@param&resetNext&是否使用下一个时间戳重置当前任务
public&static&void&resetAlarm(Context&context,&Alarm&alarm,&boolean&resetNext)&{
if&(!alarm.isEnabled)&{
logger.e(&[resetAlarm]the&alarm&should&be&enabled&);
if&(alarm.triggerTimeQueue.isEmpty())&{
initAlarm(alarm);
if&(resetNext)&{
alarm.triggerTimeQueue.poll();
if&(alarm.triggerTimeQueue.isEmpty())&{
initAlarm(alarm);
AlarmManager&manager&=&(AlarmManager)&context.getSystemService(Service.ALARM_SERVICE);
Intent&intent&=&new&Intent(context,&AlarmExpireActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(&alarm&,&gson.toJson(alarm));
PendingIntent&pi&=&PendingIntent.getActivity(context,&alarm.id,&intent,&PendingIntent.FLAG_CANCEL_CURRENT);
manager.set(AlarmManager.RTC_WAKEUP,&alarm.triggerTimeQueue.peek(),&pi);
logger.i(&restart&alarm&successfully,&alarm&id=&&+&alarm.id&+&&,&time=&&+&getAlarmHint(alarm));
GAlarm没有解决在MIUI上延迟提醒的问题。
GAlarm代码托管至:
该项目依赖GLib:
发布于 1年前,
阅读(139) | 评论(0) |
投票(1) | 收藏(0)
收录了系统错误码、基础错误码、Android&Java错误码
?错误描述?
无效请求, 通常在用户提交的请求参数有误时返回
服务器内部错误 ,通常在服务器侧出现异时返回
业务操作失败,语义解析服务出错。错误信息在error字段描述,具体参见业务相关语义(semantic)错误信息
服务不理解或不能处理该文本。文本没有匹配的服务场景
appid缺失或无效
appid已过期
appsig缺失或无效?
text参数缺失或无效?
text超过最大长度限制?
?text不满足最小长度限制
?ver参数缺失或无效
?method参数缺失或无效
?time参数无效
?IP被列入黑名单
?appid访问总数超过限制
?appid访问频率超过限制
?服务内部异常
?文件没有发现
?无效的参数
?无效的参数值
?无效的句柄
无效的数据?
?没有授权许可
?没有初始化
?打开文件出错
?没有足够内存
?没有更多数据
?加载模块失败
?无效的配置项
?无效的媒体类型
?初始化Config实例
编解码库未加载
?网络一般错误
?打开套接字
套接字链接?
?套接字接受
?无效的套接字
?无效的地址
?套接字没有打开
?非数据报套接字
?DNS解析错误
?消息一般错误
?Content为空
?Content类型无效
?Content长度无效
?Content编码无效
?会话IDE为空
?登录ID为空
同步ID为空
应用ID为空
扩展ID为空
无效的命令
无效的主题
无效的版本
没有版本号
新建响应消息失败
新建Content失败
无效的会话ID
数据库一般错误
无效的用户
无效的密码
资源一般错误
无效的名称
无效的映像
资源头部错误
合成一般错误
处于不活跃状态
没有活跃的语法
无效的媒体类型
无效的语言
没有对应的URI
获取URI内容超时
获取URI内容时出错
(EP)一般错误
(EP)链接没有名字
(EP)不活跃
(EP)初始化出错
无效的SessionID
错误的SessionID
无效的用户
无效的密码
HTTP错误基码
无有效的网络连接
网络连接超时
网络连接发生异常
无有效的结果
无匹配结果
未检测到语音
音频输入超时
无效的文本输入
文件读写失败
音频播放失败
无效的参数
用户未登陆
被异常打断
无效的编码
没有安装语音组件
引擎不支持
初始化失败
本地引擎未初始化
本地引擎无资源
本地引擎内部错误
本地唤醒引擎被异常打断
《语义开放平台API规范文档》
《科大讯飞MSC新手指南》
发布于 2年前,
阅读(394) | 评论(0) |
投票(0) | 收藏(0)
2014/4更新
不按照权威统计的格式和顺序,主要关注尺寸、分辨率和内存的配置等参数。
按屏幕尺寸升序
尺寸(单位:英尺)
RAM(单位:M)
HTC One (32GB/单卡/国际版)
android os 4.1
三星 GALAXY SIII (I9300/联通版)&
android os 4.0
LG Nexus 5(16GB)
android os 4.4
三星 GALAXY S4(I9500/16GB/单卡版)&
android os 4.2
华为 荣耀3C (1GB RAM/移动版)&
android os 4.2
魅族 MX3 (无NFC/16GB/普通版)&
Flyme 3.0&
LG G2(D802/16GB)&
android os 4.2
三星 GALAXY Note II(N7100/16GB)&
android os 4.1
联想 VIBE Z (K910/联通版)&
android os 4.2
三星 GALAXY Note3(N9006/单卡/16GB)
android os 4.3
OPPO N1(16GB/移动版)&
Color OS(基于Android 4.2)&
vivo Xplay3S(TD-LTE版)&
android os&4.3
酷派 大神&
android os& 4.2&
发布于 2年前,
阅读(140) | 评论(0) |
投票(0) | 收藏(2)
Screen的这些基本概念中,最重要的就是dip的理解,而理解dip就是理解android适配不同设备的关键。
Screen Size
实际物理尺寸。就是我们常说的3.5英寸屏幕,4.7英寸屏幕等等,这个长度说的是对角线的长度。在android中屏幕物理尺寸划分为这么几类:small,normal,large,extra large。下面是对尺寸以及密度的一个粗略分类。该图可能会由于实际设备尺寸和屏幕密度的不断增加而更新,最新的请到查看。
Resolution
“屏幕”分辨率,即屏幕上的像素总数。常用的表现形式如:20x1080等。
Screen density
屏幕密度,与dpi表达的同一个意思,两种不同的描述方式。官网如是说:
Screen density
The quantity of pixels within a physica usually referred to as dpi (dots per inch). For example, a &low& density screen has fewer pixels within a given physical area, compared to a &normal& or &high& density screen.
public float density The logical density of the display.
public int densityDpi The screen density expressed as dots-per-inch.
但其实我的理解他就是一个缩放系数,具体原因在后面解释。按照屏幕密度所有的手机可被划分为以下几类:ldpi&(low,低密度),&mdpi&(medium,标准密度),&hdpi&(high,高密度), and&xhdpi&(extra high,超大密度)。
DPI(dot per inch)
每英寸像素数。与density描述的都是屏幕的密度。但请注意这个翻译,实际上应该译为每英寸点数。为说明原因,不得不引入另一个概念:PPI(Pixel per inch),每英寸像素数。实际PPI用于电脑显示领域,DPI用于打印或印刷领域,但从很久之前两个概念就已经开始混用:
“点”有时用来表示像素,特别是计算机市场,由于计算机显示器如LCD或CRT是由一个个极小的点来描绘图像的,LCD显示器在标准屏幕分辨率下,对于一个像素可认为是由显示器的一个“点”来显示,因此ppi有时所写为DPI(dots per inch,每英寸点数)——维基百科:像素
到android这里,干脆就用dpi取代ppi代表像素密度。
DPI计算方法
像素密度=屏幕总像素数/屏幕大小。通常我们知道屏幕的尺寸是诸如3.5英寸,5.0英寸等,这是对角线长度,我们可以先获取对角线上的总像素数,再除以对角线长即可。
拿Mi2s举例说明:4.3英寸,。对角线上像素值根据勾股定理可得√(^2)≈1468.6,接着.3≈341.5
然而,从代码测试的结果看起来是有偏差的:
Density:2.0
DensityDpi:320
Resolution:
xDpi:345.0566 // x方向上(宽)每英寸像素数
yDpi:342.23157 // y方向上(高)每英寸像素数
可以看出,xDpi≈yDpi≈341,与我们的计算结果相近。但DensityDpi是320,为什么呢?在Screen Density中已经说过,android将所有屏幕的实际密度归类,处在某个区间内的密度是个定值,参考下表:
DPI值(像素/英寸)
根据图1种的分类,Mi2s的真实dpi为341,341&300,所以Mi2s属于xhdpi,再结合表1,得出DensityDpi=320。
从上面的数据也可以看出Density和DensityDpi值不同,但规律是显而易见的。在android中,mdpi是标准值,android将其density定为1,以此为准得出Density与DensityDpi的关系是:dpi=density*160。
我的疑问是,既然dpi可以代表屏幕密度,还要density干什么?想要搞清楚该死的density,必须要结合dp,往下看。
Density-independent pixel (dip,或dp)
独立像素,虚拟单位,又称设备无关像素。1dp的长度相当于一个160dpi的屏幕上一个物理像素的长度。而160dpi的屏幕则是被android定义为基准的屏幕(mdpi)。在app运行的时候,android会将dp转为实际像素进行布局。转换的公式为:px = dp * (dpi / 160)。
为什么要dip
设想app将一张图以像素为单位进行布局,该图为400px的正方形图,当app运行在上时看起来比较小,运行在960x640上时显得非常的大,而我们想要看到的效果是app运行在两个手机上时这张图看起来是大小相近的效果。
看下面这张图是以px为单位进行布局的效果:
下面这张图是使用dp布局的效果:
想要达到这样的效果,就需要在高密度手机上对其进行放大操作,低密度手机上对其进行缩小操作。但是我们无法预期自己的app会安装在什么密度,什么尺寸的手机上,即使知道也不可能为每个手机准备一套图,因此希望android能智能一些,我设置一个大概的尺寸,android能自动适配不同手机。于是就有了独立像素这个单位。见名之意,开发人员只需要用dp或者直接使用wrap_content,剩下的交给android,系统会为你的布局和图片做缩放。
dp怎么来的
那么,android是如何创造出这个独立像素的?
首先,我们的思路是从原来用px进行布局,改为用dp布局,由于最终dp还是要转化为px,引入一个系数λ,则有:px=dp*λ,λ就是我们的缩放系数;
其次,我最终目标是让所有手机上看到的图大小相同,那么到底多大,是不是要有个标准,我就选一个定做标准,让其他不同密度的手机显示的跟这个标准一样大。那么我把这个标准就定为160像素/英寸吧,取个名字叫mdpi,接着把其他密度的手机进行分类:ldpi(120像素/英寸),hdpi(240像素/英寸),xhdpi(320像素/英寸);
再次,归类都归好了,下面就开始缩放吧:
当app运行在标准手机上(mdpi),图片应该不缩放,因为它是标准,即λ=1,此时px=dp;
当app运行在ldpi手机上时,由于密度小于标准,图像的长更长,宽更宽,为了保持与标准相同的长宽,在ldpi上长要缩小原来的120/160=0.75,宽亦如此,即λ=0.75,此时px=0.75*dp;
当app运行在hdpi上时,λ=1.5,px=1.5*dp;
以此类推。。。
由上面的推导,其实λ=dpi/160=density,可见density就是λ。
1. 从官网的概念得知density与dpi都是描述屏幕密度的,似乎是相同的概念,但何必用两个同名概念来描述让人混淆呢?我个人觉得何不把他们从命名上做个区分,density就是个缩放系数,dpi才是对密度的准确描述。因此我只用dpi来表示屏幕密度,或像素密度,而density其实就是缩放系数,或密度系数;
2.&即使在某一个密度分组区间内(比如xhdpi)不同的密度的手机所展示的同样大小的图片,仔细看也不会完全相同,毕竟他们的密度不同。因此android只是尽最大可能简化适配的工作,分组并不能百分百解决适配的问题。
专用于android中的字体大小。sp产生的初衷与dp是相同的,只是它应用于字体大小。
发布于 2年前,
阅读(491) | 评论(0) |
投票(0) | 收藏(21)

我要回帖

更多关于 魅族手机怎么初始化 的文章

 

随机推荐