AndroidStudio快捷键

Ctrl+G / Ctrl+Alt+Shift+G:查询变量或者函数或者类在哪里被使用或被调用,后者是前者的复杂表现,可以选择查询范围等。 Alt+H:查找功能,全局查找 F4:查看类继承关系 F2:查看文档说明(函数使用说明) Ctrl+E:查看最近打开过的文件 Ctrl+Shift+E:查看最近编辑过的文件 double Shift:全局查找,这个查看和Alt+H稍稍有些不同,这个是全局文件查找,到文件名称层面。 Ctrl+Shift+R:快速定位到你所想打开的文件。 Alt+↑:光标所在位置那行代码往上移动 Alt+↓:光标所在位置那行代码往下移动 Ctrl+D:删除光标所在位置那行代码 Ctrl+X:剪切光标所在位置那行代码 Alt+Shift+↓/Ctrl+C:复制光标所在行代码到下一行 Ctrl+O:快捷查找当前类中的函数,变量 Ctrl+Shift+R:修改名称 Alt+Enter:导入包 Alt+←:后退,定位到上个查看或者编辑的地方 Alt+→:往前定位,比如你定位到上个点后,想回去,就可以用这个快捷键 Ctrl+/:当行注释,反注释再按一次即可 Ctrl+Shift+/:模块注释,反注释再按一次即可,注意这边的”/“不能用小键盘的 Ctrl+Shift+小键盘/:折叠代码(Ctrl+Shift+小键盘*这个不灵了,今天没空了,后面会针对这个问题做解决,并更新上来),当然笔记本没小键盘,你可以自己改快捷键 Ctrl+Alt+S:打开settings界面 Ctrl+Alt+Shift+S:打开Project Structure界面 Alt+Shift+X:运行(Run) Alt+Shift+D:调试运行(Debug) Ctrl+F9:编译工程 Ctrl+Shift+K:push文件到Server(git) Debug类快捷键 F5:但不调试进入函数内部。 F6:但不调试不进入函数内部。 F7:由函数内部返回调用处。 F8:执行到下一个断点,没断点则执行完成。 Action Mac OSX Win/Linux 注释代码(//) Cmd + / Ctrl + / 注释代码(/**/) Cmd + Option + / Ctrl + Shift + / 格式化代码 Cmd + Option + L Ctrl + Alt + L 清除无效包引用 Option + Control + O Alt + Ctrl + O 查找 Cmd + F Ctrl + F 查找+替换 Cmd + R Ctrl + R 上下移动代码 Option + Shift + Up/Down Alt + Shift + Up/Down 删除行 Cmd + Delete Ctrl + Y 扩大缩小选中范围 Option + Up/Down Ctrl + W/Ctrl + Shift + W 快捷生成结构体 Cmd + Option + T Ctrl + Alt + T 快捷覆写方法 Ctrl + O Ctrl + O 快捷定位到行首/尾 Cmd + Left/Right Ctrl + Left/Right 折叠展开代码块 Cmd + Plus,Minus Ctrl + Plus/Minus 折叠展开全部代码块 Cmd + Shift + Plus,Minus Ctrl + Shift + Plus,Minus 文件方法结构 Cmd + F12 Ctrl + F12 查找调用的位置 Ctrl + Option + H Ctrl + Alt + H 大小写转换 Cmd + Shift + U Ctrl + Shift + U ...

2015年8月7日 · 2 分钟 · 天边的星星

Android编程心得-在Assets文件夹中放入.sql文件实现创建SQlite表的操作

当我们在使用SQLiteOpenHelper时,经常使用db.execSQL(String sql)方法写入对应语句实现创建表的操作,这样的确可以实现业务逻辑。与此同时还有一种更灵活的方法,从assets文件夹下读取对应的.sql文件,然后创建表。 1.首先在工程的assets文件夹下,添加对应的.sql文件 2.配置一个Configuration类,用于保存固定路径变量 **[java]** [view plain](http://blog.csdn.net/yangqicong11/article/details/21396437#)[copy](http://blog.csdn.net/yangqicong11/article/details/21396437#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/240525)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/240525/fork) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="keyword">public</span> <span class="keyword">class</span> Configuration { - <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String DB_PATH = <span class="string">&#8220;schema&#8221;</span>; - <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String DB_NAME = <span class="string">&#8220;test.db&#8221;</span>; - <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> DB_VERSION = <span class="number">1</span>; - - } ...

2015年8月7日 · 2 分钟 · 天边的星星

Android库Volley的使用介绍

Android Volley 是Google开发的一个网络lib,可以让你更加简单并且快速的访问网络数据。Volley库的网络请求都是异步的,你不必担心异步处理问题。 Volley的优点: 请求队列和请求优先级 请求Cache和内存管理 扩展性性强 可以取消请求 下载和编译volley.jar 需要安装git,ant,android sdk clone代码: git clone https://android.googlesource.com/platform/frameworks/volley 编译jar: android update project -p . ant jar 添加volley.jar到你的项目中 不过已经有人将volley的代码放到github上了: https://github.com/mcxiaoke/android-volley,你可以使用更加简单的方式来使用volley: Maven format: jar <span class="tag"><<span class="title">dependency</span>></span> <span class="tag"><<span class="title">groupId</span>></span>com.mcxiaoke.volley<span class="tag"></<span class="title">groupId</span>></span> <span class="tag"><<span class="title">artifactId</span>></span>library<span class="tag"></<span class="title">artifactId</span>></span> <span class="tag"><<span class="title">version</span>></span>1.0.6<span class="tag"></<span class="title">version</span>></span> <span class="tag"></<span class="title">dependency</span>></span> Gradle format: jar compile 'com.mcxiaoke.volley:library:1.0.6' Volley工作原理图 {.fancybox} 创建Volley 单例 使用volley时,必须要创建一个请求队列RequestQueue,使用请求队列的最佳方式就是将它做成一个单例,整个app使用这么一个请求队列。 <span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">AppController</span> <span class="keyword">extends</span> <span class="title">Application</span> </span>{ <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String TAG = AppController.class .getSimpleName(); <span class="keyword">private</span> RequestQueue mRequestQueue; <span class="keyword">private</span> ImageLoader mImageLoader; <span class="keyword">private</span> <span class="keyword">static</span> AppController mInstance; <span class="annotation">@Override</span> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">onCreate</span>() { <span class="keyword">super</span>.onCreate(); mInstance = <span class="keyword">this</span>; } <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">synchronized</span> AppController <span class="title">getInstance</span>() { <span class="keyword">return</span> mInstance; } <span class="keyword">public</span> RequestQueue <span class="title">getRequestQueue</span>() { <span class="keyword">if</span> (mRequestQueue == <span class="keyword">null</span>) { mRequestQueue = Volley.newRequestQueue(getApplicationContext()); } <span class="keyword">return</span> mRequestQueue; } <span class="keyword">public</span> ImageLoader <span class="title">getImageLoader</span>() { getRequestQueue(); <span class="keyword">if</span> (mImageLoader == <span class="keyword">null</span>) { mImageLoader = <span class="keyword">new</span> ImageLoader(<span class="keyword">this</span>.mRequestQueue, <span class="keyword">new</span> LruBitmapCache()); } <span class="keyword">return</span> <span class="keyword">this</span>.mImageLoader; } <span class="keyword">public</span> <T> <span class="keyword">void</span> <span class="title">addToRequestQueue</span>(Request<T> req, String tag) { <span class="comment">// set the default tag if tag is empty</span> req.setTag(TextUtils.isEmpty(tag) ? TAG : tag); getRequestQueue().add(req); } <span class="keyword">public</span> <T> <span class="keyword">void</span> <span class="title">addToRequestQueue</span>(Request<T> req) { req.setTag(TAG); getRequestQueue().add(req); } <span class="keyword">public</span> <span class="keyword">void</span> <span class="title">cancelPendingRequests</span>(Object tag) { <span class="keyword">if</span> (mRequestQueue != <span class="keyword">null</span>) { mRequestQueue.cancelAll(tag); } } } 另外,你还需要一个Cache来存放请求的图片: ...

2015年8月6日 · 6 分钟 · 天边的星星

Android Paint之 setXfermode PorterDuffXfermode 讲解,androidsetxfermode

转载来自: http://blog.csdn.net/tianjian4592 前面关于paint的方法讲解里,讲到 setXfermode 就截止了,原因有两个: 那篇文章已经太长了,我自己都看不下去了; 2. setXfermode 在paint 里占有至关重要的地位; 基于以上两个原因,我们一起来看看这个方法有何妙用。 首先我们还是来看看关于这个方法的说明: /** * Set or clear the xfermode object. - 设置或清除xfermode对象; * Pass null to clear any previous xfermode. - 传递null以清除任何以前的xfermode。 * As a convenience, the parameter passed is also returned. - 为方便起见,也返回传递的参数。 * * @return xfermode */ public Xfermode setXfermode(Xfermode xfermode) { int xfermodeNative = 0; if (xfermode != null) xfermodeNative = xfermode.native_instance; native_setXfermode(mNativePaint, xfermodeNative); mXfermode = xfermode; return xfermode; } 这个方法传进一个 Xfermode 对象,而打开 Xfermode 发现里面没有提供任何可用的构造函数或方法,ctrl +T 看到它有三个子类: ...

2015年8月6日 · 8 分钟 · 天边的星星

Android 快速开发系列 ORMLite 框架最佳实践

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/39122981,本文出自【张鸿洋的博客】 上一篇已经对ORMLite框架做了简单的介绍:Android ORMLite 框架的入门用法~~本篇将介绍项目可能会使用到的一些用法,也为我们的使用ORMLite框架总结出一个较合理的用法。 通过上一篇的了解,我们使用ORMLite,需要自己写一个DatabaseHelper去继承OrmLiteSqliteOpenHelper,下面我们首先给出一个我认为比较靠谱的Helper的写法: 1、DatabaseHelper **[java]** [view plain](http://blog.csdn.net/lmj623565791/article/details/39122981#)[copy](http://blog.csdn.net/lmj623565791/article/details/39122981#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/465469)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/465469/fork) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="keyword">package</span> com.zhy.zhy_ormlite.db; - - <span class="keyword">import</span> java.sql.SQLException; - <span class="keyword">import</span> java.util.HashMap; - <span class="keyword">import</span> java.util.Map; - - <span class="keyword">import</span> android.content.Context; - <span class="keyword">import</span> android.database.sqlite.SQLiteDatabase; - - <span class="keyword">import</span> com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper; - <span class="keyword">import</span> com.j256.ormlite.dao.Dao; - <span class="keyword">import</span> com.j256.ormlite.support.ConnectionSource; - <span class="keyword">import</span> com.j256.ormlite.table.TableUtils; - <span class="keyword">import</span> com.zhy.zhy_ormlite.bean.Article; - <span class="keyword">import</span> com.zhy.zhy_ormlite.bean.Student; - <span class="keyword">import</span> com.zhy.zhy_ormlite.bean.User; - - <span class="keyword">public</span> <span class="keyword">class</span> DatabaseHelper <span class="keyword">extends</span> OrmLiteSqliteOpenHelper - { - <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> String TABLE_NAME = <span class="string">&#8220;sqlite-test.db&#8221;</span>; - - <span class="keyword">private</span> Map<String, Dao> daos = <span class="keyword">new</span> HashMap<String, Dao>(); - - <span class="keyword">private</span> DatabaseHelper(Context context) - { - <span class="keyword">super</span>(context, TABLE_NAME, <span class="keyword">null</span>, <span class="number">4</span>); - } - - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> onCreate(SQLiteDatabase database, - ConnectionSource connectionSource) - { - <span class="keyword">try</span> - { - TableUtils.createTable(connectionSource, User.<span class="keyword">class</span>); - TableUtils.createTable(connectionSource, Article.<span class="keyword">class</span>); - TableUtils.createTable(connectionSource, Student.<span class="keyword">class</span>); - } <span class="keyword">catch</span> (SQLException e) - { - e.printStackTrace(); - } - } - - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> onUpgrade(SQLiteDatabase database, - ConnectionSource connectionSource, <span class="keyword">int</span> oldVersion, <span class="keyword">int</span> newVersion) - { - <span class="keyword">try</span> - { - TableUtils.dropTable(connectionSource, User.<span class="keyword">class</span>, <span class="keyword">true</span>); - TableUtils.dropTable(connectionSource, Article.<span class="keyword">class</span>, <span class="keyword">true</span>); - TableUtils.dropTable(connectionSource, Student.<span class="keyword">class</span>, <span class="keyword">true</span>); - onCreate(database, connectionSource); - } <span class="keyword">catch</span> (SQLException e) - { - e.printStackTrace(); - } - } - - <span class="keyword">private</span> <span class="keyword">static</span> DatabaseHelper instance; - - <span class="comment">/**</span> - <span class="comment"> * 单例获取该Helper</span> - <span class="comment"> * </span> - <span class="comment"> * @param context</span> - <span class="comment"> * @return</span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">synchronized</span> DatabaseHelper getHelper(Context context) - { - context = context.getApplicationContext(); - <span class="keyword">if</span> (instance == <span class="keyword">null</span>) - { - <span class="keyword">synchronized</span> (DatabaseHelper.<span class="keyword">class</span>) - { - <span class="keyword">if</span> (instance == <span class="keyword">null</span>) - instance = <span class="keyword">new</span> DatabaseHelper(context); - } - } - - <span class="keyword">return</span> instance; - } - - <span class="keyword">public</span> <span class="keyword">synchronized</span> Dao getDao(Class clazz) <span class="keyword">throws</span> SQLException - { - Dao dao = <span class="keyword">null</span>; - String className = clazz.getSimpleName(); - - <span class="keyword">if</span> (daos.containsKey(className)) - { - dao = daos.get(className); - } - <span class="keyword">if</span> (dao == <span class="keyword">null</span>) - { - dao = <span class="keyword">super</span>.getDao(clazz); - daos.put(className, dao); - } - <span class="keyword">return</span> dao; - } - - <span class="comment">/**</span> - <span class="comment"> * 释放资源</span> - <span class="comment"> */</span> - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> close() - { - <span class="keyword">super</span>.close(); - - <span class="keyword">for</span> (String key : daos.keySet()) - { - Dao dao = daos.get(key); - dao = <span class="keyword">null</span>; - } - } - - } 1、整个DatabaseHelper使用单例只对外公布出一个对象,保证app中只存在一个SQLite Connection , 参考文章:http://www.touchlab.co/2011/10/single-sqlite-connection/ ...

2015年8月5日 · 10 分钟 · 天边的星星

Android使用UncaughtExceptionHandler捕获全局异常

Android系统的“程序异常退出”,给应用的用户体验造成不良影响。为了捕获应用运行时异常并给出友好提示,便可继承UncaughtExceptionHandler类来处理。通过Thread.setDefaultUncaughtExceptionHandler()方法将异常处理类设置到线程上即可。 1、异常处理类,代码如下: **[java]** [view plain](http://blog.csdn.net/hehe9737/article/details/7662123#)[copy](http://blog.csdn.net/hehe9737/article/details/7662123#) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="keyword">public</span> <span class="keyword">class</span> CrashHandler <span class="keyword">implements</span> UncaughtExceptionHandler { - <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String TAG = <span class="string">&#8220;CrashHandler&#8221;</span>; - <span class="keyword">private</span> <span class="keyword">static</span> CrashHandler INSTANCE = <span class="keyword">new</span> CrashHandler(); - <span class="keyword">private</span> Context mContext; - <span class="keyword">private</span> Thread.UncaughtExceptionHandler mDefaultHandler; - - <span class="keyword">private</span> CrashHandler() { - } - - <span class="keyword">public</span> <span class="keyword">static</span> CrashHandler getInstance() { - <span class="keyword">return</span> INSTANCE; - } - - <span class="keyword">public</span> <span class="keyword">void</span> init(Context ctx) { - mContext = ctx; - mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); - Thread.setDefaultUncaughtExceptionHandler(<span class="keyword">this</span>); - } - - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> uncaughtException(Thread thread, Throwable ex) { - <span class="comment">// if (!handleException(ex) && mDefaultHandler != null) {</span> - <span class="comment">// mDefaultHandler.uncaughtException(thread, ex);</span> - <span class="comment">// } else {</span> - <span class="comment">// android.os.Process.killProcess(android.os.Process.myPid());</span> - <span class="comment">// System.exit(10);</span> - <span class="comment">// }</span> - System.out.println(<span class="string">&#8220;uncaughtException&#8221;</span>); - - <span class="keyword">new</span> Thread() { - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> run() { - Looper.prepare(); - <span class="keyword">new</span> AlertDialog.Builder(mContext).setTitle(<span class="string">&#8220;提示&#8221;</span>).setCancelable(<span class="keyword">false</span>) - .setMessage(<span class="string">&#8220;程序崩溃了&#8230;&#8221;</span>).setNeutralButton(<span class="string">&#8220;我知道了&#8221;</span>, <span class="keyword">new</span> OnClickListener() { - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> onClick(DialogInterface dialog, <span class="keyword">int</span> which) { - System.exit(<span class="number"></span>); - } - }) - .create().show(); - Looper.loop(); - } - }.start(); - } - - <span class="comment">/**</span> - <span class="comment"> * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. 开发者可以根据自己的情况来自定义异常处理逻辑</span> - <span class="comment"> *</span> - <span class="comment"> * @param ex</span> - <span class="comment"> * @return true:如果处理了该异常信息;否则返回false</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">boolean</span> handleException(Throwable ex) { - <span class="keyword">if</span> (ex == <span class="keyword">null</span>) { - <span class="keyword">return</span> <span class="keyword">true</span>; - } - <span class="comment">// new Handler(Looper.getMainLooper()).post(new Runnable() {</span> - <span class="comment">// @Override</span> - <span class="comment">// public void run() {</span> - <span class="comment">// new AlertDialog.Builder(mContext).setTitle(&#8220;提示&#8221;)</span> - <span class="comment">// .setMessage(&#8220;程序崩溃了&#8230;&#8221;).setNeutralButton(&#8220;我知道了&#8221;, null)</span> - <span class="comment">// .create().show();</span> - <span class="comment">// }</span> - <span class="comment">// });</span> - - <span class="keyword">return</span> <span class="keyword">true</span>; - } - } 2、线程绑定异常处理类 ...

2015年8月5日 · 2 分钟 · 天边的星星

Github上README.md介绍

大标题 大标题一般显示工程名,类似html的<h1> 你只要在标题下面跟上=====即可 中标题 ———————————– 中标题一般显示重点项,类似html的<h2> 你只要在标题下面输入——即可 ### 小标题 小标题类似html的<h3> 小标题的格式如下 ### 小标题 注意#和标题字符中间要有空格 ### 注意!!!下面所有语法的提示我都先用小标题提醒了!!! ### 单行文本框 这是一个单行的文本框,只要两个Tab再输入文字即可 ### 多行文本框 这是一个有多行的文本框 你可以写入代码等,每行文字只要输入两个Tab再输入文字即可 这里你可以输入一段代码 ### 比如我们可以在多行文本框里输入一段代码,来一个Java版本的HelloWorld吧 public class HelloWorld { /** @param args */ public static void main(String[] args) { System.out.println(“HelloWorld!”); } } ### 链接 1.[点击这里你可以链接到www.google.com](http://www.google.com) 2.[点击这里我你可以链接到我的博客](http://guoyunsky.iteye.com) ###只是显示图片 ![github](http://github.com/unicorn.png “github”) ###想点击某个图片进入一个网页,比如我想点击github的icorn然后再进入www.github.com [![image]](http://www.github.com/) [image]: http://github.com/github.png “github” ### 文字被些字符包围 文字被些字符包围 只要再文字前面加上>空格即可 如果你要换行的话,新起一行,输入>空格即可,后面不接文字 但> 只能放在行首才有效 ### 文字被些字符包围,多重包围 文字被些字符包围开始 只要再文字前面加上>空格即可 如果你要换行的话,新起一行,输入>空格即可,后面不接文字 但> 只能放在行首才有效 ### 特殊字符处理 有一些特殊字符如<,#等,只要在特殊字符前面加上转义字符\即可 ...

2015年8月4日 · 2 分钟 · 天边的星星

Android studio使用Annotations框架

首页创建Android studio项目 在项目的build.gradle中添加如下代码(如此简单) buildscript { repositories { mavenCentral() } dependencies { // replace with the current version of the Android plugin classpath ‘com.android.tools.build:gradle:1.2.3’ // the latest version of the android-apt plugin classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.4’ } } repositories { mavenCentral() mavenLocal() } apply plugin: ‘com.android.application’ apply plugin: ‘android-apt’ def AAVersion = ‘3.3.2’//这个是Annotations的版本号,这个可以去Annotations官网查看,也可以在Android studio中Jcenter或者mavenCentral中查找最新版本号 dependencies { compile fileTree(include: [‘*.jar’], dir: ‘libs’) compile ‘com.android.support:appcompat-v7:22.2.0’ apt “org.androidannotations:androidannotations:AAVersion” compile “org.androidannotations:androidannotations-api:AAVersion” } apt { arguments { androidManifestFile variant.outputs[0].processResources.manifestFile // if you have multiple outputs (when using splits), you may want to have other index than 0 ...

2015年7月17日 · 2 分钟 · 天边的星星

Android实现推送方式解决方案

** 本文介绍在Android中实现推送方式的基础知识及相关解决方案。推送功能在手机开发中应用的场景是越来起来了,不说别的,就我们手机上的新闻客户端就时不j时的推送过来新的消息,很方便的阅读最新的新闻信息。这种推送功能是好的一面,但是也会经常看到很多推送过来的垃圾信息,这就让我们感到厌烦了,关于这个我们就不能多说什么了,毕竟很多商家要做广告。本文就是来探讨下Android中实现推送功能的一些解决方案,也希望能够起到抛砖引玉的作用。^_^** ** 1.推送方式基础知识: ** 在移动互联网时代以前的手机,如果有事情发生需要通知用户,则会有一个窗口弹出,将告诉用户正在发生什么事情。可能是未接电话的提示,日历的提醒,或是一封新的彩信。推送功能最早是被用于Email中,用来提示我们新的信息。由于时代的发展和移动互联网的热潮,推送功能更加地普及,已经不再仅仅用在推送邮件了,更多地用在我们的APP中了。 当我们开发需要和服务器交互的应用程序时,基本上都需要获取服务器端的数据,比如《地震应急通》就需要及时获取服务器上最新的地震信息。要获取服务器上不定时更新的信息,一般来说有两种方法:第一种是客户端使用Pull(拉)的方式,就是隔一段时间就去服务器上获取一下信息,看是否有更新的信息出现。第二种就是 服务器使用Push(推送)的方式,当服务器端有新信息了,则把最新的信息Push到客户端上。这样,客户端就能自动的接收到消息。 虽然Pull和Push两种方式都能实现获取服务器端更新信息的功能,但是明显来说Push方式比Pull方式更优越。因为Pull方式更费客户端的网络流量,更主要的是费电量,还需要我们的程序不停地去监测服务端的变化。 在开发Android和iPhone应用程序时,我们往往需要从服务器不定的向手机客户端即时推送各种通知消息。我们只需要在Android或IPhone的通知栏处向下一拉,就展开了Notification Panel,可以集中一览各种各样通知消息。目前IOS平台上已经有了比较简单的和完美的推送通知解决方案,我会在以后详细介绍IPhone中的解决方案,可是Android平台上实现起来却相对比较麻烦。 最近利用几天的时间对Android的推送通知服务进行初步的研究,也希望能和大家共同探讨一下。 ** 2. 几种常见的解决方案实现原理:** 1)轮询(Pull)方式:应用程序应当阶段性的与服务器进行连接并查询是否有新的消息到达,你必须自己实现与服务器之间的通信,例如消息排队等。而且你还要考虑轮询的频率,如果太慢可能导致某些消息的延迟,如果太快,则会大量消耗网络带宽和电池。 2)SMS(Push)方式:在Android平台上,你可以通过拦截SMS消息并且解析消息内容来了解服务器的意图,并获取其显示内容进行处理。这是一个不错的想法,我就见过采用这个方案的应用程序。这个方案的好处是,可以实现完全的实时操作。但是问题是这个方案的成本相对比较高,我们需要向移动公司缴纳相应的费用。我们目前很难找到免费的短消息发送网关来实现这种方案。 3)持久连接(Push)方式:这个方案可以解决由轮询带来的性能问题,但是还是会消耗手机的电池。IOS平台的推送服务之所以工作的很好,是因为每一台手机仅仅保持一个与服务器之间的连接,事实上C2DM也是这么工作的。不过刚才也讲了,这个方案存在着很多的不足之处,就是我们很难在手机上实现一个可靠的服务,目前也无法与IOS平台的推送功能相比。 Android操作系统允许在低内存情况下杀死系统服务,所以我们的推送通知服务很有可能就被操作系统Kill掉了。 轮询(Pull)方式和SMS(Push)方式这两个方案也存在明显的不足。至于持久连接(Push)方案也有不足,不过我们可以通过良好的设计来弥补,以便于让该方案可以有效的工作。毕竟,我们要知道GMail,GTalk以及GoogleVoice都可以实现实时更新的。 3.第一种解决方案:C2DM云端推送功能。 在Android手机平台上,Google提供了C2DM(Cloudto Device Messaging)服务,起初我就是准备采用这个服务来实现自己手机上的推送功能,并将其带入自己的项目中。 Android Cloud to Device Messaging (C2DM)是一个用来帮助开发者从服务器向Android应用程序发送数据的服务。该服务提供了一个简单的、轻量级的机制,允许服务器可以通知移动应用程序直接与服务器进行通信,以便于从服务器获取应用程序更新和用户数据。C2DM服务负责处理诸如消息排队等事务并向运行于目标设备上的应用程序分发这些消息。关于C2DM具体使用过程,大家可以去查阅相关的资料,在这里先让我们了解下大致方案情况。 下面是C2DM操作过程示例图: 但是经过一番研究发现,这个服务存在很大的问题: 1)C2DM内置于Android的2.2系统上,无法兼容老的1.6到2.1系统; 2)C2DM需要依赖于Google官方提供的C2DM服务器,由于国内的网络环境,这个服务经常不可用,如果想要很好的使用,我们的App Server必须也在国外,这个恐怕不是每个开发者都能够实现的; 3) 不像在iPhone中,他们把硬件系统集成在一块了。所以对于我们开发者来说,如果要在我们的应用程序中使用C2DM的推送功能,因为对于不同的这种硬件厂商平台,比如摩托罗拉、华为、中兴做一个手机,他们可能会把Google的这种服务去掉,尤其像在国内就很多这种,把Google这种原生的服务去掉。买了一些像什么山寨机或者是华为这种国产机,可能Google的服务就没有了。而像在国外出的那些可能会内置。 有了上述几个方面的制约,导致我最终放弃了这个方案,不过我想利用另外一篇文章来详细的介绍C2DM的框架以及客户端和App Server的相应设置方法,可以作为学习资源让我们有个参考的资料。 即然C2DM无法满足我们的要求,那么我们就需要自己来实现Android手机客户端与App Server之间的通信协议,保证在App Server想向指定的Android设备发送消息时,Android设备能够及时的收到。 ** 4. **第二种解决方案:MQTT协议实现Android推送功能。 采用MQTT协议实现Android推送功能也是一种解决方案。MQTT是一个轻量级的消息发布/订阅协议,它是实现基于手机客户端的消息推送服务器的理想解决方案。 wmqtt.jar 是IBM提供的MQTT协议的实现。我们可以从这里(https://github.com/tokudu/AndroidPushNotificationsDemo)下载该项目的实例代码,并且可以找到一个采用PHP书写的服务器端实现(https://github.com/tokudu/PhpMQTTClient)。 架构如下图所示: ** wmqtt.jar** 是IBM提供的MQTT协议的实现。我们可以从如下站点下载(http://www-01.ibm.com/support/docview.wss?rs=171&uid=swg24006006)它。我们可以将该jar包加入自己的Android应用程序中。 ** 5.**第三种解决方案:RSMB实现推送功能。 Really Small Message Broker (RSMB) ,他是一个简单的MQTT代理,同样由IBM提供,其查看地址是:http://www.alphaworks.ibm.com/tech/rsmb。缺省打开1883端口,应用程序当中,它负责接收来自服务器的消息并将其转发给指定的移动设备。 SAM是一个针对MQTT写的[PHP库](http://pecl.php.net/package/sam/download/0.2.0)。我们可以从这个[http://pecl.php.net/package/sam/download/0.2.](http://pecl.php.net/package/sam/download/0.2.)[](http://pecl.php.net/package/sam/download/0.2.0)地址下载它. send_mqtt.php是一个通过POST接收消息并且通过SAM将消息发送给RSMB的PHP脚本。 ** 6. **第四种解决方案:XMPP协议实现Android推送功能。 这是我希望在项目中采用的方案,因为目前它是开源的,对于其简单的推送功能它还是能够实现的。我们可以修改其源代码来适应我们的应用程序。 ...

2015年7月10日 · 1 分钟 · 天边的星星

直接拿来用!十大Material Design开源项目

** **本文详细介绍了十个Material Design开源项目,从示例、FAB、菜单、动画、Ripple到Dialog,看被誉为“Google第一次在设计语言和规范上超越了Apple”的Material Design是如何逐渐成为App的一种全新设计标准。 介于拟物和扁平之间的Material Design自面世以来,便引起了很多人的关注与思考,就此产生的讨论也不绝于耳。本文详细介绍了在Android开发者圈子里颇受青睐的十个Material Design开源项目,从示例、FAB、菜单、动画、Ripple到Dialog,看被称为“Google第一次在设计语言和规范上超越了Apple”的Material Design是如何逐渐成为App的一种全新设计标准。 1. MaterialDesignLibrary 在众多新晋库中,MaterialDesignLibrary可以说是颇受开发者瞩目的一个控件效果库,能够让开发者在Android 2.2系统上使用Android 5.0才支持的控件效果,比如扁平、矩形、浮动按钮,复选框以及各式各样的进度指示器等。 ![](http://dl2.iteye.com/upload/attachment/0103/5584/80416adf-b40f-31f9-b2e0-3986c8ab7790.jpg) 除上述之外,MaterialDesignLibrary还拥有SnackBar、Dialog、Color selector组件,可非常便捷地对应用界面进行设置。 进度指示器样式效果设置: Xml代码 <embed src="http://www.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" type="application/x-shockwave-flash" width="14" height="15"> </embed> </div> - <span class="tag"><</span><span class="tag-name">com.gc.materialdesign.views.ProgressBarCircularIndetermininate</span> - <span class="attribute">android:id</span>=<span class="attribute-value">&#8220;@+id/progressBarCircularIndetermininate&#8221;</span> - <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;32dp&#8221;</span> - <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;32dp&#8221;</span> - <span class="attribute">android:background</span>=<span class="attribute-value">&#8220;#1E88E5&#8221;</span> <span class="tag">/></span> Dialog: Java代码 <embed src="http://www.iteye.com/javascripts/syntaxhighlighter/clipboard_new.swf" type="application/x-shockwave-flash" width="14" height="15"> </embed> </div> - Dialog dialog = <span class="keyword">new</span> Dialog(Context context,String title, String message); - dialog.show(); 2. RippleEffect ...

2015年7月10日 · 3 分钟 · 天边的星星