├── 独孤九剑.jpg ├── Android-独孤九剑.png ├── README.md ├── 第十天_多媒体编程.md ├── 第四天_网络编程.md ├── 第十一天_新特性、样式与主题.md ├── 第五天_网络编程.md ├── 第二天_数据存储和读取.md ├── 第八天_服务.md ├── 第一天_Android入门.md ├── 第九天_内容提供者.md ├── 第六天_Activity页面跳转和数据传递_.md ├── 第三天_数据存储和界面展现.md ├── 第七天_广播与服务.md └── LICENSE /独孤九剑.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuGuQiuBai/Android-Notes/HEAD/独孤九剑.jpg -------------------------------------------------------------------------------- /Android-独孤九剑.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuGuQiuBai/Android-Notes/HEAD/Android-独孤九剑.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Android基础笔记 3 | - 适合零基础入门。 4 | - 此笔记是本人辛辛苦苦一个个字码出来的,转载请保留出处。 5 | 6 | ## Disclaimer 7 | 版权归原作者所有,欢迎自由转载-非商用-非衍生-保持署名和链接。 8 | -------------------------------------------------------------------------------- /第十天_多媒体编程.md: -------------------------------------------------------------------------------- 1 | 2 | ##多媒体编程 3 | 4 | 5 | 文本、图片、音频、视频 6 | 7 | #图片的处理 8 | ----- 9 | ###01 计算机表示图形的形式 10 | 11 | 图片的大小 = 图片的总像素 * 每个像素的大小 12 | 13 | Android用ARGB表示颜色信息:每个像素占4个字节 14 | 15 | 1. bmp高质量保存 16 | 单色:只能表示两种颜色,黑和白 17 | 需要使用两个数字:0和1 18 | 需要使用一个长度为1的二进制数字 19 | 每个像素占用1/8个字节 20 | 16色:只能表示16种颜色 21 | 需要16个数字:0-15 22 | 换算成二进制表示:0000 - 1111 23 | 需要一个长度为4的二进制数字 24 | 每个像素占用1/2个字节 25 | 256色:只能表示256种颜色 26 | 需要256个数字:0-255 27 | 二进制表示:0000 0000 - 1111 1111 28 | 需要长度为8的二进制数字 29 | 每个像素占用1个字节 30 | 24位色: 31 | 每个像素需要24位 32 | 每个像素占用3个字节 33 | R:0-255 34 | G:同上 35 | B:同上 36 | 37 | 2. png 较高的质量保存图片 38 | - 图片压缩算法。把相似的颜色压缩在一起。 39 | 3. jpg 良好的质量保存 40 | - 图形压缩算法。把相似的颜色给合并在一起,用同一种颜色代替。 41 | 42 | ###02 加载大图片的OOM异常 43 | Out of memory on a 30720012-byte allocation. 29M 44 | 45 | ###03 缩放图片并加载到内存中 46 | 47 | 1. 拿到图片宽高 48 | 2. 拿到手机屏幕的宽高 49 | 3. 得到合适的比例值 50 | 4. 缩放图片显示在手机上 51 | 52 | ###04 在内存中创建原图的副本(重点) 53 | - 原因:要给图片加特效,Android不允许直接操作原图,只能操作原图的副本 54 | - 创建步骤: 55 | 56 | 1. 拿到原图 57 | 2. 创建和原图一样样的空白纸张 58 | 3. 把空白的纸张铺在画板上 59 | 4. 创建画笔 60 | 5. 开始画画 61 | 62 | ###05 图形处理的API(重点) 63 | 64 | 1.缩放 65 | 2.平移 66 | 3.旋转 67 | 4.镜面 68 | 5.倒影 69 | 70 | ###06 画画板 71 | 获取手指触摸手机屏幕的XY坐标,然后用线连接起来 72 | 73 | ###07 撕衣服 74 | 75 | 原理:在界面上放两张图片,没有穿衣服的图片显示在下面,穿衣服的图片是显示在上面. 76 | 手指在屏幕滑动的过程中,把手所到之处的像素点改变成透明色. 77 | 78 | 79 | 80 | #音频 81 | ----- 82 | ###08 音乐播放器API 83 | MediaPlayer 84 | 85 | ###09影音播放器的生命周期函数 86 | 87 | 状态: 88 | 89 | 1.空闲:reset() 重新设置,new MediaPlayer() 90 | 2.初始化:setDataSource()设置播放的数据资源 91 | 3.准备:prepare(),prepareAsync()准备方法 92 | 4.播放:start()播放 93 | 5.播放完成:一直播放 94 | 6.停止:stop()停止 95 | 7.暂停:pause()暂停 96 | 8.结束:release()释放 97 | 9.错误:程序抛出异常 98 | 99 | 100 | 101 | #视频 102 | ----- 103 | ###10 视频播放器videoview 104 | 105 | 106 | 107 | #照相机 108 | ----- 109 | ###11 照相机拍照(重点) 110 | 采用隐式意图打开系统相机应用程序的拍照界面 111 | 112 | ###12 录像机应用 113 | 采用隐式意图打开系统相机应用程序的录像界面 114 | -------------------------------------------------------------------------------- /第四天_网络编程.md: -------------------------------------------------------------------------------- 1 | 2 | #通过网络从服务器获取数据 3 | 4 | #网络通信 5 | ----- 6 | ###01 网络图片查看器(重点) 7 | 1. 创建Url对象 8 | 2. 用Url对象打开连接 9 | 3. 设置请求参数,设置请求方式 10 | 4. 拿到返回状态 返回码:200成功 3xx重定向 4xx资源错误 5xx服务器错误 11 | 5. 从连接中获取服务端返回的二进制输入流 12 | 6. 在清单文件中添加访问互联网的权限 13 | 14 | 15 | ###02 为什么子线程不能修改UI界面? 16 | 17 | - NetworkOnMainThreadException:网络在主线程上的异常; 18 | 19 | 从Android4.0开始,google为让UI界面运行的更加流程,要求在主线程中不能有访问网络的操作,这样就防止UI界面卡死的现象。 20 | 所以通过子线程来访问网络,但子线程不能直接修改UI界面,要通过handler传送消息,请求主线程修改。 21 | 22 | - android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 23 | 24 | 从错误线程调用的异常 25 | 只有主线程才能修改UI 26 | 27 | - ANR applicationg not response 应用程序无响应 28 | 29 | ###03 消息处理机制的原理(重点) 30 | - 原理:如图 31 | 32 | - 使用handler的步骤: 33 | 34 | 1. 在主线程中初始化Handler 35 | 2. 在子线程中用handler发送消息 36 | 3. android系统处理消息 37 | 4. 在Handler的handlemessage()方法中处理消息 38 | 39 | - Handler的工作原理(handler,message,looper三者之间的关系): 40 | 41 | 在子线程中给主线程发送消息,在Handler的handlmessage()方法中处理消息 42 | 43 | ###04 网络源码查看器 44 | - 网络请求 45 | - Handler消息机制 46 | 47 | ###05 消息处理常用的另一个API 48 | 这个方法是运行在ui线程 49 | runOnUiThread(new Runnable() { 50 | @Override 51 | public void run() { 52 | // 修改UI界面 53 | textView.setText("更改UI"); 54 | } 55 | }); 56 | 57 | 58 | 59 | #阶段总结 60 | ----- 61 | ###06 新闻客户端 62 | 1. 从服务器获取xml数据 63 | 64 | 1. 创建Url对象,用Url对象打开连接 65 | 2. 设置请求参数 66 | 3. 拿到返回状态 返回码:200成功 3xx重定向 4xx资源错误 5xx服务器错误 67 | 4. 从连接中获取流 68 | 2. 解析XML文件 69 | 70 | 1. 初始化xml解析器 71 | 2. 设置参数和输入流 72 | 3. 解析xml文件数据 73 | 数据写完了,单元测试一下xml文件的解析 74 | 3. 把List集合中的数据显示在ListView上 75 | 76 | ListView的编写步骤 77 | 设置数据适配器adapter 78 | 1. 在主线程中初始化Handler 79 | 2. 在子线程中用handler发送消息 80 | 3. android系统处理消息 81 | 4. 在Handler的handlmessage()方法中处理消息 82 | 83 | 4. 显示图片 84 | 85 | 自定义imageView的步骤 86 | 1. 写个SmartImageView继承ImageView,开发网络加载图片的方法 87 | 2. 在xml布局中 包名+SmartImageView 88 | 3. 在getView方法中调用SmartImageView.setImageUrl()方法 89 | 90 | 91 | 92 | #使用开源框架 93 | ----- 94 | ###07 使用SmartImageView显示新闻图片(重点) 95 | 1. www.github.com 下载开源框架 96 | 2. 阅读开源框架的介绍 readme.md 或者sample示例代码 97 | 3. 复制代码到我们的工程中 98 | 4. 在item.xml中使用smartimageview替换imageview,在代码中使用smartimageview替换 imageview,调用setImageUrl(); 99 | 100 | -------------------------------------------------------------------------------- /第十一天_新特性、样式与主题.md: -------------------------------------------------------------------------------- 1 | ##新特性、样式与主题 2 | 3 | 4 | #Fragment新特性(重点) 5 | --- 6 | ###01 Fragment入门 7 | Android3.0以后添加的功能,在同一Activity切换多个的布局文件。 8 | 9 | 编写步骤: 10 | 11 | // 1. 初始化Fragment实例对象 12 | Fragment01 f1 = new Fragment01(); 13 | // 2. 拿到Fragment管理器 14 | FragmentManager fm = getFragmentManager(); 15 | // 3. 获取Fragment的事务 16 | FragmentTransaction ft = fm.beginTransaction(); 17 | // 4. 设置Fragment 18 | ft.replace(R.id.fl_content, f1); 19 | // 5. 提交 20 | ft.commit(); 21 | 22 | ###02 Fragment向下兼容 23 | 全部用android-support-v4.jar里的类 24 | 25 | ###03 Fragment和Activity之间传递数据 26 | 1.在activity中给fragment: 27 | 把fragment作为一个普通的对象,调用它的方法接收参数; 28 | 29 | 2.在fragment中给activity传数据: 30 | 把activity作为一个普通的对象,调用它的方法接收参数; 31 | 32 | ###04 Fragment的生命周期 33 | 比Activity多:onAttach()onCrateView()onActivityCrated() 34 | onDestroyView()onDetach() 35 | 36 | 37 | 开发中常用:onCrateView()onDestroy() 38 | 39 | #属性动画 40 | --- 41 | ###05 为什么使用属性动画 42 | - 动画:从开始状态到结束状态的过渡效果 43 | - 补间动画:只有一个动画效果,并没有改变控件的x,y 坐标 44 | - 属性动画:既有动画效果,又可以改变控件的x,y坐标 45 | 46 | ###06 四种种常见属性动画 47 | 1. 平移: 48 | 49 | ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "translationX", 0, 100); 50 | oa.setDuration(2000); 51 | oa.setRepeatCount(2); 52 | oa.setRepeatMode(ObjectAnimator.REVERSE); 53 | oa.start(); 54 | 2. 透明: 55 | 56 | ObjectAnimator oa2 = ObjectAnimator.ofFloat(iv, "alpha", 1, 0.5f, 0); 57 | oa2.setDuration(2000); 58 | oa2.setRepeatCount(1); 59 | oa2.setRepeatMode(ObjectAnimator.REVERSE); 60 | oa2.start(); 61 | 62 | 3. 缩放 63 | 64 | ObjectAnimator oa3 = ObjectAnimator.ofFloat(iv, "scaleX", 1, 0.5f, 0.2f); 65 | oa3.setDuration(2000); 66 | oa3.setRepeatMode(ObjectAnimator.REVERSE); 67 | oa3.start(); 68 | 4. 旋转 69 | 70 | ObjectAnimator oa4 = ObjectAnimator.ofFloat(iv, "rotationY", 0,20,45,360); 71 | oa4.setDuration(2000); 72 | oa4.setRepeatMode(ObjectAnimator.REVERSE); 73 | oa4.start(); 74 | 75 | 一起飞: 76 | 77 | //创建一个动画师集合 78 | AnimatorSet as = new AnimatorSet(); 79 | //一个一个装逼一个一个飞 80 | //as.playSequentially(oa1, oa2, oa3, oa5); 81 | //一起装逼一起飞 82 | as.playTogether(oa1, oa2, oa3, oa5); 83 | //设置播放动画的对象 84 | as.setTarget(iv); 85 | as.start(); 86 | 87 | 88 | #样式与主题 89 | --- 90 | ###07 样式(重点) 91 | 主要作用于控件上,修饰控件的一些属性 92 | 93 | ###08 主题 94 | 95 | 界面或者整个应用程序的风格 96 | 97 | 定义主题的方法与定义样式完全一样 98 | 99 | 100 | 101 | #Android基础知识点复习 102 | 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /第五天_网络编程.md: -------------------------------------------------------------------------------- 1 | ##通过网络提交数据到服务器 2 | 使用get和post向服务器提交数据、多线程断点下载 3 | 4 | 5 | #使用get和post向服务器提交数据 6 | ----- 7 | 8 | ##http的get和post协议 9 | ###01 使用GET方式向服务器端提交数据 10 | 11 | 组拼url的路径,把提交的数据拼装url的后面,提交给服务器。 12 | 13 | 缺点: 1. 安全性 2. 长度有限制不能超过4K 14 | 优点: 代码写起来很简单 15 | 16 | ###02 使用POST方式向服务器端提交数据 17 | 18 | 数据是以流的方式写给服务器 19 | 20 | 优点:1.安全 2. 长度没有限制 21 | 缺点:代码编写麻烦 22 | 23 | 和GET方式的不同: 24 | 1. 调用的url地址不一样:使用post方式没有把参数组拼到url地址的后面; 25 | String path = "http://192.168.1.100:8080/web/servlet/ 26 | 2. 请求方式不同:POST; 27 | conn.setRequestMethod("POST"); 28 | 3. 设置的请求参数不同,多了两个参数:Content-Type: application/x-www-form- urlencoded,Content-Length: 25; 29 | conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 30 | conn.setRequestProperty("Content-Length", data.length()+""); 31 | 4. 使用二进制输出流把提交的参数写到服务器端; 32 | 设置是否允许向服务器端写数据 33 | conn.setDoOutput(true); 34 | 使用二进制输出流把数据写到服务器端; 35 | conn.getOutputStream().write(data.getBytes()); 36 | 37 | ###03 post&get方式提交数据的中文乱码解决 38 | 39 | - 产生乱码的原因:客户端和服务端两边的码表不一样 40 | 41 | - 解决方案:客户端和服务端两边采用相同的码表,项目中都是用UTF-8的编码 42 | 43 | - 常见中文乱码:菱形有问号 gbk的中文数据用utf-8显示。 44 | 45 | - 常见乱码问题: 46 | 47 | Android客户端默认使用的字符集编码为UTF-8 48 | 1. 服务器端返回的中文数据是乱码: 49 | 保持服务器端和客户端使用的字符集编码一致; 50 | 2. 客户端提交给服务器端的中文数据时乱码: 51 | 保持服务器端和客户端使用的字符集编码一致; 52 | URLEncoder.encode(qq,"UTF-8") 53 | 54 | 55 | ##开源框架HttpClient 56 | ###04 使用HttpClient向服务器端提交数据(重点) 57 | 58 | - HttpClient 开源的,轻量级的浏览器,代码模拟浏览器的行为; 59 | google已经把httpclient的api已经集成到了Android里了.不需要自己单独下载了; 60 | 61 | - 使用步骤: 62 | 63 | 1.创建一个浏览器对象; 64 | 2.输入网址; 65 | 3.敲回车; 66 | 67 | 68 | ##开源框架Asynchttpclient 69 | ###05 使用开源项目Asynchttpclient的GET和POST访问网络(重点) 70 | 71 | - Asynchttpclient内部使用线程池访问网络, 72 | 不需要考虑主线程子线程的问题 73 | - 自动进行了UTF-8的编码了 74 | - 使用handler处理消息了 75 | 76 | ###06 上传文件 77 | 78 | 可以向服务器提交任意类型的文件数据 79 | 80 | 81 | 82 | #多线程断点下载 83 | ----- 84 | ###07 多线程加速下载的原理 85 | 1. 为什么需要多线程下载? 86 | 为了提高从服务器下载资源速度 87 | 88 | 2. 下载速度的限制条件? 89 | 网络带宽 90 | 91 | ###08 多线程下载的原理 92 | 如图 93 | 94 | ###09 断点下载的原理 95 | 96 | 在下载的过程中实时记录下载到的位置,下次下载时接着上一次的位置下载; 97 | 98 | ###10 多线程下载的Android移植 99 | 1. android程序和java程序运行环境的区别 100 | - 写UI,动态添加progressBar 101 | - 添加网络权限和SD的读写权限 102 | 103 | 2. 复制代码修改错误 104 | - 去掉static修饰符 105 | - 修改存储文件的路径为SD卡 106 | 107 | 3. 设置progressBar的进度 108 | 109 | 4. 测试 110 | 111 | ###11 使用开源实现多线程下载(重点) 112 | - Xutils 113 | - Afinal 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /第二天_数据存储和读取.md: -------------------------------------------------------------------------------- 1 | ##Android中的数据存储和读取 2 | 存储数据到文件中、从文件中读取数据显示在界面上 3 | 4 | #测试 5 | ----- 6 | ###1 软件测试的概念 7 | 1. 按照是否知道源代码 8 | - 白盒测试:知道源代码,写代码去测试逻辑 9 | - 黑盒测试:不知源代码,根据需求测试软件的功能 10 | 11 | 2. 按照测试的粒度 12 | - 方法测试:测试某个方法 13 | - 单元测试:测试一个代码块 14 | - 功能测试:根据需求测试软件的某个功能 15 | 16 | 3. 按照测试的暴力程度 17 | - 压力测试 18 | - 冒烟测试:monkey 19 | 20 | ###2 Android下编写单元测试代码的步骤 21 | 1. 测试类 extends AndroidTestCase 22 | 23 | 2. 测试方法 24 | * 必须是public 25 | * 给android测试框架抛出异常 26 | 27 | 3. 要对测试方法断言 28 | 29 | 4. 在manifest节点写: 30 | 31 | 34 | 35 | 在application节点写: 36 | 37 | 38 | 39 | 5. 右键部署程序运行单元测试 40 | - 绿条代表通过 41 | - 红条代表失败,方法有问题 42 | 43 | 44 | Android中查看日志 45 | ----- 46 | ###3 日志等级的划分 47 | 分为5个等级: 48 | 49 | V: verbose 提醒 黑色 Log.v(); 50 | D: debug 调试 蓝色 Log.d(); 51 | I: info 信息 绿色 Log.i(); 52 | W: warn 警告 橘黄 Log.w(); 53 | E: error 错误 红色 Log.e(); 54 | 55 | ###4 什么是上下文 Context 56 | 全局的环境对象,方便的api,可以去获取整个应用程序的数据 57 | 58 | 59 | #Android中文件存储数据 60 | ----- 61 | RAM:运行内存,相当于电脑的内存 62 | 63 | ROM:内部存储,相当于电脑的硬盘,可以持久化存储数据 64 | 65 | SD卡:外部存储 66 | 67 | ##5 内部存储(重要) 68 | 文件存储路径: /data/data/包名 69 | 70 | 文件只能存储在自己应用程序私有的文件夹下,别的应用程序无法访问 71 | 72 | 1. this.getFilesDir() == /data/data/包名/files/ 73 | 74 | 清除数据,弹出对话框提示,会清除所有的数据 75 | 76 | 2. this.getCacheDir() == /data/data/包名/cache/ 77 | 78 | 清除缓存,没有对话框提示,只清除cache目录里面的数据,当系统内存严重不足时,系统会自动清除cache目录里面的文件 79 | 应用场景:存储临时的文件 80 | 81 | 3. 输入流 this.openFileInput("config.txt"); 82 | 83 | 4. 输出流 this.openFileOutput("config.txt", 0); 84 | 85 | ##6 外部存储SD卡(重要) 86 | 记得添加权限,检查外部存储设备的状态和可用空间 87 | 88 | ###7 SD卡的路径、状态、可用空间大小 89 | - SD卡的路径: 90 | Environment.getExternalStorageDirectory() 91 | 92 | - SD卡的状态: 93 | Environment.getExternalStorageState() 94 | 95 | - SD卡的可用空间 96 | 97 | File file = Environment.getExternalStorageDirectory(); 98 | long size = file.getFreeSpace();//byte 99 | String num = Formatter.formatFileSize(this, size); 100 | 101 | ##8 SharedPreference存储数据(重要) 102 | 文件存储路径: /data/data/包名/shared_prefs/ 103 | 104 | 1. 初始化 SharedPreferences 105 | mPreferences = this.getSharedPreferences("info", 0); 106 | 107 | 2. 拿到 Editor编辑器 108 | Editor editor = mPreferences.edit(); 109 | 110 | 3. 存储数据 111 | editor.putString("qq", qq); 112 | 113 | 4. 提交,重要 114 | editor.commit(); 115 | 116 | 应用场景:存储配置信息,账号密码 117 | 118 | ##9 Android下文件访问的权限 119 | 原理:底层是通过Linux操作系统的文件模式来实现的。 120 | 121 | 默认情况下,所有的文件创建出来都是私有的。只有自己的应用程序可以访问里面的数据,别的应用程序是不可以访问数据的。 122 | 123 | 124 | 125 | #Xml文件生成和解析 126 | ----- 127 | ###10 为什么要用xml文件 128 | - 用元素描述数据 129 | - 跨平台 130 | 131 | ###11 生成xml文件的步骤(重要) 132 | 1. 初始化xml序列器 133 | 134 | XmlSerializer serializer = Xml.newSerializer(); 135 | 136 | 2. 设置参数 137 | 138 | FileOutputStream os = this.openFileOutput("student.xml", 0) 139 | serializer.setOutput(os, "utf-8"); 140 | 141 | 3. 往xml文件里面写数据 142 | 143 | serializer.startDocument("utf-8", true); 144 | 145 | ###12 解析xml文件的方式 146 | 1. sax 基于事件 147 | 2. dom&dom4j 把xml加载到内存 148 | 3. pull解析(类似于sax但是效率更高,内存开销更小) 149 | 150 | 151 | ###13 解析xml文件(重要) 152 | 1. 初始化xml解析器 153 | XmlPullParser parser = Xml.newPullParser(); 154 | 2. 设置解析器的参数 输入流 155 | parser.setInput(is, "utf-8"); 156 | 3. 解析数据 157 | 158 | -------------------------------------------------------------------------------- /第八天_服务.md: -------------------------------------------------------------------------------- 1 | #服务 2 | 3 | ##01 start开启服务的生命周期(重点) 4 | 5 | - 生命周期方法:oncreate() -->onstartCommand()--->onstartCommand()--->onDestory() 6 | 7 | 1.onCreate:在服务对象创建后调用这个方法,初始化服务对象 8 | 2.onStartCommand:开启服务后调用这个方法 9 | 3.onDestroy:在服务对象被销毁之前调用这个方法,通常在这个方法中做一些扫尾工作,比如保存数据 10 | 11 | - 特点: 12 | 13 | 1.第一次开启服务时,先创建服务对象,然后再开启 14 | 调用的方法:onCreate,onStartCommand 15 | 2.停止服务调用方法:onDestroy() 16 | 3.服务可以被多次开启,每次开启时只调用onStartCommand方法 17 | 4.服务只能被停止一次,如果多次停止不会调用任何方法 18 | 5.没有界面,可以长期运行在后台(即使界面关闭掉了) 19 | 20 | ##02 bind开启服务的生命周期(重点) 21 | - 生命周期方法: onCreate()-->onBind()-->onUnbind()-->onDestroy() 22 | 23 | 1.onCreate:在服务对象创建后调用这个方法,初始化服务对象 24 | 2.onBind()绑定服务 25 | 3.onUnbind()解除绑定的服务 26 | 4.onDestroy:在服务对象被销毁之前调用这个方法,通常在这个方法中做一些扫尾工作,比如保存数据 27 | - 特点: 28 | 29 | 1.第一次绑定服务时,先创建服务对象,再绑定 30 | 调用的方法onCreate,onBind 31 | 2.解除绑定服务后服务就会停止 32 | 3.服务只能被绑定一次 33 | 4.服务只能被解除一次,多次解除会抛出异常 34 | 35 | - 小细节: 36 | 37 | 1.如果onbind方法返回值是null,onServiceConnected方法就不会被调用 38 | 2.绑定的服务在系统设置界面,正在运行条目是看不到的 39 | 3.用的是什么conn绑定的,就必须用哪个conn去解绑 40 | 4.绑定的服务,不求同时生,但求同时死。 如果调用者Activity退出了,服务就自动跟着退出 41 | 42 | 43 | ##03 绑定服务调用服务里的方法 44 | 45 | 服务被绑定成功时,返回服务代理人;服务被连接成功时,拿到服务代理人 46 | 47 | 1. 在Activity里绑定服务bindService() 48 | 49 | bindService(intent, new MyConn(), BIND_AUTO_CREATE) 50 | intent: 意图对象,服务对应的意图对象 new Intnet(this,Service.class) 51 | ServiceConnection: 通讯频道,利用他可以获取到服务成功绑定后得到的代理人 52 | BIND_AUTO_CREATE:常量,服务不存在会自动创建 53 | 54 | 2. 如果服务被成功绑定,会执行 onBind的方法,让返回服务的代理人对象(IBinder类型) 55 | 返回值 IBinder 就是服务内部的小蜜 56 | 57 | 3. 扩展实现服务内部的代理人,可以间接的调用服务的方法 58 | 59 | public void callMethodInService(int money){ 60 | if(money>500){ 61 | methodInService(); 62 | }else{ 63 | Toast.makeText(DemoService.this, "这点钱还想办事呀?", 0).show(); 64 | } 65 | } 66 | 4. 采用内部类的方式得到服务连接的通道 67 | 68 | private class MyConn implements ServiceConnection{ 69 | //当服务被成功连接的时候调用的方法 70 | @Override 71 | public void onServiceConnected(ComponentName name, IBinder service) { 72 | 重要的参数IBinder ,代表的就是中间人,服务的小蜜 73 | } 74 | //当服务失去连接的时候调用的方法 75 | @Override 76 | public void onServiceDisconnected(ComponentName name) { 77 | } 78 | } 79 | 5. 在MyConn成功连接后,就得到了 IBInder对象即MyBinder 80 | 81 | 6. 利用MyBinder代理人间接调用服务的方法 82 | 83 | ##04 绑定服务抽取接口(重点) 84 | 85 | 接口: 可以隐藏代码内部的细节,只暴露程序员想暴露的方法 86 | 87 | 1. 在工程中添加一个接口IService,在里面写一个方法callMethodInService() 88 | 89 | 2. 让服务的代理人实现IService接口,实现接口的方法,在这个方法中调用服务的业务方法 90 | 91 | 3. 服务被绑成功时,返回服务的代理人对象(IBinder类型) 92 | 93 | 4. 服务连接成功时,拿到代理人IBinder,将其强转成IService类型 94 | 95 | 5. 在activity中,通过调用代理人IService接口暴露出来的方法,间接调用服务里的业务方法 96 | 97 | ##05 混合方式开启服务,服务的生命周期 98 | 99 | 1. 为什么需要采用混合的方式开启服务? 100 | 101 | - startService 服务长期后台运行,不可以调用服务里面的方法 102 | 103 | - bindService 可以调用服务的方法,但是不能长期后台运行 104 | 105 | - 采用混合的方式开启服务: 106 | 即想服务长期在后台运行,又可以调服务里的方法 107 | 108 | 2. 特点: 109 | 110 | 1. 如果服务被绑定了,只有解除绑定才能停止服务 111 | 2. 如果服务被采用start的方式开启过,只有stopService()才能停止服务 112 | 113 | 3. 推荐使用的步骤: 114 | 115 | 1. startService(): 为了保证让服务长期运行在后台; 116 | 2. bindService(): 绑定服务,调用服务中业务方法; 117 | 3. unBindService(): 解除绑定,不再调用服务中业务方法; 118 | 4. stopService(): 停止服务 119 | 120 | ##06 服务的应用场景 121 | 122 | 应用场景:需要写一些代码运行在后台,执行一些任务. 123 | 124 | ##07 IPC进程间通信 125 | - inter process communication 进程间通信 126 | - aidl : android interface defination language安卓接口定义语言 127 | 满足两个进程之间接口数据的交换(ipc) 128 | 129 | 130 | ##08 本地服务和远程服务 131 | * 本地服务: 服务的代码在自己应用程序工程的内部 132 | 133 | * 远程服务: 同一个设备上的另一个软件中的服务组件 134 | 135 | - 通过aidl接口暴露远程服务中的方法,任何应用程序都可以调用远程服务中的业务方法 136 | 137 | ##09 本地应用调用远程服务中方法 aidl的写法(重点) 138 | 139 | 通过aidl接口把远程服务中的业务方法暴露出去 140 | 141 | 1. 创建一个远程服务的工程,写一个服务的组件,在服务中写一个业务方法 142 | 143 | 1. 在远程服务中把IService.java改成IService.aidl 144 | 把文件中public修饰符删除了 145 | 在工程目录gen目录下会自动编译成IService.java的接口文件。 146 | 147 | 2. 在远程服务中让代理人继承IService.Stub,Stub是远程服务的代理对象 148 | 149 | 2. 创建本地应用,调用远程服务中方法: 150 | 151 | 3. 在本地应用中创建一个包,包名必须与远程服务中IService.aidl文件所在包名相同 152 | 4. 把远程服务中IService.aidl文件拷贝到本地应用的这个包下面 153 | 5. 在本地应用连接服务成功时,得到服务返回的代理人对象 154 | mBinder = IService.Stub.asInterface(service) 155 | 6. 通过远程服务代理人对象间接调用远程服务中的业务方法 156 | 157 | ##10 远程服务的使用场景 158 | 1. 超级大公司,写出来逻辑供别的程序员使用 159 | 2. 手机企业,手机定制厂商,提供一些方便的逻辑供程序员使用。snoy手机,人脸识别 160 | 3. 系统源码,内置很多的服务。电话服务TelephoneyManager LayoutInflaterService 161 | -------------------------------------------------------------------------------- /第一天_Android入门.md: -------------------------------------------------------------------------------- 1 | 2 | ##Android入门 3 | 搭建Android开发环境、Android应用开发的步骤 4 | 5 | #什么是Android 6 | ----- 7 | ###1 Android历史&版本 8 | 9 | Android2.3.3 安卓2.0后最稳定的版本 API:10 10 | Android3.0 增加了新特性,针对平板电脑的系统 11 | Android 4.1.2 安卓4.0后最稳定的版本 API:16 12 | 13 | ###2 Android系统四层架构 14 | 15 | 1. 应用程序层:安装在手上的软件都属于这一层 16 | 17 | 2. 程序框架层:开发程序调用的API都在这一层 18 | 19 | 3. 基础类库层:第三方开源的框架,dvm 20 | 21 | 4. linux kernel:各种驱动 22 | 23 | 24 | #搭建Android开发环境 25 | ----- 26 | ###3 搭建Android开发环境 27 | 28 | 1. Eclipse+ADT 29 | - ADT Android Developer Tools 安卓开发工具,Eclipse的插件 30 | - v21.xxx 最新的23.xxx 31 | 32 | 2. Android Studio 33 | - 对硬件要求高 34 | 35 | ###4 SDK的目录结构 36 | Standard Developer Kits 标准的开发工具包 37 | 38 | * add-ons 39 | >附加组件,放在一个额外的工具。google api,提供google地图的jar包 40 | * build-tools 41 | >编译工具,谷歌sdk升级后采用的目录 42 | * docs 43 | >文档目录。开发文档。(了解) 44 | * extras 45 | >附加工具 support 文件夹,提供向下兼容的jar包。 46 | >和额外的驱动,摄像头驱动,手机驱动 47 | * platform 48 | >开发平台(了解) 49 | * platform tools 50 | >开发的工具 51 | * sample 52 | >实例代码(了解) 53 | * source 54 | >源代码 (了解) 55 | * system-image 56 | >系统镜像 57 | * tools 58 | >开发工具(了解) 59 | 60 | ###5 模拟器 61 | Android Virtual Device 模拟器 62 | 63 | 手机屏幕分辨率: 64 | VGA   640*480 (Video Graphics Array) 65 | QVGA  320*240 (Quarter VGA) 66 | HVGA  480*320 (Half-size VGA) 67 | SVGA  800*600 (Super VGA) 68 | WVGA  800*480 (Wide VGA) 69 | FWVGA 854*480 (Full Wide VGA) 70 | 71 | ###6 Android工程的目录结构 72 | * src 73 | > 源代码 74 | * gen 75 | > 工具自动生成的代码 76 | >BUildconfig 调试的开关 默认开启 77 | >R.java 很多的静态的内部类 78 | * android.jar 79 | >开发用的jar包 80 | * android dependence 81 | > 依赖,向下兼容的依赖jar包 82 | * assets 83 | >资产目录 存放一些别的类型的文件 84 | * bin 85 | >eclipse工具编译的文件夹 86 | * libs 87 | >应用程序开发用的jar包 88 | * res 89 | >应用程序的资源 90 | * androidmanifest.xml 91 | > 清单文件 92 | 93 | ###7 Eclipse打包安装应用的过程 94 | 1. 生成apk文件. 95 | 96 | 1.1 把classes中的字节码文件打包通过命令dx.bat打包成一个classes.dex. 97 | 1.2 resources.arsc文件的生成. 98 | 1.3 未编译的资源文件. 99 | 1.4 把清单文件AndroidManifest.xml文件转换成二进制文件. 100 | 1.5 把以上生成的文件打包成一个压缩包(.apk) 101 | 102 | 2. 把apk文件上传到手机上 103 | 104 | 3. 安装apk应用程序 105 | - 创建一个文件夹/data/data/包名, 用于存放当前应用程序数据. 106 | 107 | ###8 常见的adb指令 108 | Android Debug Bridge 安卓调试桥 109 | 连接模拟器和Eclipse的工具 110 | 111 | * adb devices 112 | > 查看设备 113 | 114 | * adb install 115 | > 安装一个apk -r 覆盖安装 116 | 117 | * adb uninstall <包名> 118 | > 卸载一个apk,包名是应用程序的唯一标示,一个手机里面不可能有两个应用程序包名相同。 119 | 120 | * adb shell 121 | 122 | #Android应用程序开发 123 | ----- 124 | ###9 Android应用程序开发的步骤(重要) 125 | 1. 产品经理给需求 126 | 2. UI给切图,UI设计图 127 | 3. 开发,写代码 128 | 129 | 1.在xml里面写UI布局 130 | 2.在activity中写代码,打架子 131 | 3.写具体的业务 132 | 4. 测试 133 | 134 | ###10 点击事件的四种写法(重要) 135 | 1. 匿名内部类的方式 136 | 137 | btn.setOnClickListener(new OnClickListener() { 138 | 139 | @Override 140 | public void onClick(View v) { 141 | System.out.println("你点击了按钮!!!"); 142 | 143 | } 144 | }); 145 | 146 | 简单点击事件的实现 一般都用匿名内部类 147 | 148 | 2. 内部类的方式 149 | 150 | btn.setOnClickListener(new MyOnClickListener()); 151 | 152 | private class MyOnClickListener implements OnClickListener{ 153 | public void onClick(View v) { 154 | System.out.println("内部类的方式,点击按钮"); 155 | } 156 | } 157 | 3. 当前的activity implements OnClickListener{} 158 | 159 | btn1.setOnClickListener(this); 160 | public void onClick(View v) { 161 | System.out.println("你点击按钮!!!"); 162 | int id = v.getId(); 163 | switch (id) { 164 | case R.id.button1: //按钮1 165 | System.out.println("你点击了按钮1"); 166 | break; 167 | case R.id.button2: //按钮2 168 | System.out.println("你点击了按钮2"); 169 | break; 170 | default: 171 | break; 172 | } 173 | } 174 | 应用场景:界面上按钮比较多的时候,代码的可读性高 175 | 176 | 4. onClick属性 177 | 178 | public void click(View view){ 179 | System.out.println("4. 点击按钮"); 180 | } 181 | 182 | 应用场景:上课采用这种方式,开发中不建议使用 183 | 184 | ###11 五中常见ui布局(重要) 185 | 1. 线性布局 LinearLayout 186 | 187 | 重要属性 android:orientation="horizontal" 水平排列 188 | android:orientation="vertical" 垂直排列 189 | android:layout_width="0dip" 190 | android:layout_weight="1" 权重 191 | 2. 相对布局 RelativeLayout 192 | 193 | 原理:向前看,相对于某个控件的位置 194 | 3. 绝对布局 AbsoluteLayout 195 | 196 | 过时了,不推荐使用 197 | 应用:机顶盒开发常见 198 | 4. 表格布局 TableLayout 199 | 200 | 应用:办公类的软件 201 | 5. 帧布局 FrameLayout 202 | 203 | 一个控件浮在另一个控件的上方 204 | 205 | 206 | -------------------------------------------------------------------------------- /第九天_内容提供者.md: -------------------------------------------------------------------------------- 1 | 2 | #内容提供者 3 | 4 | 5 | ##01 为什么需要内容提供者? 6 | 7 | 把应用程序私有的数据暴露给别的应用程序,让别的应用程序可以对自己私有的数据库实现增删改查。 8 | 9 | ##02 内容提供者编写步骤: 10 | 11 | 1. 写一个类继承了ContentProvider 12 | 13 | 2. 在清单文件中配置内容提供者,添加了provider节点,设置了android:authorities="cn.itcast.bankdb" 14 | authorities是内容提供者的主机名,就相当于一个网站的域名或者ip,可以根据这uri找到内容提供者; 15 | 16 | 3. 在内容提供者中添加匹配器 UriMatcher 17 | 18 | 4. 根据需求实现内容提供者的增删改查的方法 19 | 20 | ##03 调用另一个工程中内容提供者的步骤: 21 | 22 | 1. 得到系统提供的内容提供者解析器: 23 | ContentResolver resolver = this.getContentResolver(); 24 | 25 | 2. 指定内容提供者的uri: 26 | 27 | 3. 通过解析器调用内容提供者的方法;解析器中的增删改查的方法是与内容提供者中的增删改查方法--对应的: 28 | 29 | ##04 内容提供者增删改查的实现 30 | 31 | - 在内容提供者实例对象创建后调用这个方法初始化实例对象:得到数据库的实例对象 32 | 33 | // 创建或者打开一个数据库实例对象 34 | public boolean onCreate() { 35 | return false; 36 | } 37 | 38 | - 增 39 | 40 | // 调用数据库的插入记录的方法,插入一条记录 41 | public Cursor query(Uri uri, String[] columns, String selection, 42 | String[] selectionArgs, String sortOrder) { 43 | int code = mUriMatcher.match(uri); 44 | // 判断用户传递过来的uri是否匹配成功 45 | if (code == ACCOUNT) { 46 | SQLiteDatabase db = helper.getReadableDatabase(); 47 | Cursor cursor = db.query("account", columns, selection, 48 | selectionArgs, null, null, null); 49 | return cursor; 50 | } else { 51 | throw new IllegalArgumentException("根据法律规定,你无权查看数据。"); 52 | } 53 | } 54 | 55 | - 删 56 | 57 | public int delete(Uri uri, String selection, String[] selectionArgs) { 58 | int code = mUriMatcher.match(uri); 59 | if (code == ACCOUNT) { 60 | SQLiteDatabase db = helper.getWritableDatabase(); 61 | int result = db.delete("account", selection, selectionArgs); 62 | db.close(); 63 | return result; 64 | } else { 65 | throw new IllegalArgumentException("根据法律规定,你无权删除数据。"); 66 | } 67 | } 68 | - 改 69 | 70 | public int update(Uri uri, ContentValues values, String selection, 71 | String[] selectionArgs) { 72 | int code = mUriMatcher.match(uri); 73 | if (code == ACCOUNT) { 74 | SQLiteDatabase db = helper.getWritableDatabase(); 75 | int result = db.update("account", values, selection, selectionArgs); 76 | db.close(); 77 | return result; 78 | } else { 79 | throw new IllegalArgumentException("根据法律规定,你无权修改数据。"); 80 | } 81 | } 82 | 83 | - 查 84 | 85 | public Cursor query(Uri uri, String[] projection, String selection, 86 | String[] selectionArgs, String sortOrder) { 87 | int code = mUriMatcher.match(uri); 88 | if (code == ACCOUNT) { 89 | SQLiteDatabase db = helper.getReadableDatabase(); 90 | Cursor cursor = db.query("account", columns, selection, 91 | selectionArgs, null, null, null); 92 | return cursor; 93 | } else { 94 | throw new IllegalArgumentException("根据法律规定,你无权查看数据。"); 95 | } 96 | } 97 | 98 | ##05 学习内容提供者的目的? 99 | 1. 要能看懂内容提供者的源码,别人是怎么通过内容提供者把数据暴露出去的, 100 | 要怎么去调用别人暴露的数据。 101 | 102 | 2. 应用场景:常见的应用-短信、通讯录联系人 103 | 104 | ##06 短信的内容提供者Uri和短信表结构 105 | - 系统短信的内容提供者路径:content://sms/ 106 | 107 | - 分析mmssms.db数据库短信sms表结构: 108 | 列:address 电话号码,date 发送或接收的时间,type 2表示发送,1表示接收,body 短信内容. 109 | 110 | ##07 短信的备份 (重要) 111 | 112 | 1. 通过短信的内容提供者把短信数据查询出来 113 | 2. 把短信以xml文件的格式写到SD卡 114 | 115 | 在清单文件中添加权限: 116 | 117 | 118 | 119 | 120 | 121 | ##08 短信的还原 (重要) 122 | 1. 解析SD卡上xml格式的短信 123 | 2. 通过短信内容提供者向数据库中插入短信记录 124 | 125 | 在清单文件中添加权限: 126 | 127 | 128 | 129 | 130 | ##09 通讯录数据库的表结构 131 | 132 | 1. raw_contacts 联系人表 133 | 保存联系人的id contact_id 134 | 135 | 2. data 数据表 136 | 保存联系人的数据 137 | 138 | 3. mimetypes 139 | MIME数据类型表 140 | 141 | ##10 如何获取系统联系人信息?(重要) 142 | 143 | 1. 查询raw_contacts表中的 _id(联系人的主键) 144 | Uri: content://com.android.contacts/raw_contacts/ 145 | 字段: contact_id 146 | 147 | 2. 根据联系人ID在data表中查询联系人的记录 148 | Uri: content://com.android.contacts/data/ 149 | 字段: mimetype_id,raw_contact_id,data1; 150 | 注意查询的列中,mimetype_id需要改成mimetype; 151 | 152 | 3. 根据mimetype判断当前记录是联系人的姓名,电话,email 153 | 154 | ##11 插入联系人到通讯录 (重要) 155 | 156 | 通过联系人的内容提供者向联系人数据库中插入一个联系人记录 157 | 158 | 1. 先在raw_contacts表创建一个新的id 159 | 2. 在data表里面添加这个id对应的数据,电话、姓名、email等 160 | 161 | ##12 内容观察者 162 | 不属于四大组件,只是内容提供者对应的一个小功能 163 | 164 | 应用场景:用来观察内容提供者数据的变化情况的 165 | 166 | ##13 短信窃听器 167 | 通过内容观察者窃听用户发出短信时,查询短信数据库 168 | -------------------------------------------------------------------------------- /第六天_Activity页面跳转和数据传递_.md: -------------------------------------------------------------------------------- 1 | 2 | #Activity界面跳转、数据传递和生命周期 3 | 4 | #Android中四大组件 5 | - Activity 活动界面 6 | 7 | - BroadcastReceiver 广播接收者 8 | 9 | - Service 服务 10 | 11 | - ContentProvider 内容提供者 12 | 13 | ##01 AndroidManifest清单文件详解 14 | 15 | 1.一个应用程序可以有多个桌面图标 16 | 17 | 2.创建桌面图标的方法如下: 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 3.activity节点中的label标签表示桌面图标的名称 27 | 28 | 4.activity节点中的label标签表示界面的标题或者名称 29 | 30 | 5.application节点中的label标签与activity节点中的label标签不是一个概念,它表示应用程序的名称,可以在应用程序管理列表中看到 31 | 32 | category:BROWSABLE浏览器类型,CAR_MODE 驾驶模式;DEFAULT默认类型,通常自己写的activity都是用这个类型; 33 | 34 | ##02 意图设置动作激活一个新的界面(重点) 35 | 36 | 1. 初始化意图 (做一件事情的目的) 37 | 38 | 2. 设置动作(在清单文件中配置的action) 39 | 40 | intent.setAction("cn.itcast.multiview.SECONDACTIVITY"); 41 | 42 | 3. 设置数据(在清单文件中配置的data) 43 | 44 | intent.setData(Uri.parse("itcast://dfds")); 45 | 46 | 4. 添加类型(在清单文件中配置的category) 47 | 48 | intent.addCategory("android.intent.category.DEFAULT"); 49 | 50 | 5. 打开页面(打开第二个界面) 51 | 52 | startActivity(intent); 53 | 54 | ##03 设计意图的目的? 55 | - 作用:激活组件和传递参数 56 | 57 | - 目的:组件之间解耦 58 | 59 | 解耦:要求写的两个程序之间可以相互独立,又可以相互调用; 60 | 61 | ##04 意图的分类:隐式意图和显式意图(重点) 62 | 1. 隐式意图:在开启目标activity时,系统通过一组动作、数据、类别等属性去清单文件里面匹配,如果匹配到,就打开目标actvity,如果没有匹配到,就抛出异常,没有找个这个activity 63 | 64 | 应用场景:适合开启其他应用程序中的activity 65 | 缺点:速度慢,效率低 66 | 67 | 2. 显式意图:在开启目标activity时,直接指定activity的名称。 68 | 69 | 步骤: 70 | 1. 初始化意图 ,指定要打开activity的名称SecondActivity 71 | Intent intent = new Intent(this, SecondActivity.class); 72 | 2. 打开目标activity 73 | startActivity(intent); 74 | 75 | 应用场景:适合开启本应用程序中的activity; 76 | 优点: 速度快,效率高,代码书写简单 77 | 78 | 79 | ##05 意图传递数据(重点) 80 | 81 | 1. 基本数据类型及其数组 82 | 83 | 2. parcelable:把对象序列化到内存中 84 | 85 | 3. serializable:把对象序列化到文件中 86 | 87 | 4. bundle:类似于map的集合 88 | 89 | 5. intent:意图 90 | 91 | ##06 URI介绍 92 | http://www.baidu.com:80/img/bd_logo1.png 93 | 94 | 组成结构: 95 | 1.schema:简单的理解为是协议名称,如http 96 | 97 | 2.host:主机名,如192.168.1.100或者ip 98 | 99 | 3.port:端口号,如8080 100 | 101 | 4.path:路径,如image文件夹 102 | 103 | 5.数据:数据资源,如1.jpg 104 | 105 | ##07 开启activity获取返回值(重点) 106 | 第一个界面跳转到第二个界面,等待第二个界面关闭时,返回给第一个界面数据 107 | 108 | 1. 采用一种特殊的方式开启Activity 109 | startActivityForResult(intent, 0); 110 | 2. 在开启的第二个Activity里面设置数据 111 | Intent data = new Intent(); 112 | data.putExtra("content", content); 113 | setResult(0, data); 114 | 3. 记得关闭新开启的第二个activity 115 | finish(); 116 | 4. 在第一个Activity里面,重写一个方法,获取返回的数据 117 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 118 | //data就是返回的intent,里面包含有数据 119 | } 120 | 121 | ##08 请求码和结果码的作用(重点) 122 | - 请求码的作用: 123 | 124 | 用来判断当前数据是从哪个界面返回的 125 | 126 | - 结果码的作用: 127 | 128 | 用来判断当前数据是从哪个界面返回的 129 | 130 | ##09 activity的生命周期(重点) 131 | 132 | - 打开一个activity调用的方法:onCreate(),onStart(),onResume() 133 | 134 | - 关闭一个activity调用的方法: onPause(),onStop(),onDestroy() 135 | 136 | - 最小化一个activity调用的方法:onPause(),onStop() 137 | 138 | - 打开一个最小化的activity调用的方法:onRestart(),onStart(),onResume() 139 | 140 | ##10 读文档查看activity的生命周期的分类 141 | 142 | 1. entire lifetime(完整的生命周期方法): 143 | 144 | onCreate(),onStart(),onResume(),onPause(),onStop(),onDestory() 145 | 146 | 2. visible lifetime(可视的生命周期方法): 147 | 148 | onStart(),onResume(),onPause(),onStop() 149 | 150 | 3. foreground lifetime(前台生命周期方法): 151 | 152 | onResume(),onPause() 153 | 154 | ##11 横竖屏切换activity的生命周期 155 | 1. 横竖屏切换生命周期的变化: 156 | 157 | 先关闭前一个界面,再打开一个新的界面 158 | 159 | 3. 固定Activity朝向 160 | 161 | android:screenOrientation="landscape" 162 | portrait:竖向的 landscape:横向的 sensor传感器类型(自适应) 163 | 164 | 3. 当屏幕朝向变化时,使actvity不敏感变化 165 | 166 | android:configChanges="orientation|screenSize|keyboardHidden" 167 | 168 | ##12 任务栈的概念 169 | 170 | - 任务:做的一件事情,activity的实例对象 171 | 172 | - 栈 :后进先出(吃完了吐出来) 队列:先进先出(吃完了拉出来) 173 | 174 | - 任务栈:task stack 记录用户操作的行为,维护一个用户体验。打开关闭的界面 175 | 176 | ##13 Activity的启动模式 177 | 178 | 1. standard:标准默认模式 179 | 180 | 打开应用的时,系统会给它创建一个默认的任务栈。开启新的activity, 181 | 系统会把这个activity压入到任务栈的栈顶,返回退出activity,系统会把activity移除任务栈。 182 | 183 | 应用:绝大多数默认的情况 184 | 185 | 2. singleTop:单一顶部模式 186 | 187 | 打开activity时,系统回去任务栈的顶部查找,如果栈顶是当前activity,系统就不会创建新的activity,而是使用已经打开的activity。 188 | 189 | 应用:浏览器书签,一个界面避免重复开启很多次 190 | 191 | 3. singleTask:单一任务模式 192 | 193 | 打开界面创建实例,系统会去整个任务栈查找,有没有当前的任务?如果没有,则在栈顶创建一个实例任务, 194 | 如果有,则删除当前实例任务上面的所有任务,使其位于栈顶,整个任务栈只有一个实例存在。 195 | 196 | 应用:浏览器 197 | 198 | 4. singleInstance:单一实例模式 199 | 200 | 前面三种都是在应用程序默认的任务栈里面。 201 | 系统会为它单独创建一个任务栈,在单独的任务栈里面运行. 202 | 203 | 应用:电话拨号器的通话界面 204 | 205 | 206 | 207 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /第三天_数据存储和界面展现.md: -------------------------------------------------------------------------------- 1 | 2 | ##数据的存储和界面展现 3 | 数据库、ListView 4 | 5 | 6 | #数据库 7 | ----- 8 | ###1 Android数据存储的方式(重要) 9 | 1. Internal Storage 内部存储 10 | - cache 11 | - files 12 | 2. External Storage 外部存储SD卡 13 | - SD卡 14 | 3. SharedPreference 参数 15 | - 设置信息,配置信息,密码 16 | 17 | 4. SQLite Databases数据库 18 | - 相似结构的数据,大量存储,增删改查。 19 | - Sqlite 20 | 5. Network Connection网络存储 21 | 22 | ###2 Sqlite数据库 23 | - 开源的 24 | - 嵌入式的数据库,轻量级。 25 | - sql语句的增删改查和MySql语句差不多 26 | 27 | ###3 数据库的创建 28 | - java中文件的创建 29 | 30 | 1.在内存中,创建文件对象 31 | File file = new File("haha.txt"); 32 | 2.在硬盘上,创建文件 33 | FileOutputStream fos = new FileOutputStream(file); 34 | fos.write("".getBytes()); 35 | fos.close(); 36 | 37 | - 数据库的创建 38 | 39 | 1.在内存中,创建数据库对象 40 | MyDBOpenHelper helper = new MyDBOpenHelper(this); 41 | 2.在手机里,创建数据库文件 42 | helper.getWritableDatabase(); 43 | 44 | 45 | 数据库的存储路径: /data/data/包名/databases/ 46 | 47 | ###4 数据库的操作 48 | - 增 49 | insert into stu (name,num) values ('zhangsan','1001') 50 | - 删 51 | delete from stu where _id = 1 52 | - 改 53 | update stu set name = 'lisi' where name = 'zhangsan' 54 | - 查 55 | select * from stu where _id = 1 56 | 57 | 优点:多表操作 58 | 缺点:容易出错并且没有返回值 59 | 60 | ###5 Android API对数据库表的增删改查(推荐使用)(重要) 61 | 缺点:单表操作 62 | 优点:不容易出错,有返回值 63 | 64 | - 增 65 | 66 | public void insert(View v) { 67 | // 1. 在内存中创建一个数据库帮助类的对象 68 | MyDbOpenHelper helper = new MyDbOpenHelper(this); 69 | // 2. 在手机上生成数据库文件 70 | SQLiteDatabase db = helper.getWritableDatabase(); 71 | // db.execSQL("insert into stu (name,num) values (?,?)", new Object[] { 72 | // "linqingxia", 28 }); 73 | 74 | ContentValues values = new ContentValues(); 75 | values.put("name", "zhangsan"); 76 | values.put("num", "10086"); 77 | /* 78 | * table :表名 nullColumnHack:默认会添加一个NULL,一般写个null就行了 values 79 | * :ContentValues类似map集合 80 | */ 81 | long res = db.insert("stu", null, values); 82 | if (res != -1) { 83 | Toast.makeText(this, "插入成功 :" + res, 0).show(); 84 | } else { 85 | Toast.makeText(this, "插入失败 :" + res, 0).show(); 86 | } 87 | // 重要,释放资源 88 | db.close(); 89 | } 90 | - 删 91 | 92 | public void delete(View v) { 93 | // 1. 在内存中创建一个数据库帮助类的对象 94 | MyDbOpenHelper helper = new MyDbOpenHelper(this); 95 | // 2. 在手机上生成数据库文件 96 | SQLiteDatabase db = helper.getWritableDatabase(); 97 | // db.execSQL("delete from stu"); 98 | /* 99 | * table :表名 whereClause:where条件 whereArgs:查询参数 100 | */ 101 | int res = db.delete("stu", null, null); 102 | if (res > 0) { 103 | Toast.makeText(this, "succ:"+res, Toast.LENGTH_SHORT).show(); 104 | } else { 105 | Toast.makeText(this, "err", Toast.LENGTH_SHORT).show(); 106 | } 107 | 108 | // 重要,释放资源 109 | db.close(); 110 | } 111 | - 改 112 | 113 | public void update(View v) { 114 | // 1. 在内存中创建一个数据库帮助类的对象 115 | MyDbOpenHelper helper = new MyDbOpenHelper(this); 116 | // 2. 在手机上生成数据库文件 117 | SQLiteDatabase db = helper.getWritableDatabase(); 118 | // db.execSQL("update stu set name=?", new Object[] { "yadan" }); 119 | /* 120 | * table :表名 values :ContentValues类似map集合 whereClause:where条件 121 | * whereArgs:查询参数 122 | */ 123 | ContentValues values = new ContentValues(); 124 | values.put("name", "lisi"); 125 | 126 | int res = db.update("stu", values, null, null); 127 | if (res > 0) { 128 | Toast.makeText(this, "succ:"+res, Toast.LENGTH_SHORT).show(); 129 | } else { 130 | Toast.makeText(this, "err", Toast.LENGTH_SHORT).show(); 131 | } 132 | // 重要,释放资源 133 | db.close(); 134 | } 135 | - 查 136 | 137 | public void query(View v) { 138 | // 1. 在内存中创建一个数据库帮助类的对象 139 | MyDbOpenHelper helper = new MyDbOpenHelper(this); 140 | // 2. 在手机上生成数据库文件 141 | SQLiteDatabase db = helper.getReadableDatabase(); 142 | 143 | Cursor cursor = db.rawQuery("select * from stu", null); 144 | /* 145 | * table :表名 146 | * columns :要查询的列 147 | * selection:查询条件 148 | * selectionArgs:查询参数 149 | * groupBy :分组 150 | * having :条件 151 | * orderBy :排序 152 | * limit :限制条件 153 | * 154 | */ 155 | Cursor cursor = db.query("stu", new String[]{"num","name","_id"}, null, null, null, null, null, null); 156 | while (cursor.moveToNext()) { 157 | int id = cursor.getInt(2); 158 | String name = cursor.getString(1); 159 | String num = cursor.getString(0); 160 | 161 | System.out.println("======"); 162 | System.out.println("id:" + id + " name:" + name + " num:" + num); 163 | } 164 | 165 | // 重要,释放资源 166 | cursor.close(); 167 | db.close(); 168 | } 169 | 170 | 171 | 172 | #ListView 173 | ----- 174 | ###6 ListView 175 | 176 | - 应用场景:用于显示大量结构相似的数据 177 | 178 | - 优化:复用converView 179 | 180 | ###7 Android中常见的默认实现类 181 | * BaseXXX 182 | * BasicXXX 183 | * SimpleXXX 184 | * DefaultXXX 185 | 186 | ###8 ListView的编写步骤(重要) 187 | 1. 在xml布局文件中声明listview的控件 188 | 189 | 193 | 2. 在代码里面查找listview 194 | 195 | findViewById(R.id.lv); 196 | 3. 设置listview的数据适配器 197 | 198 | lv.setAdapter(new MyAdapter()); 199 | 4. 编写数据适配器 200 | 201 | private class MyAdapter extends BaseAdapter{ 202 | public int getCount() { 203 | return ...;//告诉listview里面有多少条数据 204 | } 205 | public View getView(int position, View convertView, ViewGroup parent) { 206 | return ...;//返回每个位置显示的view是什么样子的。 207 | } 208 | } 209 | 210 | 211 | ###9 常见的数据适配器 212 | - ArrayAdapter 数组适配器 213 | -------------------------------------------------------------------------------- /第七天_广播与服务.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | #广播接收者 4 | 1. 什么是广播? 5 | - 电台:对外发送信号。 6 | - 收音机:接收电台的信号。 7 | 8 | 2. 为什么要用广播接收者? 9 | 10 | 在Android操作系统中也有一个类似广播电台的功能,可以把公用的一些事件作为广播消息发送出去.每个应用程序都可以接收这个事件。 11 | 12 | 3. Android系统中常见的广播事件 13 | 14 | 电池电量低,SD卡被移除,有电话打出去,有短信发送进来,软件的卸载安装,手机锁屏解锁,开机启动。 15 | 16 | ##01 android广播接收者编写步骤 17 | 1. 买收音机 18 | 19 | 2. 装电池 20 | 21 | 3. 调频道,调到你关心的频道 22 | 23 | ##02 广播接收者案例 SD卡状态监听(重点) 24 | 25 | 清单文件中需要配置如下: 26 | 27 | SD卡插拔动作: 28 | 29 | 30 | 31 | 数据类型,如果不配置,接受不到广播 32 | 33 | 34 | ##03 广播接收者案例 ip拨号器(重点) 35 | - 需求:当拨打长途电话时会自动的在电话号码前面添加17951; 36 | 37 | - 原理:通过网络拨打本地电话 38 | 39 | - 编写步骤: 40 | 41 | 1.买一个收音机: 42 | public class IpCallBroadcastReceiver extends BroadcastReceiver{} 43 | 2.装电池: 44 | 45 | 3.调整一个频道接收广播: 46 | 外拨电话的广播事件 47 | 48 | 4.添加权限: 49 | 50 | 51 | ##04 广播接收者案例 短信窃听器(重点) 52 | 53 | - 编写步骤: 54 | 55 | 1.写一个广播接收者,用于接受短信到来事件 56 | pdus:protocol data unit s 协议数据单元; 57 | 2.取出短信数据 58 | 3.转发短信到自己的手机 59 | 60 | - 清单文件中配置: 61 | 62 | 接收和发送短信权限: 63 | 64 | 65 | 66 | 短信到来动作: 67 | 68 | 69 | ##05 广播接收者案例 应用的卸载安装(重点) 70 | 71 | 清单文件中需要配置如下: 72 | 73 | 74 | 75 | //覆盖安装 76 | 77 | 78 | 数据,必须添加这个属性,否则接收不到这些事件 79 | 80 | 81 | ##06 广播接收者的特点和版本差异 82 | 83 | 1. 即使广播接收者没有运行,当广播事件到达的时候,系统会自动开启广播接收者,并且调用onReceive方法处理消息 84 | 85 | 2. google出于安全上的设计,强制要求4.0之后的版本,广播接收者如果被手工强制停止掉,就不能够接收到广播事件了,只有在下次启动这个广播接收者的程序后才能接收到广播事件 86 | 87 | ##07 自定义广播接收者的发送和接受 88 | - 搭建电台: 89 | 90 | 1.创建一个意图对象用于激活广播接收者和给接收者传递数据 91 | Intent intent = new Intent(); 92 | 2.设置广播的事件的动作 93 | intent.setAction("cn.itcast.CUSTOMBROADCAST") 94 | 3.设置给接收者传递的数据 95 | intent.setData(Uri.parse("itcast://打瓶酱油")) 96 | 4.发送广播 97 | sendBroadcast(intent); 98 | 99 | - 自定义广播接收者: 100 | 101 | 1. 买收音机 102 | 2. 装电池 103 | 3. 调频道,调到你关心的频道 104 | 105 | ##08 有序广播和无序广播(重点) 106 | 1. 无序广播:广播消息发送出去后,只要是指定这个事件的接收者都可以接收到这个事件 107 | - 无序广播的消息不能被拦截.不能被修改 108 | 109 | 2. 有序广播:广播消息发送出去后,按照接收者的优先级,从高到低一级一级的接受消息 110 | 111 | - 高优先级的接受者可以把广播消息给拦截,还可以修改广播的数据。 112 | 113 | - 如果没有给接收者指定优先级,会按照清单文件中接收者配置的先后顺序接受消息;放在最前面的接收者最先接收到消息,放在最后面的接收者后接收到消息 114 | 115 | - 有序广播可以指定最后一个接收者,他不在清单文件中注册,可以查看广播最终的数据 116 | 117 | ##09 两种广播的不同之处: 118 | - 如果拦截无序广播,会拦截失败 119 | - 无序广播不可以修改数据 120 | 121 | ##10 广播接收者案例 锁屏解锁(重点) 122 | 123 | 用代码注册 频繁生成事件的广播接受者 124 | IntentFilter filter = new IntentFilter(); 125 | filter.addAction("android.intent.action.SCREEN_OFF"); 126 | filter.addAction("android.intent.action.SCREEN_ON"); 127 | ScreenReceiver receiver = new ScreenReceiver(); 128 | this.registerReceiver(receiver, filter); 129 | 130 | 重要,注销锁屏广播 131 | unregisterReceiver(receiver) 132 | 133 | ##11 广播接收者案例 开机启动(重点) 134 | 135 | 清单文件中需要配置如下: 136 | 开机完成权限: 137 | 138 | 139 | 开机完成动作: 140 | 141 | 142 | 代码: 143 | 记得告诉Activity可以运行在应用程序的任务栈里面 144 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 145 | 146 | # 服务 service 147 | 148 | ##01 线程进程和应用程序之间的关系 149 | 150 | 开启应用程序Android系统为其创建一个Linux进程,应用程序的所有组件都是运行在同一个进程的同一个线程(main)里面。 151 | 152 | - 应用程序:包含了四大组件中任何一个或者多个组件的程序 153 | 154 | - 进程:应用程序的载体。主要用来负责运行dalvik虚拟机,而我们开发的应用程序就是运行在dalvik虚拟机里。 155 | 156 | - 进程销毁,进程里面的所有线程都不存在了 157 | 158 | ##02 进程的生命周期及其优先级 159 | - Process lifecycle 进程的生命周期 160 | 161 | - Android操作系统会尽可能长期的保留应用程序的进程,系统根据进程的优先级回收不重要的进程,释放内存。 162 | - 如果进程被系统回收,开启的所有的线程都不在了。 163 | 164 | - 进程的优先级: 165 | 166 | 1. Foreground process 前台进程 167 | 能看到应用程序的界面。并且可以操作这个应用程序。 168 | 2. Visible process 可视进程 169 | 能看到这个应用程序,但是操作不了。 170 | 3. Service process 服务进程 171 | 应用程序带一个后台运行的服务,并且服务没有停止。 172 | 4. Background process 后台进程 173 | 应用程序被最小化了,但是没有退出。 174 | 5. Empty process 空进程 175 | 应用程序没有任何活动的组件了 176 | 177 | ##03 服务 178 | 179 | 1. 什么是服务? 180 | 181 | 是一个没有界面,并且可以长期运行在后台的组件(简单的理解为是没有界面的activity) 182 | 183 | 2. 为什么要用服务? 184 | - 问题:如果开启子线程,也可以没有界面,长期后台运行。 185 | 186 | 让线程长期运行在后台,如果进程被系统回收,开启的所有的线程都不在了 187 | - 内存不足时,系统杀掉服务,如果内存充足,系统会还原服务 188 | 189 | 3. 服务编写步骤: 190 | 191 | 1.自定义一个类,继承父类Service; 192 | 2.在清单文件中配置一个service节点,name属性指向这个类的名称; 193 | 194 | ##04 服务的生命周期(重点) 195 | 196 | - 生命周期方法: 197 | 198 | 1.onCreate:在服务对象创建后调用这个方法,初始化服务对象; 199 | 2.onStartCommand:开启服务后调用这个方法; 200 | 3.onDestroy:在服务对象被销毁之前调用这个方法,通常在这个方法中做一些扫尾工作,比如保存数据; 201 | 202 | - 特点: 203 | 204 | 1. start方式第一次开启服务时,先创建服务对象,然后再开启服务 205 | 调用方法:onCreate(),onStartCommand() 206 | 2. 服务可以被多次开启,每次开启时只调用 207 | onStartCommand() (onStart已过时) 208 | 3. 服务只能被停止一次,调用方法:onDestroy() 209 | 如果服务已经停止,多次调用stopService()无效 210 | 211 | ##05 服务里面可以执行耗时的操作吗?(面试题) 212 | 213 | - 服务是运行在主线程(main ui线程)里面的,不可以执行耗时的操作 214 | 215 | - 如果要执行耗时的操作需要在服务里面开启子线程执行耗时的操作。 216 | 217 | - 服务的特点:就是保证当前应用程序不容易被系统回收,即使被回收还会复活。 218 | 219 | ##06 监听电话状态的模板代码(重点) 220 | 221 | 1. 清单文件中添加权限: 222 | 223 | 224 | 225 | 2. 代码: 226 | 227 | 1. 获取系统电话的服务 228 | TelephonyManager tm = (TelephonyManager)getSystemService(TELEPHONY_SERVICE); 229 | 2. 设置电话状态监听器 230 | tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE); 231 | 3. 创建内部类 232 | private class MyListener extends PhoneStateListener { 233 | // 当呼叫的状态发生变化调用的方法。 234 | @Override 235 | public void onCallStateChanged(int state, String incomingNumber) { 236 | System.out.println("来电号码:"+incomingNumber); 237 | // 零响 接通状态 空闲 238 | switch (state) { 239 | case TelephonyManager.CALL_STATE_IDLE: // 空闲 240 | break; 241 | case TelephonyManager.CALL_STATE_RINGING: // 响铃状态 242 | break; 243 | case TelephonyManager.CALL_STATE_OFFHOOK: //电话接通 244 | break; 245 | } 246 | super.onCallStateChanged(state, incomingNumber); 247 | } 248 | } 249 | 4. 服务停止的时候 取消监听全部的状态 250 | tm.listen(listener, PhoneStateListener.LISTEN_NONE); 251 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | --------------------------------------------------------------------------------