解决Android5.0应用安装失败的问题

缘起 把手机OTA升级到Android 5.0(Android L)以后安装某打车软件失败,尝试了几次结果一样。 探究竟 最开始想到是软件和5.0的适配兼容问题,查下Log吧。 首先通过 adb logcat 监测log,然后重新尝试安装,没有发现特别醒目的信息。 然后通过adb install xxx.apk的方式安装,得到以下错误提示: ...

十一月 26, 2014

在ContentResolver中使用Group By

缘起 使用ContentProvider查询短信,希望可以在ContentResolver.query中使用Group By ,发现系统并没有提供接口或者可用字段。 ...

九月 25, 2014

WebSocket入门和应用

WebSocket介绍 WebSocket是一种协议,本质上和http,tcp一样。协议是用来说明数据是如何传输的。它的url前缀是ws:// 或者wss://,后者是加密的websocket。WebSocket没有试图在HTTP之上模拟server推送,而是直接在TCP之上定义了帧协议,因此WebSocket能够实现全双工通信。 WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。 WebSocket通信协议于2011年被IETF定为标准 [RFC 6455][1],WebSocketAPI被W3C定为标准。 WebSocket解决了web实时化以及服务器端推送的问题,相比传统http有如下好处: 一个WEB客户端只建立一个TCP连接 Websocket服务端可以推送(push)数据到web客户端. 有更加轻量级的头,减少数据传送量 更详细内容请移步[维基百科][2] ...

十一月 7, 2013

一个逗号引发的惨案

根据判断条件组装建表的sql语句,有一处写成了全角的逗号,从而导致满足条件的字段后面都跟的全角逗号,sqlite认为直到遇到下一个半角逗号之前,都是上一个字段的类型声明,从而丢失了多个字段。 例如下面这样: create table card (userLevel TEXT,barCode TEXT,barCodeUrl TEXT,ucno TEXT,bigLogo TEXT,timeLineLink TEXT,blogLink TEXT) barCode 和 ucno类型后面是全角逗号,导致sqlite认为TEXT,barCodeUrl TEXT和TEXT,bigLogo TEXT是类型生命,丢失了这2个字段,但是建表成功,不会报任何错误,等到执行插入操作时才会提示没有该字段。 而由于插入操作只会针对遇到的第一个没有的字段进行提示,更进一步隐藏了问题的本质(建表字段较多,没有一一核对。。)。开始以为是sqlite的关键字,后来转念一想,关键字的话建表时就会报错了,而不是不报错直接建表成功。在多个sqlite工具下建表,结果是一样的。 最后在同事帮助下才通过删除几个字段的方式,最后细看组装出来的sql语句,终于发现是有多个全角逗号导致的。。 折腾了2个多小时,究其原因还是,浮躁,粗心。最开始引发的原因可能是写注释和代码时,中英文来回切换导致的。可见,写英语注释的重要性。。 当然,sqlite强大容错性也促成了这个bug。在此记录下,以警示自己!

五月 6, 2013

Android应用没有Activity是否可以接受广播?

一个应用没有activity,在API<3.1的版本是可以的接受广播,3.1以后就不可以了。 从3.1开始出于安全的考虑,一个应用必须至少运行一次才能接受广播,意思是说用户知道这个应用运行过,它才可以接受广播。如果非要试试没有activity的话,可以第一次安装有activity,然后,删除activity和xml对应的配置信息再次安装。不过这样实际意义不大。 普通的App如果没有启动默认都是停止状态的,停止状态的App默认是接受不到任何广播的。不过发送广播时如果添加指定标记,也可以使停止状态的应用接受这个的广播。 /** * If set, this intent will not match any components in packages that * are currently stopped. If this is not set, then the default behavior * is to include such applications in the result. */ public static final int FLAG_EXCLUDE_STOPPED_PACKAGES = 0x00000010; /** * If set, this intent will always match any components in packages that * are currently stopped. This is the default behavior when * {@link# FLAG_EXCLUDE_STOPPED_PACKAGES} is not set....

十二月 19, 2012

Ant编译Android工程

一.Ant安装 Windows下安装Ant: ant 官网可下载 http://ant.apache.org ant 环境配置: 解压ant的包到本地目录。 在环境变量中设置ANT_HOME,值为你的安装目录。 把ANT_HOME/bin加到你系统环境的path。 Ubuntu下安装Ant sudo apt-get install ant即可,环境变量也会自动配置。 二.编译Anadroid工程 android本身是支持Ant编译的,这里要知道一些Android命令。配置好android sdk 环境,保证在任意目录下执行android 命令。 1.创建一个android项目 android create project -k tk.laomos.demo -a Demo -t 25 -p . 参数说明: -k /–package 为命名空间(包名) -a /–name 工程名 -p /–path 项目 -t 为目标平台的版本对应id编号 查看当前平台Api level对应的id:(列出不同版本平台的对应id编号) android list targets 2.更新一个android项目产生build.xml等ant配置文件 对已经存在的android工程,我们可以update下(修改平台的版本),这样会自动添加build.xml 等ant的配置文件. android update project --name Demo -t 25 -p . 然后直接执行ant可以查看相应的参数。 ant 参数如下: debug:带调试用签名的构建 release:构建应用程序,生成的apk必须签名才可以发布 install:安装调试构建的包到运行着的模拟器或者设备; 直接执行: ant debug install...

十月 12, 2012

通过adb启动手机应用

通过adb shell pm命令可以启动手机中已安装的应用,还可以发送广播,启动服务等等。 例如: //拨打电话 adb shell am start -a android.intent.action.CALL -d tel:10086 //启动浏览器打开网页 adb shell am -a android.intent.action.VIEW -d http://laomos.tk //发送广播 adb shell am broadcast -a tk.laomo.START //启动已经安装的应用 adb shell am start tk.laomo.demo/tk.laomo.demo.MainActivity 通过adb shell pm启动应用可以用于: 1.自动化测试 2.配合ant、maven使用,ant、maven打包安装,adb shell pm启动应用 等等。 Ps:android中通过包名启动应用可以这样调用: Intent mIntent = getPackageManager() .getLaunchIntentForPackage("com.laomo.demo"); startActivity(mIntent);

十月 12, 2012

判断手机是否已安装google map

需求是这样的:如果手机已安装google map,通过google map打开google地图;否则通过浏览器打开google地图(无论是否已安装其它地图程序)。 网上比较普遍的判断方法是通过Class.forName判断有没有这个类: try { Class.forName("com.google.android.maps.MapActivity"); } catch (Exception e) { return; } 例如这个如何在Android真机上检测是否有Google Map add-on 国外一位大牛指出:在标签中还包含了一个没有公布的属性"android:required",你可以将com.google.android.maps库的这个属性设置为false,即: 这代表如果在目标机器上内置了Google Map add-on,则可以正常使用应用;如果目标机器没有内置Google Map add-on,也可以成功安装应用。但是开发人员需要在代码中自行判断Google Map add-on是否可用。 try { Class.forName("com.google.android.maps.MapActivity"); } catch (Exception e) { Toast.makeText(MainActivity.this, "Oop! google地图不可用", Toast.LENGTH_SHORT).show(); return; } Intent intent = new Intent(); intent.setClass(MainActivity.this, MyMapActivity.class); startActivity(intent); 但是这种方法在有些版本的系统上不生效。后来一朋友说他们是这样实现的: 1.首先定义一个方法isIntentAvailable(Intent intent);用来判断有没有这个intent要”启动的“应用。 private boolean isIntentAvailable(Intent intent) { List<ResolveInfo> activities = getPackageManager().queryIntentActivities(intent, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT); return activities.size() != 0; } 2.然后调用判断即可。 Intent intent = new Intent(Intent....

十月 6, 2012

Android SparseArray

Sparse array —稀疏数组 原型解释:http://hi.baidu.com/kxw102/item/9302f36ef2b9db106995e639" 所谓稀疏数组就是数组中大部分的内容值都未被使用(或都为零),在数组中仅有少部分的空间使用。因此造成内存空间的浪费,为了节省内存空间,并且不影响数组中原有的内容值,我们可以采用一种压缩的方式来表示稀疏数组的内容。 人性化的SparseArray:http://blog.sina.com.cn/s/blog_68d72c9b010131ug.html SparseArray是android里为<Interger,Object>这样的Hashmap而专门写的class,目的是提高效率,其核心是折半查找函数(binarySearch),今天在看这个class的实现时发现一个很好的设计: public void remove(int key) { delete(key); } remove和delete都实现了,功能当然是一样的,对用户来说,想用delete,和remove的都可以。 SparseArray<E>详解:http://blog.csdn.net/xyz_fly/article/details/7931943 最近编程时,发现一个针对HashMap<Integer, E>的一个提示: 翻译过来就是:用SparseArray<E>来代替会有更好性能。 那我们就来看看源码中SparseArray到底做了哪些事情: 一、构造 从构造方法我们可以看出,它和一般的List一样,可以预先设置容器大小,默认的大小是10: public SparseArray() { this(10); } public SparseArray(int initialCapacity) { ...... } 二、增 它有两个方法可以添加键值对: public void put(int key, E value) public void append(int key, E value) 在存储数据的时候,是采用了二分法方式,以下是它采用二分法的源码: private static int binarySearch(int[] a, int start, int len, int key) { int high = start + len; int low = start - 1; while (high - low > 1) { int guess = (high + low) / 2; if (a[guess] < key) { low = guess; continue; } high = guess; } if (high == start + len) return start + len ^ 0xFFFFFFFF; if (a[high] == key) { return high; } return high ^ 0xFFFFFFFF; } 所以,它存储的数值都是按键值从小到大的顺序排列好的。...

九月 15, 2012

Android应用程序请求root权限

前提是手机已经破解获取root权限 只是简单的取得root权限: try { Runtime.getRuntime().exec("su"); } catch (Exception e) {} 取得root权限并在程序里获得root结果: private boolean hasRoot() { char[] arrayOfChar = new char[1024]; try { int j = new InputStreamReader(Runtime.getRuntime().exec("su -c ls") .getErrorStream()).read(arrayOfChar); if (j == -1) { return true; } } catch (IOException e) { } return false; } -c, ——commmand=COMMAND 执行一个命令,然后退出所切换到的用户环境; 执行"su -c ls"这样不会阻塞程序。

八月 30, 2012