安卓基础笔记

------------------------------day01-------------------------------

获取屏幕宽高的四种方式

方法一:

1
2
3
WindowManager wm = (WindowManager)  this .getSystemService(Context.WINDOW_SERVICE);
int  width = wm.getDefaultDisplay().getWidth();
int  height = wm.getDefaultDisplay().getHeight();</div>

方法二:

1
2
3
WindowManager wm1 =  this .getWindowManager();
int  width1 = wm1.getDefaultDisplay().getWidth();
int  height1 = wm1.getDefaultDisplay().getHeight();

方法一与方法二获取屏幕宽度的方法类似,只是获取WindowManager 对象时的途径不同。

方法三:

1
2
3
4
5
WindowManager manager =  this .getWindowManager();
DisplayMetrics outMetrics =  new  DisplayMetrics();
manager.getDefaultDisplay().getMetrics(outMetrics);
int  width2 = outMetrics.widthPixels;
int  height2 = outMetrics.heightPixels;

方法四:

1
2
3
4
5
Resources resources =  this .getResources();
DisplayMetrics dm = resources.getDisplayMetrics();
float  density1 = dm.density;
int  width3 = dm.widthPixels;
int  height3 = dm.heightPixels;

方法三与方法四类似

注解 jsk1.5之后才有  写在方法上
*@Test 单元测试  必须为public修饰,不能有static,运行时调用junit运行
*@Deprecated 过时的
*@SuppressWarnings("all") 压制  去除黄色警告线
*@Override 方法重写


断言 Assert.assertEquals(40, result);// 参数为(期望值,实际值)


四种解析xml方法:
*dom解析xml
[1]创建工程类对象DocumentBuilderFactory
[2]获取解析器对象DocumentBuilder
[3]解析xml文档Document   parse(File file)
[4]获取指定标签的集合getElementsByTagName(String s)
[5]遍历集合获取指定所引出的标签  item(i)
[6]获取节点名称  getNodeName() 获取文本内容getTextContent() 获取节点类型getNodeType()
*sax解析xml
[1]创建工厂类对象  SAXParserFactory
[2]获取解析器SAXParser
[3]解析xml文档parse(File file, new DefaultHandler(){重写文档开始结束 元素开始结束 文本内容标签的方法});
*xmlpull解析xml   (需要借助于第三方的jar包)
[1]创建工厂类对象XmlPullParserFactory
[2]获取解析器XmlPullParser
[3]解析xml文档setInput(File file , String 编码形式)
[4]获取事件类型int eventType = parser.getEventType();
[5]判断循环条件为类型不等于结束文档元素   eventType != XmlPullParser.END_DOCUMENT
[6]switch 判断每一个事件类型
[7]获取属性值getAttributeValue(i)  获取元素名称  getName() 获取元素值nextText() 获取下一个事件类型next()
*json解析  (需要借助于第三方jar包)
[1]用构造方法解析  {}对象   new JSONObject(String s)  
[2]获取指定元素对应的值      json.opt(String name) 
[3]用构造方法解析  [{},{}] 对象数组    new JSONArray(String s)
[4]获取指定索引处的对象get(i)     返回值类型强制转换为JSONObject
[5]获取指定元素对应的值opt(String name)


------------------------------day02-------------------------------


创建控件对象
*所有的控件都继承View类
*Button bt = (Button) findViewById(R.id.button1);
*EditText editText = (EditText) findViewById(R.id.editText1);
*创建按钮点击事件 bt.setOnClickListener(new OnClickListener() {重写onClick方法public void onClick(View v){..}}
*获取文本框里的内容 String text = editText.getText().toString();
*创建意图Intent 并实现 共四步:
//[1]创建意图对象
Intent intent = new Intent();
//[2]给意图设置动作
intent.setAction(Intent.ACTION_CALL);
//[3]设置数据
intent.setData(Uri.parse("tel:" + text)); //打电话前面必须有协议  tel:
//[4]开始活动
startActivity(intent);
*打电话意图注意事项:
打电话的号码前面必须有协议"tel:"
在配置文件Androidmanifest.xml中需要申明权限 <uses-permission android:name="android.permission.CALL_PHONE"/>


实现按钮点击事件的四种方法:
*匿名内部类
*创建一个类去实现OnClickListener
*用this关键字  bt.setOnClickListener(this);  前提是MainActivity类实现OnClickListener  常用
*在layout的activity_main.xml文件中 的按钮属性里添加一个Onclick属性  然后直接在MainActivity里重写这个属性名称的方法参数为(View v)


五种布局Layout
*线性布局LinearLayout
*相对布局RelativeLayout
*表格布局TableLayout
*帧布局FrameLayout
*绝对布局


width 宽度 hight 高度  margin..边距  align..与..对齐  center..与整体中心对齐  fastScrollEnabled滚动条
below  above to..of在谁的..边  


------------------------------day03-------------------------------


安卓里的单元测试
*该方法需要继承"安卓测试环境"AndroidTestCase
*"配置文件"AndroidManifest.xml中要申明两点:
*<instrumentation  
android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.itheima.ceshi"><instrumentation/>
*<application...>
<uses-libraryandroid:name="android.test.runner"/>


判断一个变量是否为空    TextUtils.isEmpty(String name) ;


登录案例
*Context上下文---->可操作内置存储卡
MainActivity extends Context   
Context的对象可以理解为MainActivity的对象,所以在MainActivity类中可以用this表示,在其他类中用MainActivity.this表示
String path = context.getFilesDir().getPath() 得到路径是"/data/data/包名/files/"(context表示Context的对象)
FileOutputStream fos = context.openFileOutput("info2.txt", 0);得到的是一个字节输出流对象  第二个参数表示权限
FileInputStream fis = context.openFileInput("info2.txt");得到的是一个字节输入流对象
*toast一个输出语句跟信息提示框差不多
Toast.makeText(MainActivity.this, 要提示的内容, 0).show();最后一参数表示停留时间的长短,可选0和1
*Environment环境---->可操作sdcard
String path = Environment.getExternalStorageDirectory().getPath();得到的是一个路径"/sdcard/"
往内存卡里写数据在配置文件AndroidManifest.xml中要有一个权限申明:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
判断内存卡状态是否安装
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) 判断内存卡是否已安装
获取内存卡空间总大小
long num1 = Environment.getExternalStorageDirectory().getTotalSpace();
获取内存卡可用空间大小
long num2 = Environment.getExternalStorageDirectory().getUseableSpace();
将数据解析为固定格式
totalSize = Formatter.formatFileSize(this, totalSpace);
useSize = Formatter.formatFileSize(this, usableSpace);


权限
*分为 自己-用户组-其他 r表示可读 w表示可写 x表示可执行 1代表可,0代表不可, 可读可写可执行的二进制111
*修改文件权限(了解)
在adb进入Linux系统 并进入到要修改的文件的目录   chmod 777 修改的文件名(7代表的是可读可写可执行的二进制111转换来的十进制)


sp 相当于一个map集合 可以存取数据到本地xml文件 不用IO流(重要)
*存储数据   四步 ----->sepc (see pc 看电脑)
//[1]创建sp对象
*SharedPreferences sp = getSharedPreferences("info",MODE_PRIVATE);
//[2]获取一个Editor对象
Editor edit = sp.edit();
//[3]添加数据到sp
edit.putString("name", name);
edit.putString("pwd", pwd);
//[4]提交数据到本地文件
edit.commit();
*读取数据------>sg 两步(2g)
//[1]创建sp对象
SharedPreferences sp = getSharedPreferences("info", MODE_PRIVATE); 第二个参数表示权限
//[2]读取数据
String name = sp.getString("name", "");第二个参数表示 如果第一个参数不存在则返回""


小知识   //TODO ..  相当于标记 可以快速定位


将数据序列化为xml文档   前两步准备工作 先创建xml序列化对象 序列化指定文件 从开始文档依次序列化内容(序列化 文件 内容 三大步)

//[1]创建序列化对象
XmlSerializer serializer = Xml.newSerializer();
//[2]设置序列化时输出到的指定文件的字节输出流
FileOutputStream fos = openFileOutput("xml2.xml", MODE_PRIVATE);
serializer.setOutput(fos, "utf-8");
//[3]序列化xml申明 开始文档
serializer.startDocument("utf-8", false);第二个参数表示是否有独立
//[4]序列化开始根标签
serializer.startTag(null, "user");第一个参数表示是否有约束
//[5]序列化属性开始标签
serializer.startTag(null, "person");
//[6]序列化开始标签
serializer.startTag(null, "name");
//[7]序列化文本内容
serializer.text(persons.get(i).name);
//[8]序列化结束标签
serializer.endTag(null, "name");
//[9]序列化结束属性标签
serializer.endTag(null, "person");
//[10]序列化结束根标签
serializer.endTag(null, "user");
//[11]序列化结束文档标签
serializer.endDocument();


------------------------------day04-------------------------------


从控制台进入数据库
mysql -u root -p
显示所有数据库 查看表 查看表结构
show databases; show tables; desc 表名;
创建数据库 创建表
create database 数据库名; create table 表名(...);
删除数据库 删除表
drop database 数据库名; drop table 表名;
进入数据库
use 数据库名;
查看当前所在的数据库
select database();


使用sql对数据库操作crud
insert into 表名 values(...);
select * from 表名;
update 表名 set 字段 = 目标值;
delete from 表名;
增加一个字段: alter table 表名 add 要增加的字段 类型;


where条件的使用
语法:
select * from 表名 where 条件
update 表名 set 要修改的字段 ="修改后的值" where 条件 
delete from 表名 where 条件
1].运算符 <, <=,>, >= ,==
2].in 在某个字段内查询某个值
3].条件同时满足 and or
4].like 模糊查询   例:like '%值%'
5]as 别名的使用    例:select english as 英语 from student;
6]distinct 去除重复记录  例:select distinct* from student;
7]排序
注意:单独使用的时候不需要加where关键字
[7.1]order by 字段名 asc 升序 如果不指定asc默认就是asc
select * from student order by english asc;
[7.2]order by 字段名 desc 降序
select * from student order by english desc;


聚合函数的使用
[1]count()函数   
select count(*) from ...where....
[2]sum()函数 
select sum(要进行求和字段) from ...where.... 
[3]avg()函数
select avg(要计算平均数的字段名称) from …
[4]max()函数 
select max(字段) from...
[5]min()函数 
select min(字段) from... 


分组查询和limit关键字
[1]分组查询:常用于聚合函数,根据一个或多个列对结果集进行分组
[1.1]统计每个学生的英语成绩的总和
语法:group by 字段 
select name,sum(english) from student group by name;
[2]having: 使用HAVING 子句原因是,使用分组的时候,WHERE 关键字无法与聚合函数一起使用
[2.1]统计每个学生的英语成绩的总和>100;
select name,sum(english) from student group by name having sum(english)>200;
[3]limit  分页查询 
语法:
1)limit 数量;
2) limit 起始位置(不包含起始位置),数量
[3.1]查询5条数据
select * from limit 5;
[3.2]从第5条记录开始查,一共查询4条记录
select * from limit 5,4;
JDBC  (java database connection)就是通过java操作mysql数据库 共四步 "足联升值"   需要导入Mysql的jar包
[1]注册驱动 Class.forName("com.mysql.jdbc.Driver");// 第二种DriverManager.register()不常用
[2]连接数据库获取连接通道 DriverManager.getConnection("jdbc:mysql://localhost:3306/数据库名","root",数据库密码);
[3]创建申明对象 [2].createStatement();
[4]执行sql语句 [3].execute..(sql语句);
    步骤简要概述:注册好驱动后连接签一个声明拿着声明执行语句去 (注连声执)--->(足联升值)
执行查询方法
ResultSet resultSet = [3].executeQuery(sql语句); //它是一个游标,可以指向不同的数据
while(resultSet.next){
resultSet.get..(字段名称)
}


关闭资源
ResultSet  Statement  Connection   都需要关闭资源


sql注入   
例如登录案例 
在登录时需要查询数据库里的帐号和密码是否都正确,
sql语句为 String sql = "select * from 数据库名 where name = '"+输入的帐号+"' + and password = '"+输入的密码+"'";
在登录时帐号写成 "正确的帐号 'or' 1 = 1"   密码随便写 便可登录成功.
针对这一bug的解决办法 sql语句使用时要用占位符  JDBC的第三步  "声明"变成了"预备声明"prepareStatement 
使用占位符? 将sql语句写成 String sql = "select * from 数据库名 where name = ? and password = ?";
获取PrepareStatement对象 PrepareStatement statement = 通道对象.prepareStatement(sql)//区别于createStatement();
给占位符赋值     statement.setString(1,输入的帐号);
statement.setString(2,输入的密码);
执行sql语句 ResultSet result = statement.executeQuery();//区别于executeQuery(sql);



------------------------------day05-------------------------------


安卓的数据库"sqlite"  就是一个文件
SQLiteOpenHelper  抽象类  管理数据库  没有无参的构造方法
创建一个类继承他  重写构造方法  和其他方法
super(context,数据库名,null,数据库版本从1开始);


创建数据库步骤
[1]创建SQLiteOpenHelper的子类对象
[2] SQLiteDatabase = [1].getwritableDatabase();//第一次为创建数据库,否则为打开数据库    数据库满了 会报错
 [1].getReadableDatabase() //数据库满了返回一个可读的数据库


安卓单元测试时一段代码被重复执行时
创建一个setUp()方法 单元测试前执行此方法 把重复代码写在这个方法里就可以了


用完后要关闭数据库 database.close()


SQLiteOpenHelper的重写的两个方法
onCreate()数据库第一次创建的时候调用  做表的初始化
OnUpdate()版本号升级了才可以调用  做表的更新  只可以升级不可以降级
sql语句调用
数据库对象.execSQL(sql语句);
安卓下的sql语句
创建一个表
db.execSQL("create table 表名(_id integer primary key,字段1 类型)");
增加 db.execSQL("insert into 表名(字段1,字段2) values(值1,值2)");
通过占位符的形式增加
db.execSQL("insert into 表名(字段1,字段2) values(?,?)",new Object[]{值1,值2});
查 db.execSQL("select 字段1,字段2 from表名")和mysql也一样
删除和更新和mysql一样


查询数据库
Cursor cursor = db.rawQuery("select * from 表名",null)
if(cursor != null && cursor.getcount()>0){
cursor.getString(列的索引);
}


从控制台操作Sqlite数据库
adb shell ---> cd 数据库所在的文件夹目录 ---> sqlite3 数据库名(打开数据库) --->sql语句;


修改控制台的编码方式
改成gbk编码方式 chcp 936    改成utf-8编码方式 chcp 65001


安卓api下对sql语句的增删改查crud
ContentValues values = new ContentValues(); //相当于一个map集合
values.put(字段1,值)
values.put(字段2,值)
增 db.insert(表名,null,values)  返回值一个long类型
删 db.delete(表名,字段=?,new String[]{值});
改 db.update(表名,values,字段=?,new String[]{值});
查 db.query(....);


事物  多条sql语句同时执行时  转账案例  转账过程中出错 钱不会少 也不会多
开启事物 db.beginTransaction()
db.setTransactionSuccessful();
关闭事物 db.endTransaction();


listView控件
listView的显示数据需要通过"数据适配器"来显示
ListAdapter为一个接口 子类有BaseAdapter,ArrayAdapter,CursorAdapter,SimpleCursorAdapter...
通过继承他的子类来实现显示数据
通过继承BaseAdapter
[0]在main布局中创建listView,新建一个item布局
[1]重写getCount()方法 返回要显示的item的个数  重写getView()返回一个View对象
[2]在MainActivity里调用setAdapter()来显示数据




listView的优化   (针对第二个参数View(历史缓存对象)的使用  )
加一个判断 if(View对象 == null){
创建TextView对象lv
}else{
lv = (TextView)View对象
}


listView控件在添加时 宽和高要使用"match_parent"  这样效率高


五大布局 都继承ViewGroup类  


打气筒的使用  可显示复杂界面
将资源布局文件转为View对象
View view = View.inflate(context,布局文件,null)


打气筒创建的三种方式
[1]View.inflate(context,布局文件,null)
[2]LayoutInflater.from(上下文).inflate(布局文件,null)
[3](LayoutInflater)getSystemService(LAYOUT_INFLATE_SERVICE).inflate(布局文件,null);


数组适配器ArrayAdapter
listView显示的只有文本数据时适合使用
[1]activityMain布局里创建一个ListView
[2]创建一个item布局 放一个TextView组件  不需要布局
[3]MainActivity里创建listView对象
[4]定义个数组,里面是需要显示的内容
[5]创建ListView对象,创建ArrayAdapter对象
[6]显示数据 lv.setAdapter(..)


简单适配器SimpleAdapter
listView显示的数据为文本且需要布局
[1]ActivityMain.xml里创建一个listView
[2]创建一个item布局,写好布局
[3]Mainactivity里创建listView对象
[4]创建一个list<HashMap<String,String>>的集合 并添加要显示的数据
[5]创建SimpleAdapter对象
[6]设置要显示ListView数据  lv.setAdapter(.)



调用安卓数据库显示到listView
先在ActivityMain.xml中创建ListView
创建item布局
[1]创建数据库
创建一个类继承SQLiteOpenHelper
[2]创建listView对象
[3]创建一个List集合
[4]创建一个类继承BaseAdapter|ArrayAdapter|SimpleAdapter
设置getCount()方法返回值为List集合的大小
在getView()方法中
利用打气筒创建View对象
设置要显示的内容
创建TextView对象tv
tv.setText(..)
[5]查询数据库Query()方法中
把查询到的数据封装到对象中,把对象添加到List集合中
设置要显示ListView数据 (这一步一定不能忘)
lv.setAdapter([4]创建的类的对象)


item点击事件
setOnclick..()


listView展示数据的原理
m:mode  v: View  listView   controller  adapter
------------------------------day06-------------------------------


netstat -ano 查看电脑软件的端口




















------------------------------day07-------------------------------
HttpURLConnection 类的操作 用来获取网页数据的
[1]创建Url对象
URL url = new URL(网址);
[2]打开连接
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
[3]设置请求方式
conn.setRequestMethod("GET");
[4]设置连接超时
conn.setConnectTimeout(毫秒时间);
[5]获取服务器返回的状态码
int code = conn.getResponseCode(); //code = 200表示请求成功
[6]如果请求成功,接受返回的数据  数据为IO流的形式
InputStream in = conn.getInputStream()
[7]将字节流转为String类型 得到数据


注:联网的操作都要添加一个权限Internet
安卓4.0以后不能在主线程做联网操作,必须在子线程里做
只有主线程才能跟新ui 解决方案 利用助手Handler去处理
[1]在主线程创建一个Handler对象,并重写Handler里的handleMessage(..)方法
Handler handler = new Handler(){
public void handleMessage(Message msg){
[4]//处理第[3]步发过来的消息,更新ui
}};
[3]Handler对象在子线程中给主线程发送消息
Message msg = new Message(); | Message msg = Message.obtain();
msg.obj = 转换好格式的服务器返回的信息
handler.sendMessage(msg);


toast 也是一个View不能再主线程更新





ScrollView控件
只能有一个孩子 例如:里面套一个textView就可以滚动这个textView的内容

缓存图片
获取出数据后执行
[1]File file = new File(getCacheDir(),"test.png");//getCacheDir()得到的是一个缓存目录/data/data/包名/cache
[2]用IO流字节输出流写到文件
[3]Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());//从路径读取图片
base64加密
针对图片名称进行加密
Base64.encodeToString(path.getBytes(),Base64.DEFAULT);


runOnUiThread(action)
不用Handler发消息更新ui了
Handler 里的postDelayed(Runnable,时间)多长时间后开始执行..
当Activity销毁时
protect void onDestroy(){...}


------------------------------day08-------------------------------


range头 断点续传和下载时用
在访问网络链接下载东西时 在获取字节流数据前加上一步conn.setRequestProperty("Range","bytes=开始位置-结束位置");


servlet入门
定义一个类继承HttpServlet
重写doGet()和doPost()方法
去web.xml文件中配置 <servlet>
注册浏览器访问虚拟路径<servlet-mapping>
resq.getwriter();
servlet绝对路径写法即<form  action = "/工程名/映射" method = "get">映射为创建servlet时生成的注解
servletConfig创建servlet时就创建了他,是一个接口
String name = getServletConfig().getServletName();//得到的是一个全类名
String name = getServletConfig().getInitParameter("name");//获取系统初始化参数即在配置文件web.xml中设置的参数(在servlet里设置)


ServletContext可以配置全局参数 <context-Param>
ServletContext servletContext = getServletConfig().getServletContext();
ServletContext servletContext = getServletContext();
String name = servlet.getInitParameter("name");
servletContext.set/getAttribute(key,value);
获取真实的路径:String fileUoloadPath = servletContext.getRealPath("upload")


request和response请求和响应
request
获取请求方式  request.getMethod();//get或post
获取URI(统一资源标识符就是代表一个路径)request.getRequestURI()
获取头信息 request.getHeader("Host");
获取表单提交的内容request.getParameter("name")
多个相同name时用request.getParametervalues("name")得到一个集合,然后遍历得出每一个值
response
以字节流输出时的解码问题
通知浏览器以utf-8的方式查看返回数据response.setheadler("Content-Type","text/html;charset=utf-8")
使用字节输出流对象写出给客户response.getOutputStream().write(data.getbytes("utg-8"))
以字符流输出时的解码问题
修改response域默认编码表response.setCharracterendcoding("utf-8")
通知浏览器以utf-8的方式查看返回数据response.setheadler("Content-Type","text/html;charset=utf-8")
使用字符输出流对象写出给客户response.getWriter().write(data)


request解决乱码
post解决乱码
request.setCharacterEncoding("utf-8")
get解决乱码
String name = request.getParameter("name")
byte[] bytes = name.getBytes("iso-8859-1")
String name = new String(bytes,"utf-8")
url编码和解码
String encode = URLEncode.encode(data,"utf-8")


String data = "%di%eu%4f%8j%"
String decode = URLDecode.decode(data,"utf-8")


文件上传
必须是个post表单<form action = "",method = "post" enctype = "multipart/form-data"/>
选择文件的那个按钮类型和属性为<input type = "file" name = "file"/>


servlet3.0实现文件上传
在这个定义的servlet类前加一个注解@MultipartConfig
获取普通上传内容String name = request.getParameter("name")
获取文件上传到的真实路径 String uploadPath = getServletContext().getRealPath(工程下定义的一个文件夹名称)
获取文件上传内容 Part  part = request.getPart("file")
获取上传文件的单独名称 part.getHeader("Content-Disposition")然后再分割
写到文件part.write(uploadPath + "/"+上一步得到的单独文件名称)


------------------------------day09-------------------------------




POST提交数据的方式 与GET提交数据方式的区别
先获取data数据
设置提交数据方式不同:conn.setRequestMethod("POST"); conn.setRequestMethod("GET");
多设置两个头信息:conn.setRequestProperty("Content-type",值);
conn.setRequestProperty("Content-length",data.length());
把组拼好的数据提交到服务器:conn.setDoOutput(true)//设置一个标记允许输出
  conn.getOutputStream().write(data.getBytes());

httpClient
DefaulthttpClient client = new DefaulthttpClient();
HttpGet get = new HttpGet(path)
HttpResponse response = client.execute(get)
int code = response.getStatusLine().getStatusCode()



urlEncodedFormEntity
post.setEntity(entity)


开源项目synchHttpClient
不需要开启线程 也可直接跟新ui
创建对象
调用post或get方法




多线程下载
获取文件大小
int len = conn.getContentLength()
在看客户端创建一个和服务器一模一样大小的文件
new RandomAccessFile("..exe","rw")
开三个线程酸楚每个线程下载的大小
int blockSize = length/count;
for循环算出每个线程下载的开始位置和结束位置
for循环在开启多个线程
断点下载

------------------------------day10-------------------------------

多界面切换
创建一个界面 [1]创建布局 [2]创建类继承Activity 并加载布局setContentView(..)
跳转主要是隐式意图和显示意图的使用
跳转到别的应用用的是隐式意图, 跳转到自己应用的其他界面用显示意图
隐式意图设置清单文件 系统的应用清单文件已设置好
调用清单文件的方法介绍
setAction()  addCategory()  setData()  setType()  setDataAndType()


人品计算器案例
单选按钮的布局  <RadioGroup > <RadioButton/>  <RadioButton/> </RadioGroup>
跳转时意图携带数据 
intent.putExtra("name", name);
intent.putExtra("sex", sex);
startActivity(intent);
跳转到界面后提取意图和携带过来的数据
Intent intent = getIntent();
String name = intent.getStringExtra("name");
int sex = intent.getIntExtra("sex", 0);




短信大全
Intent intent = new Intent();
//------------------下面数据是从系统代码中查找的
intent.setAction("android.intent.action.SEND");
intent.addCategory("android.intent.category.DEFAULT");//添加环境
intent.setType("text/plain");
intent.putExtra("sms_body", data);//注意添加短信数据的方式是putExtra(),所以获取短信的方式是getExtra();

startActivity(intent);

短信发送案例
页面跳转并为了获取跳转界面里的数据 开始意图时要用startActivityForResult(intent, 数字);
跳转后的页面创建意图并putExtra携带数据返回用setResult(数字, intent);关闭界面finish();
finish(0执行后MainActivity会执行onActivityResult()方法


发送短信 简易记法:短信管理者发送   需要SEND_SMS权限
SmsManager manager = SmsManager.getDefault();
manager.sendTextMessage(phone, null, message, null, null);


------------------------------day11-------------------------------


四大组件之一广播接受者BroadcastReceiver
[1]现在清单文件中定义一个广播接受者 和 接受的广播事件类型
[2]创建一个广播接受者类  

创建一个广播接受者需要在清单文件中配置下
<Receive name= "创建的这个全类名"
action = "需要的广播事件类型"


ip拨号案例  即打电话时自动在号码前加上固定号段 (get和set两步)
广播事件类型action:"android.intent.action.NEW_OUTGOING_CALL"
权限:"android.permission.PROCESS_OUTGOING_CALLS"
[1]定义一个类继承BroadcastReceiver并重写onReceive方法
[2]获取打电话时输入的号码intent.getResultData()//可以把往出打电话理解为向外发广播,这一步就是接受广播数据
[3]设置修改广播数据并发出去setResultData(号段+[2]);


sd卡状态监听 安装与卸载
广播事件类型action:"android.intent.action.MEDIA_MOUNTED" | "android.intent.action.MEDIA_UNMOUNTED"
data约束:scheme="file"
[1]定义一个类继承BroadcastReceiver并重写onReceive方法
[2]获取广播事件类型intent.getAction()判断是否与sd卡的两个广播事件类型一致并处理//只是用来接受广播,也没有数据也不需要修改数据和发送


短信监听器
广播事件类型action:"android.provider.Telephony.SMS_RECEIVED"
权限:"android.permission.RECEIVE_SMS"
[1]定义一个类继承BroadcastReceiver并重写onReceive方法
[2]获取短信数组intent.getExtras().get("pdus");//发过来的短信广播数据为pdu格式的不能用getrResultDara()接受;
[3]遍历得到的短信数组创建SmsMessage对象SmsMessage.createFromPdu(byte[] obj);
[4]获取短信发送者[3].getOriginatingAddress()和短信内容[3].getMessageBody();


应用的状态  安装和卸载  与sd卡状态监听差不多
广播事件类型action:"android.intent.action.PACKAGE_ADDED" | "android.intent.action.PACKAGE_REMOVED"
data约束scheme:"package"
[1]定义一个类继承BroadcastReceiver并重写onReceive方法
[2]获取广播事件类型intent.getAction()判断是否与应用的两个广播事件类型一致并处理
intent.getData()可以得到安装或卸载掉额那个应用的包名


手机重启   手机重启后打卡带有重启监听的这个软件即打开Activity界面   就是在广播中开启Activity  用startActivity(intent)
广播事件类型action:"android.intent.action.BOOT_COMPLETED"
权限:"android.permission.RECEIVE_BOOT_COMPLETED"
[1]定义一个类继承BroadcastReceiver并重写onReceive方法
[2]创建intent对象 Intent intent2 = new Intent(content,MainActivity.class)//这个intent和参数的Intent不一样,参数的intent是广播的Intent,这个是开启Activity的Intent
[3]在广播中开启Activity要设置一个标记intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
[4]开启Activity  content.startaActivity(intent2);


创建有序广播和无序广播 sendBroadcast()和sendOrderBroadcast()
无序广播
[1]创建意广播意图对象Intent intent = new Intent();
[2]设置广播事件类型intent.setAction("包名");//可随便写
[3]添加数据intent.putExtra("key","内容");
[4]关键一步发送广播sendBroadcast(intent);
接受时取数据遵从数据怎么存就怎么取
有序广播
在清单中设置优先级property
[1]创建意广播意图对象Intent intent = new Intent();
[2]设置广播事件类型intent.setAction("包名");//可随便写
[3]关键一步发送广播sendOrderBroadcast(第三个参数为最终接受者,倒数第二个参数为发送内容);
终止广播 abortBroadcast();




特殊的广播接受者 锁屏和开屏  
这个广播接受者在清单文件中注册无效 需要动态注册 new 广播接受者,new 意图过滤器,添加事件,注册
[1]定义一个类继承BroadcastReceiver并重写onReceive方法
 根据获取到的事件类型与下面添加的意图事件是否一致并执行相应逻辑
[2]mainActivity中new出[1]创建的类的对象receiver
创建意图过滤器IntentFilter filter = new IntentFilter()
添加意图事件filter.addAction("android.intent.action.SCREEN_OFF")
添加意图事件filter.addAction("android.intent.action.SCREEN_ON")
动态注册广播接受者registerReceiver(receiver,filter);


当Activity销毁时onDestroy()取消注册广播接受者unregisterReceiver(register);


帧动画    通过ImageView显示  用到"AnimationDrawable"
[1]找到ImageView控件对象iv
[2]设置一个背景资源iv.setBackgroundResource(R.drawable.my_anim)
[3]获取背景AnimationDrawable rocketAnimation = (AnimationDrawable)iv.getBackground();
[4]开始rocketAnimation.start()


样式和主题
在res下的values里的style.xml里添加  不仅限于style.xml里

------------------------------day12-------------------------------
服务Service四大框架之一
开启服务的两种方法:
startService(..)  这种方式开启可以是程序在后台一直运行,不会被杀死
bindService(..) 这种方式开启可以访问服务中暴漏的方法()
电话监听案例
开启一个服务 用来监听来电,而且不宜被杀死,但要想自动开启服务 ,还需要放在重启的广播接受中开启服务
实现步骤
[1]创建一个类继承BroadcastReceiver作为一个广播接受者,在onReceive中即收到广播后开启服务,并在清单中配置
由于系统重启不属于本应用的方法,所以清单文件中要添加意图过滤器
[2]创建一个类继承Service作为一个服务,在oncreate方法中开启电话监听,并在清单文件中配置
电话监听TelephonyManager通过getSystemService(..)获取,调用listen方法
电话录音new MediaRecorder();

注意权限:接受重启Receiver_boot 读取电话状态Read _phone_state,记录声音record_audio,和往内存卡写的权限

使用服务操作解锁屏
好处:因为服务会在后台一直运行,所以解锁屏的广播接受者会一直处于开启状态
步骤:
在mainActivity中开启一个服务,在服务的oncreate方法中注册广播,在服务的onDestroy方法中取消注册广播


注册特殊广播接受者的步骤
receiver = new ScreenReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.SCREEN_OFF");
filter.addAction("android.intent.action.SCREEN_ON");
registerReceiver(receiver,filter)


取消注册广播
unregisteredReceiver(receiver);


百度音乐盒
采用混合开启服务的方式 即保证了程序在后台一直运行, 有保证了可以调用服务里的播放暂停等各种方法
步骤:
[1]在mainActivity的oncreate方法中,先startService(..)在bindService(..)
[2]在MainActivity的onDestroy方法中取消绑定服务unbindService(..)
[3]创建一个类继承Service,并在服务中定义各种方法,创建一个接口暴漏要对外的方法,在服务类中创建私有的一个中间人对象继承Binder并实现接口
[4]在中间人类中重写接口中的方法,并在onBind方法中设置好返回值
[5]在Mainactivity中在onServiceConnected方法中获取中间人对象
[6]在MainActivity中完成按钮点击事件,利用中间人调用服务接口中暴漏的方法


进程间通讯ipc
即一个应用访问另一个应用里的暴漏的方法
斗地主中调用支付宝买欢乐豆的案例
[1]创建支付宝工程,并创建一个服务,里面添加个支付的方法,并创建好中间人对象MyBinder,创建一个提供一个接口里面暴漏这个支付方法,清单文件中注意要配置action,
[2]将这个接口后缀改为aidl,并把接口中的public去掉,将MyBinder继承Stub;
[3]将这个aidl和联通所在的包名复制到斗地主工程下,这样才可以进行进程间通讯
[4]在斗地主MainActivity中使用bindService通过隐式意图的方式(因为是调用其他应用)开启服务,在onDestroy中取消注册绑定服务,在onServiceConnected中创建中间人对象,用来调用接口中的方法
[5]实现按钮点击事件利用中间人调用接口中的支付方法;


对话框合集
包括:普通对话框,单选对话框,多选对话框,进度条,最后都要调用show()方法才可以显示
用到的类:AlertDialog.Builder dialog = new Builder(context);
用到的方法:dialog.setTitle(..)dialog.setMessage(..)dialog.setpositiveButton(..),dialog.show()
单选框的创建dialog.setSingleChoiceItems(数组,..)
多选框的创建dialog.setMultiChoiceitems(数组,...)
进度条的创建:ProgressDialog dialog1 = new ProgressDialog(context)
用到的方法:dialog1.setTitle(..),dialog1.setProgressStyle(..),dialog1.show();
进度条的使用时先要设置最大位置dialog1.setMax(100),进度位置设置方法dialog1.setProgress(i);
进度条的取消dialog1.dismiss();
注意使用进度条时属于耗时操作一定要在子线程中使用




广播中开启服务  如开机自动启动服务
服务中开启广播  为了让广播接受者长期在后台长期运行 如屏幕解锁屏

------------------------------day13-------------------------------
内容提供者
一个应用的数据库想让别的应用访问时 ,这个应用可以创建一个内容提供者.暴漏增删改查的方法并分别添加Uri地址,让其他应用通过匹配Uri的方式访问
创建内容提供者的步骤:
[1]创建一个类继承ContentProvider自动重写增删改查的方法
[2]在清单文件中配置provider属性name,authorities(相当于主机名),exported(4.3之后需要写)
[3]创建一个uri匹配器并定义为静态变量 static UriMatcher matcher = new uriMatcher(UriMatcher.NO_MATCH);
[4]静态代码块中匹配器添加uri matcher.addURI("自定义字符串","自定义字符串",自定义匹配码);
[5]在生成的oncreate()方法中创建数据库对象.
[6]在增删改查的方法中用匹配器匹配调用者传递进来的Uri地址生成匹配码,如果这个匹配码和你自定义的匹配码相同的话则
执行数据库的的增删改查方法,并返回具体的返回值


应用中访问其他应用中的内容提供者(即对其他应用的数据库的增删改查)
使用内容解析者ContentResolver执行增删改查的方法,然后把需要的Uri和values传递进来;
例如:getContentResolver().insert(uri,values);


短信备份  权限:READ_SMS  WRITE_SMS  WRITE_EXTERNAL_STORAGE
用内容解析者查询系统暴漏的短信内容提供者
Cursor cursor = getContentResolver().query(uri,new String[]{"address","date","body"},null,null,null);
uri的解析路径为"sms": Uri uri = Uri.parse("content://sms/")
将查询到的数据序列化到xml文件中;


虚拟短信
即自己给自己发短信 原理就是将数据直接插入到短信的数据库
getContentResolver().insert(Uri,values);


查询联系人
需要查询联系人数据库的三张表 raw_contact_id, data, mimetypes,
但实际上mimetypes这个表里的内容就是在data中,所以只需要两个uri路径
uri路径去系统的provider.Contacts包中查找清单文件中的主机名authorities,
Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
Uri uri2 = Uri.parse("content://com.android.contacts/data");
先查询raw_contact_id表中的id作为下面查询具体数据时的判断条件,同一个联系人不同类型数据的id是一样的
Cursor cursor = context.getContentResolver().query(uri, new String[]{"contact_id"}, null, null, null);
查询联系人的具体数据
Cursor cursor2 = context.getContentResolver().query(uri2, new String[]{"data1","mimetype"}, "raw_contact_id=?", new String[]{contact_id}, null);
mimetype表示数据的类型比如是姓名或者是邮箱\电话


插入联系人
将写好的联系人数据(姓名,电话,邮箱)插入到系统的联系人的数据库中
[1]查询raw_contacts表得到查询到的个数即为已存联系人的数量,将其加一并插入作为data表中的raw_contact_id
[2]将联系人的信息data1,raw_contact_id,mimetype,分别插入到数据库


内容观察者 如短信监听
如果一个应用的数据库被别的应用操作了,他会自动发一条通知,告知内容观察者getContentResolver().notifyChange(uri,null)
创建内容观察者的具体步骤:
在ManiActivity中oncreate方法中用内容解析者注册内容观察者 getContentResolver().registerContentObserver(uri,true,observer);
创建一个类继承ContentObserver 重写onchange方法比如提取数据
Uri uri = Uri.parse("content://sms/");
Cursor cursor = getContentResolver().query(uri, new String[]{"address","date","body"}, null, null, null);
cursor.moveToFirst();
cursor.moveToFirst();
String address = cursor.getString(0);
String date = cursor.getString(1);
String body = cursor.getString(2);


------------------------------day14-------------------------------

加载大图片
[0]getSystemService()得到windowManager对象,并得出屏幕宽和高 width = wm.getDefaultDisplay().getWidth();
[1]创建图片工厂的参数对象 BitmapFactory.Options options = new Options();
[2]申明从参数中仅仅查看图片大小 options.injustDecodeBounds = true;
[3]解析 BitmapFactory.decodeFile(路径,options);
[4]获取图片宽和高 int outWith = options.outwith;
[5]计算出缩放比  图片宽/屏幕宽 图片高/屏幕高 并比较哪个大并且大于1 则缩放比设置为哪个 options.inSampleSize = scale;
[6]声明从参数中不仅仅查看图片大小 options.injustDecodeBounds = false;
[7]解析 BitmapFactory.decodeFile(路径,options);
[8]在控件上显示 iv.setImageBitmap(bitmap)


图片的处理
要想对图片进行处理必须先创建他的副本,对副本进行操作在保存.
创建副本的步骤
[0]利用位图工厂解析出图片 src = BitmapFactory.decodeResource(getResources(),R.drawable.123.png);
[1]创建一个和要复制的图片等大的白纸 Bitmap.createBitmap(src.getwith(),src.getheight(),src.getconfig())
[2]创建画笔Paint paint = new Paint();
[3]创建画布将白纸铺到画布 Canvas canvas = new  Canvas([1]);
[4]开始画画Canvas.drawBitmap(src,new Matrix(),paint);
[5]显示iv.setImageBitmap(白纸)
对图片旋转 matrix.setRotate(....)
对图片平移 matrix.setTranslate(...)
对图片缩放 matrix.setScale(...)
对图片镜像 x缩放为-1+平移用matrix.postTranslate(..)
对图片倒影 y缩放-1+平移用matrix.postTranslate(..)


画画板
就是在创建出副本的基础上对iv添加一个触摸监听事件
在按下事件中获取开始的x和y坐标
在移动的事件中获取x和y的停止坐标
然后开始画线canvas.drawLine(startX, startY, stopX, stopY, paint);
再把停止坐标赋值给开始坐标
返回值改为true 表示销毁那一刻的事件


设置画笔加粗 paint.setStrokeWidth(20);
设置画笔颜色 paint.setColor(Color.RED);
保存图片 copyBitmap.compress(CompressFormat.PNG, 100, fos);//fos为输出的目录


播放音乐
[1]创建mediaplayer对象 MediaPlayer mediaPlayer = new MediaPlayer();
[2]设置音频资源 mediaPlayer.setDataSource("/mnt/sdcard/xpg.mp3");
[3]准备 mediaPlayer.prepare();
[4]开始播放 mediaPlayer.start();


播放网络音乐
与播放本地音乐不同的是准备阶段采用的是异步
准备 mediaPlayer.prepareAsync();
创建准备就绪监听事件 mediaPlayer.setOnPreparedListener
重写里面的准备就绪方法 开始播放音乐


SurfaceView播放视频(只支持mp4和3gp格式)


videoView  播放视频 (只支持mp4和3gp格式)

vitamio开源项目的使用(支持所有格式) 并且自带控制器
注意类库的加载使用方法
把类库当作工程加载进来  在需要使用这个类库的工程上右击选择属性找到安卓选项 点击加载

------------------------------day14-------------------------------
fragment   简易记法:管理事物替换提交的内容
Activity布局里创建两个fragment
创建创建两个类继承fragment
重写oncreateView方法 在这个方法里通过打气筒把布局转为View对象并展示界面
创建两个布局用来布局两个fragment类


动态添加fragment  "FragmentManager"
通过windowManager获取屏幕宽和高 比较宽和高判断竖屏还是横屏
竖屏时加载一个fragment 横屏时加载另一个fragment;
获取Fragment管理者FragmentManager fragmentmanager = getFragmentManager()
开启事物 transaction = fragmentmanager.biginTransaction();
替换原窗口内容transaction.replace(android.R.id.content, new FirstFragment);
最后提交事物 Transaction.commit();


Fragment兼容低版本 "FragmentManager"
MainActivity 修改为继承FragmentActivity
获取FragmentManager的方法不同 getSupportFragmentManager()


微信主界面的搭建   "FragmentManager"
Activity中搭建布局 底部四个按钮 上部为一个LinearLayout布局方向为垂直
创建四个Fragment类继承Fragment 同时创建四个fragment布局文件 里面设置要显示的内容
MainActivity中创建按四个钮点击事件 
获取FragmentManager  fragmanager  = getFragmentManager();
开启事物 transaction = fragmentmanager.biginTransaction();
替换原窗口内容transaction.replace(android.R.id.content, new FirstFragment);
最后提交事物 Transaction.commit();




fragment之间的通讯  
替换原窗口内容这一步不同transaction.replace(android.R.id.content, new FirstFragment,标记);
第三个参数是主要是Fragment之间交互时用来获取Fragment的对象 调用Fragment里的方法
在一个Fragment里获取另一个Fragment的对象 getActivity().getFragmentManager().findFragmentByTag(标记);


使用xml实现补间动画   使用动画工具类"AnimationUtils"来加载动画
[1]在res目录下创建一个anim文件夹,里面创建xml文件,在xml文件中定义动画效果  alpha  translate  scale rotate set
[2]动画的显示代码
Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.alpha);
iv.startAnimation(animation);








菜单的事件类型  简易记法:创建打开选择
菜单创建时onCreateOptionsMenu
菜单打开时onMenuOpened
菜单条目选择时onOptionsItemSelected




AutoCompleteTextView控件的使用  Spinner控件的使用步骤一样
使用数组适配器显示数据actv
[0]找到这个控件
[1]定义一个数组,存储要显示的数据
[2]创建一个数组适配器ArrayAdapter
[3]显示actv.setAdapter([2])




通知栏   通知管理者下达通知,设定好通知内容发送
低版本时的方法
[1]初始化化时创建出"通知管理者对象" 用来最后一步发通知nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
[2]创建"通知对象"Notification noti = new Notification(R.drawable.ic_launcher, "您收到一条信息", System.currentTimeMillis());
[3]设置最近的事件信息  即手指"通知内容" noti.setLatestEventInfo(this,"小芳","老地方见",PendingIntent);然后在前一步创建延期意图对象PendingIntent.getACtivity(....)
[4]"发送通知"nm.Notify(1,noti);


取消通知 nm.cancel(1);



























































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值