AndroidStudio是Google I/O 2013大会上推出的Android开发环境,基于IntelliJ IDEA,和EclipseADT类似。AudioStudio使用Gradle来构建项目。Gradle是一款自动化编译部署测试工具。

本文主要介绍如果将EclipseADT的项目迁移到AndroidStudio。
1.为项目生成Gradle所需的文件

  • 项目节本结构

  • ADT版本在22以上,在项目上右击->Export,然后选择Generate Gradle build files。

  • 一路next,直到finish。搞定,这时候已经生成Gradle的相关文件,此时的结构

2.在AndroidStudio中导入项目

  • 打开AudioStudio,选择Import Project,选择项目的目录。OK即可导入。

  • 主要就是build.gradle文件。

扩展阅读

Express

Express是Node.js的一个Web框架,Web应用程序有公用的模式,所以使用框架来构建经常事半功倍。其他一些成熟的框架,比如:

  • Ruby on Rails(Ruby)
  • Sinatra(Ruby)
  • Django(Python)
  • Zend(PHP)
  • CodeIgniter(PHP)

一些使用Express能做的事情有:

  • 基于JSON的API
  • 单页面Web应用程序
  • 事实Web应用程序

安装Express:npm install -g express
使用-g标记表示Express将是全局安装。

Express项目文件结构如下:

  • app.js
    app.js是用来启动应用程序的应用程序文件夹,它包含应用程序的配置信息。
  • node_modules
    用来保存在pack.json中定义并且已经安装的Node模块
  • package.json
    提供应用程序的信息,包括运行应用程序所需安装的依赖模块
  • public
    Web进行服务的公共文件夹,在这个文件夹中可以看到样式单、javascript和图片
  • routes
    路由,定义了应用程序应该响应的页面
  • views
    视图文件夹定义应用程序的布局
    在views文件夹有很多以.jade为扩展名的文件,Express利用模板引擎将视图编译成HTML,默认情况,Express使用Jade作为模板引擎。

Jade

Jade通过缩进定义页面结构,如果一行在上一行下面缩进,就认为它是上一行的子行。

  • html 编译后是:
    这里可以使用任何HTML标记(body、section、p等等)
  • 要给标记使用id,可加上一个# 号后跟id名称,注意不允许有空格
    section# wrapper 编译后:
  • 可以添加一个类,方法是加上一个小数点后跟类的名称。
    p.highlight 编译后:

  • 急需要类也需要id
    section# wrapper.class-name 编译后:
  • Jade也支持在一个标记上有多个类
    p.first.second.third.fourth 编译后:

  • 为了创建HTML结构,要使用缩进
1
2
p
span

编译后:

1
<p><span></span></p>

要标记中加入文本,只需在标记定义后加入即可
h1 Very important heading 编译后:

Very important heading

  • Jade支持管道描述符(|)组织大文本
1
2
3
4
p
| Text can be over
| many lines
| after a pipe symbol

编译后:

1
<p>Text can be over many lines after a pipe symbol</p>

Jade输出数据

Jade使用两个特殊符号来决定应该如何翻译代码,当一个字符是减号(-),用于告诉随后的代码应当被执行。第二个字符是字符(=)告诉解释器要对对代码进行演算、转义,然后输出。

变量

  • -var foo = bar
    变量设置之后可以再以后使用:
    p I want to learn to use variables.Foo is # {foo}!
    ”# {变量}“这个特殊语法将用变量来代替:

I want to learn to use variables.Foo is bar!

#### 循环 循环用来迭代数组和对象。
1
2
3
- users = ['Sally','Joseph','Michael','Sanjay']
- each user in users
p= user

编译后:

1
2
3
4
<p>Sally</p>
<p>Joseph</p>
<p>Michael</p>
<p>Sanjay</p>

也可以使用for关键字

1
2
- for user in users
p= user

对象进行迭代:

1
2
3
4
5
- obj = {first_name:'George',surname:'Ornbo'}
- each val,key in obj
li # {key}:# {val}
```
编译后:
  • first_name:George
  • surname:Ornbo
  • 1
    #### 条件
    - awake = false - if (awake) p You are awake! Make coffee! - else p You are sleeping
    1
    2
    `if`和`else`关键字之前的减号(-)是可选的
    #### 内联(inline)JavaScript
    script alert('You can execute inline JavaScript through Jade')
    1
    2
    ##### 包含(include)
    Jade通过include关键字后跟想要包含的模板来支持包含功能
    html body include includes/header ```

    用于Windows和OS X的安装程序可以再Node.js的主页下载:http://nodejs.org/

    验证Node.js是否正确安装

    在命令行中输入node可以看到以下提示:

    First Code

    1
    2
    3
    4
    5
    6
    7
    // server.js
    var http = require('http')
    http.createServer(function (req,res){
    res.writeHead(200,{'Content-Type':'text/plain'});
    res.end('Hello Node.js\n');
    }).listen(3000,"127.0.0.1");
    console.log("Server running at http://128.0.0.1:3000/");

    在命令行中执行node server.js,一个简单的web吴福气就完成了

    npm

    npm(Node Package Manager)是Node.js的包管理器,它允许开发者在Node.js应用程序中创建、共享并重用模块。

    • 安装模块
      npm install [module_name]

    • 使用模块
      下载之后必须请求(require)它们,var module = require('module');

    • 如何找模块

      1. 官方来源:在http://search.npmjs.org/上有一个官方基于Web的npm搜索工具。也可以在nmp命令行工具来搜索Node.js模块npm search irc
      2. 非官方来源:如http://blago.dachev.com/modules站点,该站点可以提供了Github上某个项目的围观者数量、分叉(fork)数量以及问题数量。或者http://eirikb.github.com/nipster/根据GitHub上的分叉数量对项目评级。
    • 本地和全局的安装

      1. 本地安装:本地安装意味着库将安装在项目本地的一个名为node_modules的文件夹下以便项目使用,这是默认行为。
        ├ foo.js
        ├ node_modules/module_name
      2. 全局安装:有些模块可能任何一个位置都能运行这些可执行文件,需要全局安装,只需要在安装时加上-g标记。npm install -g express
    • 查找模块文档
      通过npm docs [module_name]一般就能查看文件,还可以使用npm bugs [module_name]查看项目的Bug

    • 使用package.json指定依赖关系(dependency)
      npm允许开发人员使用package.json文件来指定应用程序中要用的模块,并且通过单个命令来安装它们npm install,如下例

      1. 创建一个模块foo.js
        1
        2
        3
        4
        var _ = require('underscore');
        _.each([1,2,3],function(num){
        console.log("underscore.js says " + num);
        });
      2. 创建一个package.json
        1
        2
        3
        4
        5
        6
        7
        {
        "name":"example02",
        "version":"0.0.1",
        "dependencies":{
        "underscore":"~1.2.1"
        }
        }
      3. 运行npm install
        可以看在underscore库安装在了node_modules文件夹下

    Node.js目的

    Node.js网站提供了的队Node.js的一段简短描述

    Node.js是构建在Chrome的JavaScript运行时之上的一个平台,用于简单构建快速的、可扩展的网络应用程序。Node.js使用事件驱动的、非阻塞的I/O模型,这让其既轻量又高效,是运行于不同发布设备上的数据密集型实时应用程序的完美平台。

    回调

    函数可以被作为参数传递到另一个函数中,然后被调用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var fs = require('fs');

    fs.readFile('somefile.txt','utf8',function(err,data){
    if(err)throw err;

    > Blockquote

    console.log(data);
    });
    1. fs(filesystem)模块被请求,以便在脚本中使用
    2. 将文件系统上的文件路径作为第一个参数提供给fs.readFile方法
    3. 第二个参数是utf8,表示文件编码
    4. 被回调函数作为第三个参数提供给fs.readFile方法
    5. 回调函数的第一个参数是err,用于保存在读取文件时返回错误
    6. 回调函数的第二个参数是data,用于保存读取文件所返回的数据
    7. 一旦文件被读取,回调就会被调用
    8. 如果err为真,那么就会抛出错误
    9. 如果err为假,那么来自文件的数据就可以使用

    使用curl查看HTTP表头

    概述

    ContentProvider是Android应用对外开放的数据接口,只要符合它所定义的Uri格式的请求,均可以正常访问执行操作。其他的Android应用可以使用ContentResolver对象通过与ContentProvider同名的方法请求执行,被执行的就是ContentProvider中的同名的方法。所以ContentProvider很多对外可以访问的方法,在ContentResolver中均有同名的方法,是一一对应的,如图:

    Uri

    在Android中,Uri是一种比较常见的资源访问方式,而对ContentProvider而言,Uri也是有固定格式的:
    :////

    • :ContentProvider的srandard_prefix始终是content://
    • :ContentProvider的名称
    • :请求的数据类型
    • :指定请求的特定数据

    ContentProvider

     ContentProvider也是Android应用的四大组件之一,所以也需要在AndroidManifest.xml文件中进行配置。而且某个应用程序通过ContentProvider暴露了自己的数据操作接口,那么不管该应用程序是否启动,其他应用程序都可以通过这个接口来操作它的内部数据。
     Android附带了许多有用的ContentProvider,但是本篇博客不会涉及到这些内容的,以后有时间会再讲解。Android附带的ContentProvider包括:

    • Browser:存储如浏览器的信息。
    • CallLog:存储通话记录等信息。
    • Contacts:存储联系人等信息。
    • MediaStore:存储媒体文件的信息。
    • Settings:存储设备的设置和首选项信息。
      在Android中,如果要创建自己的内容提供者的时候,需要扩展抽象类ContentProvider,并重写其中定义的各种方法。然后在AndroidManifest.xml文件中注册该ContentProvider即可。

    ContentProvider是内容提供者,实现Android应用之间的数据交互,对于数据操作,无非也就是CRUD而已。下面是ContentProvider必须要实现的几个方法:

    • onCreate():初始化提供者。
    • query(Uri, String[], String, String[], String):查询数据,返回一个数据Cursor对象。
    • insert(Uri, ContentValues):插入一条数据。
    • update(Uri, ContentValues, String, String[]):根据条件更新数据。
    • delete(Uri, String, String[]):根据条件删除数据。
    • getType(Uri) 返回MIME类型对应内容的URI。

    除了onCreate()和getType()方法外,其他的均为CRUD操作,这些方法中,Uri参数为与ContentProvider匹配的请求Uri,剩下的参数可以参见SQLite的CRUD操作,基本一致。
    还有两个方法:call()和bulkInsert()方法,使用call,理论上可以在ContentResolver中执行ContentProvider暴露出来的任何方法,而bulkInsert()方法用于插入多条数据。

    在ContentProvider的CRUD操作,均会传递一个Uri对象,通过这个对象来匹配对应的请求,那么如何确定一个Uri执行哪项操作呢?需要用到一个UriMatcher对象,这个对象用来帮助内容提供者匹配Uri,它所提供的方法非常简单,仅有两个:

    • void addURI(String authoity,String path,int code):添加一个Uri匹配项,authtity为AndroidManifest.xml中注册的ContentProvider的authority属性;path为一个路径,可以设置通配符,# 表示任意数字,*表示任意字符;code为自定义的一个Uri代码
    • int match(Uri uri):匹配传递的Uri,返回addUri()传递的Code参数。

    在创建好一个ContentProvider之后,还需要在AndroidManifest.xml文件中对ContentProvider进行配置,使用一个<provider…/>节点,一般只需要设置两个属性即可访问,一些额外的属性就是为了设置访问权限而存在的

    • android:name:provide的响应类
    • android:authorities:Provider的唯一标识,用于Uri匹配,一般为ContentProvider类的全名

    ContentResolver

    ContentResolver,内容访问者。可以通过ContentResolver来操作ContentProvider所暴露处理的接口。一般使用Content.getContentResolver()方法获取ContentResolver对象,上面已经提到ContentResolver的很多方法与ContentProvider————对应,所以它存在insert、query、update、delete等方法。

    getType()中的MIME

    MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型。在ContentProvider中的getType方法,返回的就是一个MIME的字符串。如果支持需要使用ContentProvider来访问数据,getType()完全可以返回一个Null,并不影响效果,但是覆盖ContentProvider的getType方法对于用new Intent(String action,Uri uri)方法启动activity是很重要的,如果它返回的MIME type和activity在中定义的data的MIME type不一致,将造成activity无法启动。
    getType返回的字符串,如果URI针对的是单条数据,则返回的字符串以vnd.android.cursor.item/开头;如果是多条数据,则以vnd.android.cursor.dir/开头。

    访问权限

    对于ContentProvider暴露出来的数据,应该是储存在自己应用内存中的数据,对于一些储存在外部储存器上发数据,并不能限制访问权限,使用ContentProvider就没有意义了。对于ContentProvider而言,有很多权限控制,可以AndroidManifest.xml文件中对节点的属性进行配置,一般使用如下一些属性设置:

    • android:grantUriPermssions:临时许可标志。
    • android:permission:Provider读写权限。
    • android:readPermission:Provider的读权限。
    • android:writePermission:Provider的写权限。
    • android:enabled:标记允许系统启动Provider。
    • android:exported:标记允许其他应用程序使用这个Provider。
    • android:multiProcess:标记允许系统启动Provider相同的进程中调用客户端。

    基础部分
    数据类型基于C和Objective-C的基础上提出,Int是整形,DoubleFloat是浮点型,Bool是布尔型,String是字符串。Swift还有两个集合类型ArrayDictionary
    除了我们熟悉的类型,Swift 还增加了 Objective-C 中没有的类型比如元组(Tuple)。元组可以让你创建或者传递一组数据,比如作为函数的返回值时,你可以用一个元组可以返回多个值。
    Swift 还增加了可选(Optional)类型,用于处理值缺失的情况。可选表示“那儿有一个值,并且它等于 x ”或者“那儿没有值”。可选有点像在 Objective-C 中使用nil,但是它可以用在任何类型上,不仅仅是类。可选类型比 Objective-C 中的nil指针更加安全也更具表现力,它是 Swift 许多强大特性的重要组成部分。
    Swift 是一个类型安全的语言,会阻止不正确的值传递。

    常量和变量

    常量和变量必须在使用前声明,用let来声明常量,用var来声明变量。

    1
    2
    let a = 10
    var b = 1

    以在一行中声明多个常量或者多个变量,用逗号隔开:

    1
    var x = 0.0, y = 0.0, z = 0.0

    类型标注,在声明常量和变量的时候加上类型标注,说明变量或者常量要存储的类型。

    1
    var str:String

    变量名不能包含数学符号,箭头,保留的关键字,Unicode码位,连线和制表符。不能以数字开头。

    输出常量和变量

    使用println函数来输出当前的变量或常量的值:

    1
    println(myValue)

    使用\()语法可以将值转换成字符串类型

    1
    println("I have a value -- \(myValue)")

    注释

    与C语言相通,可以使用//,/*做单行、多行注释,也可以嵌套

    1
    2
    3
    4
    5
    6
    7
    8
    // 单行注释
    /*
    多行注释
    */
    /* 嵌套
    /* 注释 */
    * 嵌套
    */

    分号

    Swift 并不强制要求你在每条语句的结尾处使用分号(;),同一行内写多条独立的语句则必须加上分号

    1
    let cat = "pop";println(cat)

    整数

    整数可以是有符号的或者无符号的
    如8位无符号整数的类型是UInt8,32位有符号的整数是Int32

    整数范围

    可以根据不同数据类型的minmax来获取对应的最大值和最小值

    1
    2
    let minValue = UInt8.min
    let maxValue = UInt8.max

    Int

    长度默认与平台的原生字长相同

    • 在32位平台上,IntInt32长度相同。
    • 在64位平台上,IntInt64长度相同。

    浮点数

    • Double表示64位浮点数。当你需要存储很大或者很高精度的浮点数时请使用此类型。
    • Float表示32位浮点数。精度要求不高的话可以使用此类型。

    类型安全和类型推断

    Swift 是一个类型安全(type safe)的语言。不匹配的类型会被标记为错误。

    1
    2
    3
    4
    5
    let meaningOfLife = 42
    // meaningOfLife 会被推测为 Int 类型
    //如果你没有给浮点字面量标明类型,Swift 会推断你想要的是Double:
    let pi = 3.14159
    // pi 会被推测为 Double 类型

    数值型字面量

    • 一个十进制数,没有前缀
    • 一个二进制数,前缀是0b
    • 一个八进制数,前缀是0o
    • 一个十六进制数,前缀是0x

    如果一个十进制数的指数为exp,那这个数相当于基数和10^exp的乘积:

    • 1.25e2 表示 1.25 × 10^2,等于 125.0。
    • 1.25e-2 表示 1.25 × 10^-2,等于 0.0125。

    如果一个十六进制数的指数为exp,那这个数相当于基数和2^exp的乘积:

    • 0xFp2 表示 15 × 2^2,等于 60.0。
    • 0xFp-2 表示 15 × 2^-2,等于 3.75。

    类型别名

    类型别名(type aliases)就是给现有类型定义另一个名字。你可以使用typealias关键字来定义类型别名。

    1
    typealias AudioSample = UInt16

    元组

    元组(tuples)把多个值组合成一个复合值。元组内的值可以使任意类型,并不要求是相同类型。

    1
    let http404Error = (400,"Not Found")

    元组分解

    1
    2
    let (statusCode,statusMessage) = http404Error
    println(statusCode) //输出404

    也可以使用一部分元组,忽略的部分使用下划线(_)标记

    1
    let (statusCode,_) = http404Error

    也可以实现下标访问单个元素

    1
    let statusCode = http404Error.0

    可以定于元组的时候给单个元素命名

    1
    2
    let http200Status = (statusCode:200,description:"OK")
    println(http200Status.statusCode)

    可选值(Optional)

    使用可选值来处理值可能缺失的情况

    1
    2
    // 设置num是一个可选值,并赋值为3
    let num? Int = 3

    if语句及强制解析

    if语句可以判断一个可选值是否包含值,如果可选类型有值返回ture,没有值返回false

    1
    2
    3
    4
    // num为一个可选值
    if var value = num {
    // 有值
    }

    确定可选类型包含值后,可以再可选的名字后面加上感叹号(!)来获取值。
    这个感叹号表示:我知道这个可选值有值,请使用它

    1
    num!.toString()

    可选绑定

    使用可选绑定来判断可选类型是否包含值,如果包含就把赋值给一个临时常量或者变量。

    1
    if let temp = someOptional

    nil

    可以给可选变量赋值为nil来表示它没有值

    1
    2
    var someOptinal:Int? = nil
    someOptinal = 3

    如果在声明可选变量或常量的时候没有赋值,默认设置为nil

    隐式解析可选类型

    改用感叹号来声明一个隐式解析可选类型,隐式可选类型就是一个普通的可选类型,但是可以被当做非可选类型来使用,并不需要每次都解析来获取值。

    1
    2
    let value : String! = "Hello"
    println(value) // 不需要value!

    隐式解析可选类型主要被用作Swift中类的构造过程
    隐式解析可选类型可以被当做普通可选类型来判断它是否有值

    1
    2
    3
    if value {
    // 有值
    }

    断言

    断言用作出结束代码运行并通过调试来找到原因

    使用断言进行调试

    断言会在运行时判断一个逻辑条件是否为true,当条件为真,运行某段代码,条件为假,代码运行停止,应用被终止
    例如使用全局assert函数来写一个断言,向assert函数传入一个结果为true或者false的表达式以及一条信息,当表达式为false的时候这条信息会被显示

    1
    2
    3
    let age = -3
    assert(age >= 0,"岁数不能小于0")
    // 断言会被触发

    何时使用断言

    当条件可能为假时使用断言,但是最终一定要保证条件为真,这样代码才能继续运行,断言的适用场景

    • 整数类型的下标索引被传入一个自定义下标脚本实现,但是下标索引可能太小或者太大
    • 需要给函数传入一个值,但是非法的值可能导致函数不能正常运行
    • 一个可选值现在是nil,但是后续的代码运行时需要一个非nil

    基本运算符

    Swift支持大部分标准C语言的运算符,且改进许多特性来减少常规的编码错误,如:赋值符(=)不返回值,以防止把想要判断相等运算符(==)的地方写错导致赋值的错误。数值运算符(+,-,*,、,%)会检测并不允许值溢出。允许使用Swift的溢出运算符来实现溢出。
    区别于C语言,在Swift中可以对浮点数进行取余运算(%),Swift还提供了表达两数之间的值的区间的运算符(a..ba...b)表达一个区间的数值。

    数值运算符

    赋值表达用一个值来初始化或更新变量或常量

    1
    2
    3
    let b = 10;
    var a = 5;
    a = b

    但赋值不返回任何值

    1
    2
    3
    if x = y {
    // 此句错误,因为x = y表达式不返回值
    }

    数值运算

    • 加法(+)
    • 减法(-)
    • 乘法(*)
    • 除法(/)
      Swift默认不允许数值运算中出现溢出情况,但是可以使用溢出运算符来达到有目的的溢出(如a &+ b)
      加法可以用于String的拼接
    1
    "heloo" + " world"

    两个Character值或一个String和一个Character值,相加会生成一个新的String值

    求余运算

    1
    2
    9 % 4 // 等于1
    -9 % 4 // 等于-1 4*(-2)+(-1) = 9

    浮点数求余计算

    1
    8 % 2.5 // 等于0.5

    自增和自增运算

    和 C 语言一样,Swift 也提供了方便对变量本身加1或减1的自增(++)和自减(–)的运算符。其操作对象可以是整形和浮点型。

    • 当++前置的时候,先自増再返回。
    • 当++后置的时候,先返回再自增。

    复合赋值(Compound Assignment Operators)

    Swift也提供把其他运算符和赋值运算符组合的复合赋值运算符

    1
    2
    var a = 1
    a += 2 // a = 3

    比较运算

    • 等于(==)
    • 不等于(!=)
    • 大于(>)
    • 小于(<)
    • 大于等于(>=)
    • 小于等于(<=)
      Swift还提供了恒等于===和恒不等于!==来比较两个对象是否饮用同一个对象的实例

    三元条件运算(Ternary Conditional Operator)

    问题 ? 答案1 : 答案2,如果问题成立,返回答案1的结果; 如果不成立,返回答案2的结果。

    1
    let value = (boolValue ? 10 : 30)

    三元条件运算提供有效率且便捷的方式来表达二选一的选择。

    区间运算符

    闭区间运算符

    a...b定义了一个包含从ab所有值的区间,闭区间运算符在迭代一个区间的所有值时非常有用,比如for-in循环中:

    1
    2
    3
    for index in 1...5{
    //
    }

    半闭区间

    a..b定义了一个从ab但不包括b的区间。

    1
    2
    3
    4
    5
    let names = ["Anna","Alex","Brian","Jack"]
    let count = name.count
    for i in 0..count {
    //
    }

    逻辑运算

    • 逻辑非(!)
    • 逻辑与(&&)
    • 逻辑或(||)

    Gradle

    • 什么是Gradle?
      Gradle 是以 Groovy 语言为基础,面向Java应用为主,基于DSL语法的自动化构建工具。说到Java的自动化构建工具。
      使用Gradle构建Android项目的优点:
    • 在IDE环境和命令行下使用同一个构建系统
    • 改进的依赖关系管理
    • 更容易地集成到自动构建系统

    Gradle 基本概念

    如果你用Android Studio新建一个项目的时候,默认生成一大堆关于gradle的东西,其中最重要的是一个build.gradle的文件,内容如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    buildscript {
    // 声明用本地maven库查找依赖
    repositories {
    mavenCentral()
    }
    dependencies {
    classpath 'com.android.tools.build:gradle:0.8.+'
    }
    }
    // 声明项目是一个android构建
    apply plugin: 'android'
    // SDK版本 build工具版本
    android {
    compileSdkVersion 19
    buildToolsVersion "19.0.0"
    // 版本细节
    defaultConfig {
    minSdkVersion 14
    targetSdkVersion 19
    versionCode 1
    versionName "1.0"
    }
    // 发行版定义
    buildTypes {
    release {
    runProguard false
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
    }
    }
    }

    dependencies {
    compile 'com.android.support:support-v4:19.0.+'
    }

    buildscript节点的内容完全不用动,大概意思就是支持maven,声明Gradle的版本。
    apply plugin节点声明构建的项目类型,这里当然是android了
    android节点设置编译android项目的参数,接下来,我们的构建android项目的所有配置都在这里完成。

    构建一个Gradle Android项目

    除了最基本的Android Gradle配置文件,项目常常需要引入第三方的jar包,比如依赖一个support_v4的jar包,则完整的build.gradle文件如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    buildscript {
    repositories {
    mavenCentral()
    }
    dependencies {
    classpath 'com.android.tools.build:gradle:0.8.+'
    }
    }
    apply plugin: 'android'

    android {
    compileSdkVersion 19
    buildToolsVersion "19.0.0"

    defaultConfig {
    minSdkVersion 14
    targetSdkVersion 19
    versionCode 1
    versionName "1.0"
    }
    buildTypes {
    release {
    runProguard false
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
    }
    }
    }

    dependencies {
    //单文件依赖
    compile files('libs/android-support-v4.jar")
    //某个文件夹下面全部依赖
    compile fileTree(dir: 'libs', include: '*.jar')
    }

    接着在命令行切换到项目目录下

    1
    gradle clean

    如果是第一次使用gradle构建,则会下载相关依赖包并且对环境进行初始化,如果出错了,一般可能是下载超时,试多几次即可,最后你会看到如下提示:BUILD SUCCESSFUL 完成以上的步骤,就可以正式使用gralde 构建你的android项目了。

    接着执行

    1
    gradle build

    就完成了android 项目的构建了。如果,你是照着以上步骤走的话,你将会在项目目录里面看到一个build 的目录,里面就是用gradle 构建android项目的全部东西了。最终打包的apk 就在build/apk 目录下了。然后,你会发现,两个apk 一个是 [项目名]-debug-unaligned [项目名]-release-unsigned,看名字就猜到一个是调试模式没有进行优化的apk(可直接安装),一个是release模式但没有签名的apk(不可直接安装)。

    打包签名

    默认输出 release apk 是没有签名的,那么我们需要签名的很简单,只需要在android{}里面补充加上如下代码即可。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // 签名
    signingConfigs {
    myConfig {
    storeFile file("storm.keystore")
    storePassword "storm"
    keyAlias "storm"
    keyPassword "storm"
    }
    }

    buildTypes{
    release {
    signingConfig signingConfigs.myConfig
    runProguard true
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
    }
    }

    然后,运行

    1
    2
    gradle clean 
    gradle build

    接着在build/apk目录下就生成了我们需要的签名的apk。

    创建SQLite数据库推荐继承SQLiteOpenHelper类,然后重写其中的onCreate()方法,在onCreate()方法中,执行数据库创建的SQL语句。而SQLiteOpenHelper不仅仅用于SQLite的创建,也可以对其进行维护,以及获得SQLiteDatabase这个数据库操作对象。
    SQLiteOpenHelper提供了两个构造器,用于传递当前上下文对象以及SQLite数据库版本信息,在SQLiteOpenHelper的继承类构造方法中,会调用它:

    1
    2
    3
    // context是上下文对象;name是数据库名称;factory是一个允许子类在查询时使用的游标,一般不用传null;version是数据库版本号;errorHandler是一个接口,当数据库错误的时候,执行的补救方法。
    SQLiteOpenHelper(Context context,String name,SQLiteDatabase.CursorFactory factory,int version).
    SQLiteOpenHelper(Context context,String name,SQLiteDatabase.CursorFactroy factory,int version,DatabaseErrorHandler errorHandler).

    常用的方法:

    • String getDatabaseName():获取数据库名。
    • SQLiteDatabase getReadableDatabase():创建或者打开一个可读的数据库对象。
    • SQLiteDatabase getWritableDatabase():创建或者打开一个可读/写的数据库对象。
    • abstract void onCreate(SQLiteDatabase db):当第一次调用SQLiteOpenHelper的时候执行,之后再次调用将不再执行,一般用于完成数据库初始化的工作。
    • void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion):当数据库版本号发生向上更新时,被执行。
    • void onDowngrade(SQLiteDatabase db,int oldVersion,int newVersion)当数据库版本号发生向下更新时,被执行。

    执行CRUD
     当使用SQLiteOpenHelper的getReadableDatabase()或者getWritableDatabase()方法获取到SQLiteDatabase对象,就可以对这个数据库进行操作了。

    对于熟悉SQL语句的开发者而言,其实只需要使用两个方法,即可执行所有CRUD操作,以下方法提供多个重载方法:

    • void execSQL():通过SQL语句执行一条非查询语句。
    • Cursor rawQuery():通过SQL语句执行一条查询语句。

    AppDelegate.h与AppDelegate.cpp文件

    这两个文件时Cocos2d-x游戏的入口文件,控制着游戏的生命周期,除去构造函数和析构函数外,共有 3 个方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // 应用程序启动后将调用这个方法。默认的实现中已经包含了游戏启动后的必要准备
    bool applicationDidFinishLaunching()
    {
    // 初始化游戏引擎控制器Director,以便启动游戏引擎
    auto director = Director::getInstance();
    auto glview = director->getOpenGLView();
    if(!glview){
    glview = GLView::create("My Game");
    director->setOpenGLView(glview);
    }
    // 启动FPS显示
    director->setDisplayStats(true);
    // 设置绘制间隔
    director->setAnimationInterval(1.0 / 6.0);

    auto scence = HelloWorld::createScene();
    director->runWithScene(scence);

    return true;
    }

    这段代码首先对引擎进行必要的初始化,然后开启了 FPS 显示。FPS 即每秒帧速率,也就是屏幕每秒重绘的次数。启用了FPS 显示后,当前 FPS 会在游戏的左下角显示。通常在游戏开发阶段,我们会启用 FPS 显示,这样就可以方便地确定游戏运行是否流畅。

    接下来是设置绘制间隔。绘制间隔指的是两次绘制的时间间隔,因此绘制间隔的倒数就是 FPS 上限。对于移动设备来说,我们通常都会将 FPS 限制在一个适当的范围内。过低的每秒重绘次数会使动画显示出卡顿的现象,而提高每秒重绘次数会导致设备运算量大幅增加,造成更高的能耗。人眼的刷新频率约为 60 次每秒,因此把 FPS 限定在 60 是一个较为合理的设置,Cocos2d-x 就把绘制间隔设置为 1/60 秒。至此,我们已经完成了引擎的初始化,接下来我们将启动引擎。

    最后也是最关键的步骤,那就是创建 Hello World 场景,然后指派 Director 运行这个场景。对于游戏开发者而言,我们需要在此处来对我们的游戏进行其他必要的初始化,例如读取游戏设置、初始化随机数列表等。程序的最末端返回 true,表示程序已经正常初始化。

    void applicationDidEnterBackground()。当应用程序将要进入后台时,会调用这个方法。具体来说,当用户把程序切换到后台,或手机接到电话或短信后程序被系统切换到后台时,会调用这个方法。此时,应该暂停游戏中正在播放的音乐或音效。动作激烈的游戏通常也应该在此时进行暂停操作,以便玩家暂时离开游戏时不会遭受重大损失。

    void applicationWillEnterForeground()。该方法与 applicationDidEnterBackground()成对出现,在应用程序回到前台 时被调用。相对地,我们通常在这里继续播放刚才暂停的音乐,显示游戏暂停菜单等。

    1. abs(singedNumber):返回给定的有符号数字的绝对值
    1
    2
    abs(-1) == 1
    abs(-42) == 42
    1. contains(sequence,element):判断给定的序列(如数组)是否包含特定的元素
    1
    2
    3
    4
    var languages = ["Swift","Objective-C"]
    contains(languages,"Swift") == true
    contains(languages,"Java") == false
    contains([29,85,42,96,75],42) == true
    1. drop

    1. abs(singedNumber):返回给定的有符号数字的绝对值
    1
    2
    abs(-1) == 1
    abs(-42) == 42
    1. contains(sequence,element):判断给定的序列(如数组)是否包含特定的元素
    1
    2
    3
    4
    var languages = ["Swift","Objective-C"]
    contains(languages,"Swift") == true
    contains(languages,"Java") == false
    contains([29,85,42,96,75],42) == true
    1. drop