安卓

第一章

Android是Google公司基于Linux平台开发的手机及平板电脑的操作系统。

一。安卓体系的具体结构

分层结构,由高到低分别是应用程序层、应用程序框架层、核心类层、Linux内核

1.应用程序层(Applications)

​ 一个核心应用程序的集合,所有安装在手机上的应用程序都属于这一层,例如系统自带的联系人程序、短信程序等

2.应用程序框架层(Application Framework)

​ 主要提供了构建应用程序时用到的各种API

3.核心类层(Libraries)

​ 包含了系统库及Android运行时库。系统层这一层主要通过CC++库来位Android系统提供主要的特性支持。

4.Linux内核

​ 为Android设备的各种硬件提供了底层的驱动

二。Dalvik虚拟机

1.定义

​ Google自己设计用于Android平台的虚拟机,可以简单地完成进程隔离和线程管理,并可以提高内存的使用效率。每个Android应用程序在底层都会对应一个独立的Dalvik虚拟机实例。

2.与Java虚拟机的不同

Java虚拟机: 基于栈的架构

​ 栈是连续的内存空间,取出存入的速度比较慢

  • 编译后文件:.java -> .class -> .jar

Dalvik虚拟机: 基于寄存器的架构

​ 寄存器是CPU上的一块缓存,存取速度比从内存中快很多

  • 编译后文件: .java -> .class -> .dex -> .odex

三。Android程序结构

1.manifests

思考题:清单文件的作用功能

​ 存放AndroidManifest.xml文件(清单文件),是整个项目的配置文件。四大组件都需要在这个文件中注册。

​ 还可以在该文件中给程序添加权限。

​ 清单文件中的配置的信息会添加到安卓系统中,程序运行时,系统会找到清单文件中的配置信息

四大组件注册

1.activity注册方法
1
2
3
4
5
6
7
8
9
10
11
<activity
android:label="@string/app_name"
android:launchMode="singleInstance"
android:name=".Day21_03_SmsActivity" >

<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

</activity>
2.BroadcastReceiver静态注册方法

1
2
3
4
5
6
7
<receiver android:name=".SmsReceiver" >

<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>

</receiver>
3.ContentProvider注册方法

1
2
3
4
5
<provider
android:authorities="com.aile.provider.student"
android:name=".StudentProvider" >
</provider>

4.Service服务(IntentService和service注册方法)
1
2
<service android:name=".MyService" >
</service>

2.java

​ 存放所有Java代码,可以创建多个包,每个包里可以存放不同文件或者Activity

3.res

​ 存放资源。

  • drawable目录用于存放图片以及xml文件
  • layout存放布局文件
  • mipmap存放应用程序图标

4.Gradle Scripts

​ 存放项目创建的相关文件,无需修改


第二章

一。布局

1.线性布局LinearLayout

1)orientation属性:

  • 控制控件的排列方向
  • 有vertical和horizontal(默认)
    • vertical为线性垂直显示
    • horizontal为线性布局水平显示
1
2
3
4
5
6
7
8
<LinearLayout xmlns:android=""
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">

<Button>

</LinearLayout>

2)wrap_content和match_parent

  • wrap_content:包括内容让当前控件根据内容大小自动伸缩
  • match_parent:填充父窗体由父容器大小决定控件大小
    • 水平排列时不可用

3)layout_weight权重

  • 按钮1的权重值为1
    • 计算方法: 1/(1+1+2) = 1/4
    • 所以按钮1占一行的1/4
  • 设置android:layout_width=”match_parent”后Button中的layout_width会失去作用,所以设置为0dp作为规范写法,不会影响效果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<LinearLayout xmlns:android=""
android:layout_width="match_parent"
android:layout_height="wrap_content"
<Button
android:id="@+id/btn_one
android:layout_width="0dp
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="按钮1">
<Button
android:id="@+id/btn_two
android:layout_width="0dp
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="按钮2">
<Button
android:id="@+id/btn_three"
android:layout_width="0dp
android:layout_height="wrap_content"
android:layout_weight="2"
android:text="按钮3">

</LinearLayout>

2.相对布局RelativeLayout

默认采用的是相对布局

  • px: 像素
  • pt: 磅数
  • dp: 基于屏幕密度的抽象单位,不同设备希纳是效果不同
  • sp: 可伸缩像素

3.帧布局FrameLayout

  • 所有控件默认显示在左上角。

  • 按先后放入顺序重叠摆放,先放入的控件显示在最底层,后放入的控件显示在最顶层

布局属性 功能 属性值
android:foreground 设置前景图片(始终在所有子控件之上) 图片路径
android:foregroundGravity 前景图片显示位置 left right center

4.表格布局TableLayout

布局属性 功能
android:stretchColumns 设置该列被拉伸
android:shrinkColumns 设置该列被收缩
android:collapseColumns 设置该列被隐藏
  • 所有列号都是从“0”开始
控件属性 功能
android:layout_column 设置该单元显示位置
android:layout_span 设置该单元占据几列,默认为1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<TableLayout xmln:android=""
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:stetchColumns="2"> //拉伸第三列
<TableRow>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="0"
android:text="按钮1" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="1"
android:text="按钮2" />
</TableRow>
</TableLayout>

5.绝对布局AbsoluteLayout

二。常用控件

1.TextView

控件属性 功能
android:text
android:textColor
android:textSize
android:textStyle
android:height
android:width
android:maxLength
android:password
android:gravity 设置文本位置

layout_width、layout_height和width 、height区别

1.

  • 对于带layout前缀属性通常是相对父控件而言
  • 不带是相对与控件本身而言

2.layout的可以单独使用,不带的不能单独使用

3.不带的只能设置为固定值

4.要使用不带的,就必须同时设置layout_width和layout_height属性

2.EditText

控件属性 功能
android:hint 没有输入内容时显示的提示文本
android:lines 固定行数决定EditText高度
android:editable 是否可编辑
android:scrollHorizontally 是否出现横拉条

可以设置android:maxLines来设置最大行数,超过行数会显示滚动条

3.Button的3种常用的点击方式

1.布局中指定onClick属性

1
2
3
4
5
6
<Button
android:id = "@id/btn_one"
android:text = "按钮1"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:onClick = "click" />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class MainActivity extends AppCompatActivity  {
private Button myBtn_one;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化控件
myBtn_one = (Button) findViewById(R.id.btn_one)
}
//实现onClick()方法,实现按钮1点击事件
public void click(View v){
myBtn_one.setText("按钮1点击")
}
}

2.使用匿名内部类

1
2
3
4
5
<Button
android:id = "@id/btn_two"
android::text = "按钮2"
android:layout_width = "match_parent"
android:layout_height = "wrap_content" />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class MainActivity extends AppCompatActivity {
private Button myBtn_two;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化控件
myBtn_two = (Button) findViewById(R.id.btn_two);

//匿名内部类的方法实现按钮2点击事件
myBtn_two.setOnclickListener(new View.OnClickListener() {
@Override
//重写onClick方法
public void onClick(View v) {
myBtn_two.setText("按钮2点击");
}
})
}
}

3.在当前Activity中实现OnClickListener接口

  • 按钮较多时使用
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
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button myBtn_two;
private Button myBtn_one;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化控件
myBtn_two = (Button) findViewById(R.id.btn_two);
myBtn_one = (Button) findViewById(R.id.btn_one);
myBtn_one.setOnClickListener(this);
myBtn_two.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch(v.getId() ){
case R.id.btn_one:
myBtn_one.setText("按钮1");
break;
case R.id.btn_two:
myBtn_two.setText("按钮2");
break;
}
}
}

4.RadioButton

RadioGrop是单选组合框,可容纳多个RadioButton

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
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RadioGroup
android:id="@+id/rdg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton
android:id="@+id/r_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="25dp"
android:text="女">
</RadioButton>
<RadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="25dp"
android:text="男"
android:checked="true">
</RadioButton>
</RadioGroup>
</LinearLayout>
  • checked属性:设置为true则默认选中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private RadioGroup radioGroup
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化控件
radioGroup = (RadioGroup) findViewById(R.id.rdg);

//匿名内部类的方法
radioGroup.setOnCheckChangeListener(new RadioGroup.OnCheckChangeListener() {
@Override
//重写方法
public void OnCheckChange(RadioGroup group) {
if(checkedId == R.id.r_btn) {

}else {

}
}
})


5.消息对话框

1
2
3
4
5
6
7
8
9
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建Toast
Toast.makeText(this , "Hello,Toast", Toast.LENGTH_SHORT).show();

})

三。LogCat的使用

​ Android中的命令行工具,用于获取程序成启动到关闭的日志信息。

等级

等级由低到高排

import android.util.Log

1.Verbose 全部消息 (黑色)

  • Log.v()

2.Debug 调试信息(蓝色)

  • Log.d()

3.Info 一般信息(绿色)

  • Log.i()

4.Warning 警告信息(橙色)

  • Log.w()

5.Error 错误信息(红色)

  • Log.e()

6.Assert

过滤器

1.Filter Name 过滤器的名称

2.by Log Tag 根据定义的Tag过滤,通常使用类名

3.by Log Message 根据输出内容过滤信息

4.by PID 根据进程id

5.by Application Name 根据应用名称过滤信息

6.by Log Level 根据日志的级别过滤信息

四。单元测试

​ 单元测试是指应用程序开发过程中对最小的功能模块进行测试,可以在完成某个功能之后对该功能进行单独测试,而不需要把应用程序安装到手机或启动模拟器再对各项功能进行测试,可以提高开发效率和质量

Android Studio在创建项目时就默认创建了一个androidTest包和ApplicationTest类,把测试的功能模块写入此类即可

进行单元测试时的步骤

1.在ApplicationTest类中添加一个test()测试方法

  • 所有测试方法必须以test开头,否则没有测试选项

2.单独选择test方法进行运行查看结果


第三章

一。Activity创建

包名处右键—>new—->Activity—->Empty Activity

输入Activity Name和Layout Name、Package name

创建的activity.java

1
2
3
4
5
6
7
public class ShopActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shop);
}
}

手动注册

1
2
3
在AndroidManifest.xml中添加
<activity android:name=".ActivityExample"> </activity>

二。生命周期

img

1.生命周期状态

onCreate() —> onStart() —> onResume() —> onPause() —> onStop() —> onDestroy()

1)启动状态

2)运行状态

3)暂停状态

4)停止状态

5)销毁状态

2.生命周期方法

1.onCreate()方法

创建时调用

1
2
3
4
5
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(saveInstanceState);
setContentView(R.layout.activity_main);
}

2.onStart()方法

在Activity即将可见时调用

1
2
3
4
@Override
protected void onStart() {
super.onStart();
}

3.onResume()方法

在Activity获取焦点开始与用户交互时调用

1
2
3
4
@Override
protected void onResume() {
super.onResume();
}

4.onPause()方法

当前Activity被其他Activity覆盖或锁屏时调用

当执行到onPause()方法失去焦点 , 重新回到前台会执行onResume()方法

1
2
3
4
@Override
protected void onPause() {
super.onPause();
}

5.onStop()方法

Activity对用户不可见时

1
2
3
4
@Override
protected void onStop() {
super.onStop();
}

6.onDestroy()方法

Activity销毁

1
2
3
4
@Override
protected void onDestroy() {
super.onDestroy();
}

7.onRestart()方法

Activity从停止状态再次启动

1
2
3
4
@Override
protected void onRestart() {
super.onRestart();
}

三。Activity之间的跳转

​ Intent称为意图,是程序中各组件进行交互的一种重要方式,不仅可以将指定当前组件要执行的动作,还可以在不同组件之间进行数据传递。一般用于启动Activity、Service以及发送广播等

1.打开浏览器

1
2
3
4
5
6
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);

2.数据传递

将要传递的数据暂存到Intent中,启动另外一个Activity后从Intent中取出数据即可

1
2
3
4
5
6
7
8
9
10
//传递数据

Intent intent = new Intent(this,Activity.class);
intent.putExtra("extra_data","hello"); //第一个参数为name,第二个参数为value
startActivity(intent);

//Activity中取数据

Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");

3.数据回传

startActivityForResult(Intent intent,int requestCode)

setResult(int resultCode,Intent data)方法

不过现在已经弃用

代替为registerForActivityResult()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Activity01中

Intent intent = new Intent(this,Activity02.class);
startActivityForResult(intent,1) //第一个参数是Intent对象,第二个参数是请求码,输入一个唯一值即可


Activity02中返回数据

Intent intent = new Intent();
intent.putExtra("extra_data","hello");
setResult(1,intent); //第一个参数用于向Activity返回处理结果,一般使用0或1


Activity02被销毁时会回调Activity01的onActivityResult()方法,Activity01中需要重写一下接收数据

@Override
protected void onActivityResult(int requestCode,int resultCode,Intent data){
super.onActivityResult(requestCode,resultCode,data);
if (requestCode == 1) {
if (resultCode == 1) {
String string = data.getStringExtra("extra_data");
}
}
}

第四章

一。五种存储方式

1.文件存储

​ 读取/写入文件,通过openFileInput()和openFileOutput()方法读取设备上的文件。与Java中实现I/O程序一致

存储位置

  • 默认存储在 data/data//files/ 目录下
1
2
FileOutputStream fos = openFileOutput(String name,int mode);  //输出流
FileInputStream fis = openFileInput(String name); //输入流
  • “name” 表示文件名
  • “mode” 表示文件的操作模式
    • MODE_PRIVATE: 文件只能被当前程序读写
      • 默认模式
    • MODE_APPEND: 文件内容可以追加
    • MODE_WORLD_READABLE: 文件的内容可以被其他程序读
    • MODE_WORLD_WRITEABLE: 文件的内容可以被其他程序写

数据存储到文件

1
2
3
4
5
6
7
8
9
10
String name = "data.txt";
String data = "hello";
FileOutputStream fos;
try {
fos = openFileOutput(name,MODE_PRIVATE);
fos.write(data.getBytes());;
fos.close();
} catch (Exception e) {
e.printStackTrace();
}

数据读取

1
2
3
4
5
6
7
8
9
10
11
String content = "";
FileInputStream fis;
try {
fis = openFileInput("data.txt");
byte[] buffer = new byte[fis.available()]; //创建缓冲区,获取文件长度
fis.read(buffer); //内容读入buffer缓冲区
content = new String(buffer) //转换成字符串
fis.close();
} catch (Exception e) {
e.printStackTrace();
}

2.SharedPreferences

​ 用XML格式将数据存储到设备中,可以存储应用程序的各种配置信息(用户名、密码等)

存储位置

  • data/data//shared_prefs文件夹中

存储方式

  • 通过key/value(键值对)的形式将数据保存在XML文件中
  • value值的类型只能是Float,Int,Long,Boolean,String,StringSet类型数据

1.存储数据

1.调用getSharedPreferences(String name,int mode)方法获取实例对象

2.调用SharedPreferences的edit方法获取到可编辑的Editor对象

3.通过putString(),putInt()方法存储数据

4.通过commit()方法提交数据

1
2
3
4
5
6
7
8
9
SharedPreferences sp = getSharedPreferences("data",MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putString("name","hello");
editor.putInt("age",9);
editor.commit(); //提交

//删除数据
editor.remove("name"); //删除一条数据
editor.clear(); //删除所有数据

2.获取数据

1.获取SharedPreferences对象

2.通过getxxx()方法获取到对应的key值

1
2
SharedPreferences sp = getSharedPreferences("data",MODE_PRIVATE);
String data =getSring("name","") //第二个参数为缺省值,如果name不存在,则返回空字符串

3.SQLite数据库

​ Android自带的一个轻量级数据库,支持基本SQL语法,一般使用它作为复杂数据的存储引擎。

详细见第五章

4.ContentProvider

​ 四大组件之一,主要用于应用程序之间的数据交换,可以将自己的数据共享给其他应用程序使用

5.网络存储

​ 将数据存储在服务器上

二。XML解析

1.DOM解析
2.SAX解析
3.PULL解析

三。JSON解析


第五章

考编程题查询数据并展示在listview中

看p138的绿豆通讯录

一。数据库的创建

1.创建一个类继承SQLiteOpenHelper

2.重写onCreate()和onUpgrade()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MyHelper extends SQLiteOpenHelper {
public MyHelper(Context context) {
super(context, "ahao",null,2);
//上下文对象 数据库名称 游标工厂(通常为null) 数据库版本
}
//数据库第一次创建时调用
public void onCreate(SQLiteDatabase db) {
//初始化数据库的库结构
db.execSQL("CREATE TABLE information(_id INTEGER PRIMARY KEY AUTOINCREMENT,name VARCHAR(20), price Integer)");
//表名为information,数值_id,name,price
}
//数据库的版本号增加时调用
public void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion) {

}
}

二。增删改查

1.增加数据

1
2
3
4
5
6
7
8
9
public void insert(String name,String price) {
SQLiteDatabase db = helper.getWritableDatabase(); //获取可读写SQLiteDatabase对象
ContentValues values = new ContentValues(); //创建 ContentValues 对象
values.put("name",name); //添加数据到 ContentValues对象
values.put("price",price);
long id = db.insert("information",null,values); //插入一条数据到information表
// 第一个参数是表名 第二个参数是要插入的行为空行时,将这个列名的值设为null 第三个参数为 ContentValues 对象 通过键值对的形式存入数据
db.close();
}

2.修改数据

1
2
3
4
5
6
7
8
9
10
public int update(String name, String price) {
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("price",price);
int number = db.update("information",values,"name=?",new String[]{name});
//第一个参数表示表名,第二个参数接收一个ContentValues对象 第三个参数为可选的where语句, 第四个参数表示whereClause语句中表达式的占位参数列表,会替换where中的"?"
db.close();
return number;
}

3.删除数据

1
2
3
4
5
6
public int delete(long id) {
SQLiteDatabase db = helper.getWritableDatabase();
int number = db.delete("information","_id=?",new String[]{id+""});
db.close();
return number;
}

4.查询数据

1
2
3
4
5
6
7
8
9
10
11
12
13
public boolean find(long id) {
SQLiteDatabase db = helper.getWritableDatabase();
Cursor cursor = db.query("information",null,"_id=?",new String[]{id+""},null,null,null);
// 第一个参数表示表名称
// 第二个参数表示查询的列名
// 第三个参数表示接收查询条件子句
//第四个参数接收查询子句对应的条件值
//第五个参数表示分组方式 第六个参数表示接收having条件(定义组的过滤器) 第七个参数表示排序方式
boolean result = cursor.moveToNext();
cursor.close(); //关闭游标
db.close();
return result;
}

使用execSQL()方法操作

1
2
3
4
5
6
7
8
//插入
db.execSQL("insert into information (name,price) values (?,?)",new Object[]{name,price});
//修改
db.execSQL("update information set name=? where price =?",new Object[]{name,price});
//删除
db.execSQL("delete from information where _id = 1");
//查询
Cursor cursor = db.rawQuery("select * from person where name=?",new String[]{name});

三。SQLite中的事务

事务时一个对数据库执行工作的单元,是针对数据库的一组操作,可以由一条或多条SQL语句构成。

事务是以逻辑顺序完成的工作单位或序列,可以由用户手动操作完成,也可以由某种数据库程序自动完成

同一事务的操作具备同步的特点,一条语句无法执行,所有语句都不会执行

1
2
3
4
5
6
7
8
9
10
11
db.beginTransaction();  //开始事务
try {
db.execSQL();
db.setTransactionSuccessful();//标志事务执行完成
} catch (Exception e) {
Log.i("处理失败",e.toString());
}finally {
db.endTransaction(); //关闭事务
db.close();
}

  • 当执行到endTransaction()方法时,首先会检查是否有事务执行完成标记,有则提交数据,无则回滚数据

四。ListView控件

ListView是一个列表视图,由很多Item(条目)组成,每个Item的布局时相同的,Item布局单独使用一个XML定义

1.数据适配器

1)BaseAdapter

​ 基本的适配器,实际上是一个抽象类,通常在使用自定义适配器时需要继承BaseAdapter。有四个抽象方法

方法 功能描述
public int getCount() 得到Item条目的总数
public Object getItem(int position) 根据position(位置)得到某个Item的对象
public long getItemId(int postion) 根据position得到某个Item的id
public View getView(int position, View converView, ViewGroup parent) 得到相应position对应的Item视图,position是当前Item的位置,converView用于复用旧视图,parent用于加载XML布局

2)SimpleAdapter

​ 继承自BaseAdapter,实现对四个抽象方法进行了封装。使用SimpleAdapter进行数据适配时,只需要在构造方法中传入相应的参数即可

1
public SimpleAdapter(Context context, List<? extends Map<String,?>> data, int resource, String[] from,int[] to);
  • Context context: Context上下文对象
  • List> data: 数据集合,data中每一项对应ListView中每一项数据
  • int resource: Item布局的资源id
  • String[] from: Map集合里面的key值
  • int[] to: Item布局相应的控件id

3)ArrayAdapter

​ BaseAdapter的子类,只需要在构造方法中传入相应参数即可。通常用于设配TextView控件。

示例

activity_main.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ShopFragment">

<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/shop_image"
android:divider="#d0d0d0"
android:dividerHeight="1dp" />

</RelativeLayout>

item.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:id="@+id/image"
android:background="@drawable/shop">
</ImageView>
<TextView
android:id="@+id/item_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我的item布局"
android:textSize="18sp">
</TextView>
</LinearLayout>

MainActivity.java

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
35
36
37
38
39
40
41
42
43
44
45
public class ShopActivity extends AppCompatActivity {
private ListView listView;
private String[] name = {"京东", "pdd"};
private int[] icons = {R.drawable.apple,};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shop);

//设置ListView
//1、绑定控件
ListView listView = (ListView) findViewById(R.id.list_view);
//2.创建一个Adapter实例
MyBaseAdapter myBaseAdapter = new MyBaseAdapter();
//设置Adapter
listView.setAdapter(myBaseAdapter);
}

class MyBaseAdapter extends BaseAdapter {
@Override
public int getCount() {
return name.length;
}

@Override
public Object getItem(int position) {
return name[position];
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = View.inflate(MainActivity.this, R.layout.item, null); //从item.xml中找到并转换成View对象
TextView textView = (TextView) findViewById(R.id.item_tv);
textView.setText(name[position]);
ImageView image = (ImageView) findViewById(R.id.shop_image);
image.setBackground(icons[position]);
return view;
}
}

第六章

当产生一个广播事件时,可以有多个BroadcastReceiver 接收并处理数据。

广播接收者只需要在清单文件或代码中进行注册并指定要接收的广播事件,创建一个类继承自BroadcastReceiver类,重写onReceive()方法,在方法中处理广播事件即可

一。基础

1.创建

new —-> other —-> Broadcast Receiver

注册

1)静态注册

AndroidMainfest.xml

1
2
3
4
5
6
7
<application>
<receiver
android:name=".MyReceiver"
android:enable="true"
android:exported="true">
</receiver>
</application>

MyReceiver.java

1
2
3
4
5
6
7
8
9
public class MyReceiver extends BroadcastReceivver {
public MyReceier() {

}
@Override
public void onReceive(Context context, Intent intent) {
//用于实现广播接收者的相关操作
}
}
2)动态注册
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shop);
//实例化广播接收者
MyReceiver receiver = new MyReceiver();
//实例化过滤器并设置要过滤的广播
String action = "android.provider.Telephony.SMS_RECEIVED";
IntentFilter intentFilter = new IntentFilter(action);
//注册广播
registerReceiver(receiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
//Activity销毁时取消注册BroadcastReceiver
unregisterReceiver(receiver);
}

2.拦截电话案例

广播接收者OutCallReceiver
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class OutCallReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//获取拨打的电话号码
String number = getResultData();
//创建SharedPreferences对象,拦截号码
SharedPreferences sp = context.getSharedPreferences("config",Context.MODE_PRIVATE);
String number2 = sp.getString("name","");
if(number.equals(number2)){
//清除电话
setResultData(null);
}else {
.................
}
}
}

AndroidManifest.xml中添加权限

1
2
3
4
5
6
7
<application>
<receiver android:name=".OutCallReceiver">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/> //权限
</intent-filter>
</receiver>
</application>

二.广播类型

1.有序广播

可以被拦截

​ 按照接收者声明的优先级别依次接收,发送广播时,只有一个广播接收者能够接收此消息,当此广播接收者中逻辑执行完毕后,广播才会继续传递。


优先级设置

  • 在注册广播接收者时,在标签中使用priority属性设置优先级
1
<intent-filter android:priority="100">
  • 属性值越大,优先级越高
  • 优先级相同时,先注册的优先级高

2.无序广播

​ 完全异步执行,发送广播时,所有监听这个广播的广播接收者都会接收到此广播消息,但接收和执行的顺序不确定

拦截广播案例

发送有序广播

1
2
3
4
5
6
7
8
9
public void  send(View view) {
Intent intent = new Intent();
//定义广播的事件类型
intent.setAction("Intercept_Stitch");
//发送广播
sendOrderedBroadcast(intent,null);

//第二个参数指定接收者的权限
}

添加广播接收者

1
2
3
4
5
6
public class MyBroadcastReceiverOne extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("广播接收者1接收到广播事件")
}
}

注册广播接收者

1
2
3
4
5
<receiver android:name=".MyBroadReceiverTwo">
<intent-filter android:priority="1000">
<action android:name="Intercept_Stitch"></action>
</intent-filter>
</receiver>

拦截有序广播

优先级高的广播接收者可以拦截收到的广播

1
2
3
4
5
6
7
public class MyBroadcastReceiverOne extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("广播接收者1接收到广播事件")
abortBroadcast() //比这个广播接收者优先级低的广播接收者都会被拦截
}
}

指定广播接收者

1
2
3
4
5
6
Intent intent = new Intent();
//定义广播的事件类型
intent.setAction("Intercept_Stitch");
//发送有序广播
MyBroadcastReceiverThree receiver = new MyBroadcastReceiverThree
sendOrderedBroadcast(intent,null,receiver,null,0,null,null);

第七章

Service(服务)是一个长期运行在后台的用户组件,没有用户界面。因此服务更适合执行一段事件而又不需要显示界面的后台操作(下载数据、播放音乐等)

一。创建

1
2
3
4
5
6
7
8
9
public class MyService extends Service {
public MyService() {

}
@Override
public IBinder onBind(Intent intent) {
throw new
}
}
  • 默认包含一个构造方法和一个onBind()方法
  • onBind()用于绑定服务,放回一个IBinder对象

注册

name中填的是服务的路径

enabled:是否实例化该组件

exported:该服务是否能够被其他应用程序调用或交互

1
2
3
4
5
6
7
8
9
<application>
.........
<service
android:name=".MyService"
android:enabled="true"
android:exported="true">
</service>
</application>

二。生命周期

​ 服务的启动方式有两种,分别是**startService()方法和bindService()**方法

image.png

方法

  • onCreate():第一次创建服务时执行
  • onDestory():服务被销毁时执行
  • onStartCommand(): 通过startService()方式启动服务
  • onBind(): 通过bindService()方法启动服务
  • onUnbind(): 客户端调用unBindService()断开服务器绑定时执行

启动

1.startService 方式

三。服务的通信

通过绑定方式开启服务后,服务与Activity可以通信。

必须保证服务是以绑定方式开启的,否转无法进行通信和数据交换。

1.本地服务通信

应用程序内部的通信

2.远程服务通信

两个应用程序之间的通信

注意看p175


第八章

一。简介

​ ContentProvicer内容提供者是四大组件之一,功能是在不同程序之间实现数据共享

  • 文件存储、SharePreferences存储、数据库存储这些只能在当前应用程序中访问

【Android】第十二周、内容提供者(ContentProvider)_内容提供者的工作原理__popo_的博客-CSDN博客

  • 要访问ContentProvider中共享的数据,一定要借助ContentProvider类

Uri

为内容提供者的数据建立了唯一的标识符。主要由scheme、authoritied和path三部分组成

scheme:

  • “content://“ 是一个标准前缀,表明这个数据被ContentProvider所控制

authority:

  • 在创建内容提供者时指定的authorities属性值,用于区分不同的应用程序
  • 一般采用程序包名命名

path:

  • 代表资源(数据)

二。内容提供者的创建

增删改查

  • insert()
  • delete()
  • update()
  • query()

注册

1
2
3
4
5
6
7
8
9
<application>
...
<provider
android:authorities="cn.app"
android:name=".MyContentProvider"
android:enabled="true"
android:exported="true">
</provider>
</application>

三。使用

1.访问内容提供者

1
2
3
4
5
6
7
8
9
10
11
12
13
       //获取相应操作的Uri
Uri uri = Uri.parse("content://cn.app/person");
//获取到ContentResolver对象
ContentResolver resolver = context.getContentResolver();

Cursor cursor = resolver.query(uri, new String[] { "address", "date", "type", "body"},null,null,null)

while (cursor.moveToNext()) {
String address = cursor.getString(0);
long date = cursor.getLong(1);
int type = cursor.getInt(2);
String body = cursor.getString(3);
}

案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
       //获取短信操作的Uri
Uri uri = Uri.parse("content://sms/");
//获取到ContentResolver对象
ContentResolver resolver = context.getContentResolver();

Cursor cursor = resolver.query(uri, new String[] { "address", "date", "type", "body"},null,null,null)
if(cursor != null && cursor.getCount() > 0) {
while (cursor.moveToNext()) {
String address = cursor.getString(0);
long date = cursor.getLong(1);
int type = cursor.getInt(2);
String body = cursor.getString(3);
}
}

四。内容观察者

观察指定Uri所代表的数据,数据变化时会触发ContentObserver的onChange()方法。

在onChange()方法中使用ContentResovler可以查询到变化的数据


第九章

GET方法

1
2
3
4
5
6
7
8
9
10
11
12
13
String path = "http://192.168.1.1:8080/web?username="+URLEncoder.encode("zhangsan")+"&password="+URLEncoder.encode("123");

//创建URL对象
URL url = new URL(path)

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
int responsecode = conn.getResponseCode;
if( responsecode == 200) {
InputStream is = conn.getInputStream
}
  • URL长度一般要小于1KB

POST方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
String path = "http://192.168.1.1:8080/web";
URL url = new URL();
HttpURLConnection conn = (HttpURLConnection) conn.openConnection();
conn.setRequestMethos("POST");
conn.setConnectTime(5000);

String data = "username="+URLEncoder.encode("zhangsan")+"&password="+URLEncoder.encoder("123")

//设置请求头数据提交方式,以form表单方式提交
conn,setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
//设置提交数据长度
conn.setRequestProperty("Content-Length", data.length() + "");

conn.setDoOutput(true); //设置运行向外写数据
OutputStream os = conn.getOutputStream(); //利用输出流向服务器写数据
os.write(data.getBytes()); //将数据写给服务器
int code = conn.getRequestCode();
if( code == 200 ) {
InputStream is = conn.getInputStream();
}


第十章

Fragment

Fragment不能独立存在,必须嵌入到Activity中使用

  • Activity暂停时,它所拥有的Fragment都暂停
  • Activity销毁时,它所拥有的Activity都销毁

image-20240106130326103

生命周期方法

  • onAttach() : 当Fragment和Activity建立关联时调用
  • onCreateView(): 创建视图
  • onDetach(): 当Fragment和Activity解除关联时调用

注册

  • 在Activity的布局文件中引用即可
1
2
3
4
5
6
7
<fragment
android:id="@id/fragment"
android:name=""
android:layout_width=""
android:layout_height="">
</fragment>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private List<Fragment> fragmentList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<Fragment> fragments = new ArrayList<>(Fragment) ();
fragments.add(new Fragment1());
fragments.add(new Fragment2());
fragments.add(new Fragment3());
FragAdapter adapter = new FragAdapter(getSupportFragmentManager(), fragments);
//设定设配器
ViewPager vp = (ViewPager) findViewById(R.id.viewpager);
vp.setAdapter(adapter);
}

安卓
https://ahaostillcoding.github.io/2024/01/07/安卓/
作者
a_hao
发布于
2024年1月7日
许可协议