Java-Android
- BasicsTwo(java)
- 反射
- 修改方法
- 修改值
- java正则验证
- 简易IO(面向文件的增删改查)
- IO流
- (文件字节输入流)FileInputStream
- (文件字节输出流) FileOutputStream
- (文件字符输入流)FileReader
- (文件字符输出流)FileWriter
- 【字节流复制(边读边写)】
- (缓冲输出字符流)BufferedWriter
- (缓冲输入字符流) BufferedReader
- (字节字符转换流)
- (序列化输入流)ObjectInputStream
- (序列化输出流)ObjectOutputStream
- 网络编程
- Server类
- ServerThread类
- Client类
- ClientThread
- -----------------------------------------
- BasicsThree(java~Web)
- 数据库学习(MySQL)
- 创建数据库
- 使用数据库
- 创建数据表
- 查询数据
- 增加数据
- 删除数据
- 更新数据(修改数据)
- 删除表
- --------------------------------------
- Web使用SSM框架简易连接MySQL
- Resources资源文件
- spring.xml
- mybatis.xml
- 实体类
- 数据访问层(dao层)
- 接口类
- xml文件(mapper)
- 业务逻辑层
- 分页展示实体类
- 控制器类
- WEB-INF内JSP文件(引用easyUI)
- 首页
- 添加页面(JS正则表达式验证)
- 修改页面(JS正则表达式验证)
- -----------------------------------------
- PhaseOne (Android)
- View
- RadioGroup
- RadioButton
- CheckBox
- Button
- TextView
- ImageView
- ImageButton
- ScrollView
- HorizontalScrollView
- EditText
- ListView
- GridView
- -----------------------------------------
- One(Android)
- Menu
- 系统Menu
- 上下文Menu
- 自定义Menu(PopupMenu)
- 对话框builder
- 普通对话框
- 单选对话框
- 多选对话框
- 进度条对话框
- 自定义对话框
- 自定义弹出窗口(PopupWindow)
- 通知
- notification在手机header显示
- Fragment(UI片段)
- 创建Fragment
- 模拟购物界面
- 布局
- Fragment类
- MainActivity类
- ViewPager (横向滑动Fragment)
- 主要思路
- 框架布局 activity_main.xml
- fragment布局
- Fragment类
- FragmentAdapter类 (Fragment适配器)
- MainActivity类
- 效果如下 ↓↓↓↓↓
- 引用TabLayout
- 主要思路
- activity_main.xml 框架布局
- FragmentAdapter类(Fragment适配器类)
- MainActivity类
- 效果如下 ↓↓↓↓↓
- Android轮播图(banner)
- 布局文件
- java类中
- 效果如下 ↓↓↓↓
- SharedPreferences
- 布局文件(写入两个供测试按钮即可)
- MainActivity文件
- 读写SD卡
- MainActivity类中
- 对Android数据库的增删改查
- mainActivity类中
- SQLite类中
- 内容提供者,内容解析者 Content Provider
- ContentProvider(内容提供者)
- SQLite类
- MainActivity类
- 创建ContentProvider类
- ContentProvider类
- ContentResolver(内容解析者)
- MainActivity类中
- 获取手机联系人和本地音乐(音乐播放器、电话簿)
- 创建实体类
- 联系人实体类(Person)
- 音乐实体类(Music)
- 创建适配器
- 音乐适配器(MusicAdapter)
- 联系人适配器(PersonAdapter)
- 主要的
- 获取本地音乐(Main2activity)
- 获取手机联系人(MainActivity)
- 广播(BroadcastReceiver) 动态
- 创建广播接收者
- 注册广播
- 发送广播
- 接收广播
- 静态与动态广播
- 动态广播
- MainActivity类中
- MyReceiver类(广播接收类)中
- 静态广播
- MainActivity中
- MyReceiver中
- 清单文件中
- 服务(Service)
- 创建Service
- MyService类
- MainActivity类
- 音乐播放器
- MainActivity类中
- 服务类
- 实体类
- -------------------------------
- PhaseTwo(Android)
- OkHttp(MVC)
- 单例类
- 单例类中需要的拦截器
- M层(Model模块)
- C层(Controller控制器层)
- V层(View视图层)
- IActivity
- BaseActivity
- IFragment
- BaseFragment
- 自定义Activity
BasicsTwo(java)
反射
修改方法
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
ArrayList<String> list = new ArrayList<>();
list.add("oiuoaisduf");
list.add("asljkdf");
Class<? extends ArrayList> aClass1 = list.getClass(); //通过对象名获取class
Class<ArrayList> aClass2 = ArrayList.class; //通过集合获取class
Class<?> aClass3 = Class.forName("java.util.ArrayList"); //通过包和类名获取class
Method add = aClass1.getDeclaredMethod("add", Object.class);
add.invoke(list,5.21345689756);
add.invoke(list,123456789);
add.invoke(list,5.21345689756);
System.out.println(list);
}
修改值
private static HashMap<String,User> map = new HashMap<>();
static {
User no1 = new User("wangyide", "5210");
User no2 = new User("aaa", "123");
map.put("user1",no1);
map.put("user2",no2);
}
public static void main(String[] args) {
Class<HashMap> hashMapClass = HashMap.class;
Collection<User> values = map.values();
Field[] declaredFields = hashMapClass.getDeclaredFields();
}
java正则验证
正则表达式是用于判定文本格式的,一般用于判断用户添加信息的格式,或登录注册时使用的。
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true){
System.out.println("请输入QQ邮箱:");
String email = scanner.next();
//调用正则判断方法
boolean regex = regex(email);
//如果不对则输出错误信息 正确则跳出
if (regex){
System.out.println("格式正确");
break;
}else {
System.out.println("格式不正确");
}
}
}
private static boolean regex(String email){
//正则表达式解析对象Pattern 参数为正则表达式
Pattern compile = Pattern.compile("^\\d+@\\w+.com(.cn)?$");
//pattern对象获取匹配数据对象 参数为输入的邮箱
Matcher matcher = compile.matcher(email);
boolean b = matcher.find();
return b;
}
}
运行效果 ↓↓↓↓↓
简易IO(面向文件的增删改查)
public class Demo {
private static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) throws Exception {
start();
}
private static void start() throws Exception {
System.out.println("1.文件目录操作");
System.out.println("0.退出");
System.out.println("请输入您的选择:");
switch (scanner.nextInt())
{
case 1:
System.out.println("1:D:\\ 2.C:\\");
System.out.println("请选择路径");
File file = new File("D:\\");
File file1 = new File("C:\\");
if (scanner.nextInt()==2)
{
show(file1);
}else {
show(file);
}
start();
break;
case 0:
System.out.println("谢谢使用");
System.exit(0);
break;
default:
System.out.println("输入错误,请重新输入");
start();
break;
}
}
private static void show(File file1) throws Exception {
if (file1.isDirectory())
{
File[] files = file1.listFiles();
for (File s:
files) {
System.out.println(s.getName());
}
System.out.println("1.继续打开 2.创建文件 3.创建文件夹 4.删除文件或文件夹 5.返回上一级 0.退出");
int i = scanner.nextInt();
if (i==1)
{
System.out.println("请输入文件名:");
String name = scanner.next();
for (File s:
files) {
if (name.equals(s.getName()))
{
show(s);
}
}
}else if (i==2)
{
System.out.println("请输入文件名(加后缀名如:.txt):");
String name = scanner.next();
File file = new File(file1+"/"+name);
file.createNewFile();
}else if (i==3)
{
System.out.println("请输入文件夹名:");
String name = scanner.next();
File file = new File(file1+"/"+name);
file.mkdir();
}else if (i==4)
{
System.out.println("请输入要删除的文件夹:");
String name = scanner.next();
File file6 = new File(file1+"/"+name);
deleteFile(file6);
System.out.println("删除成功");
}else if (i==0)
{
System.exit(0);
}else if (i==5)
{
String path = file1.getPath();
File parentFile = file1.getParentFile();
show(parentFile);
}
else {
System.out.println("输入错误");
}
}
}
private static void deleteFile(File file) {
if (file.exists())
{
if (file.isFile())
{
file.delete();
}else {
if (file.length()==0)
{
file.delete();
}
File[] files = file.listFiles();
for (File f:
files) {
if (f.isFile())
{
f.delete();
}else {
deleteFile(f);
}
}
file.delete();
}
}else {
System.out.println("不存在此文件");
}
}
}
IO流
缓冲流
缓冲流是用来优化字节或字符流的,
一般字符流比字节流读写要快,但字节流可读取写入除字符以外的数据
序列化流
序列化流可以读取或写入对象,但直接写入会造成乱码
转换流
转换流用来将字节流和字符流相互替换
一般读取JSON-url中的数据获取的流为字节流
一般编程会把字节流转换为字符流
加上缓冲流达到最佳效果
(文件字节输入流)FileInputStream
FileInputStream fileInputStream = new FileInputStream("字节流.txt");
byte[] bs = new byte[1024]; //用来存 读到的内容
int len = fileInputStream.read(bs); //len:读到的长度
String string = new String(bs,0,len);
System.out.println(string);
fileInputStream.close();
(文件字节输出流) FileOutputStream
FileOutputStream fileOutputStream = new FileOutputStream("字节流.txt");
fileOutputStream.write("你好".getBytes());
fileOutputStream.close();
(文件字符输入流)FileReader
FileReader fileReader = new FileReader("字符流.txt");
char[] cs = new char[1024]; //保存读到的内容
int len = fileReader.read(cs);
String string = new String(cs,0,len);
System.out.println(string);
fileReader.close();
(文件字符输出流)FileWriter
FileWriter fileWriter = new FileWriter("字符流.txt");
fileWriter.write("你好");
fileWriter.close();
【字节流复制(边读边写)】
//读
FileInputStream fileInputStream = new FileInputStream("D:\\install\\ideaIU-2020.1.3.exe");
//写
FileOutputStream fileOutputStream = new FileOutputStream("D:/aaa.exe");
byte[] bs = new byte[1024]; //存储读取到的内容
while (true) {
int len = fileInputStream.read(bs);
if (len==-1) {
break;
}
fileOutputStream.write(bs, 0, len);
}
fileInputStream.close();
fileOutputStream.close();
(缓冲输出字符流)BufferedWriter
FileWriter fileWriter = new FileWriter("缓冲字符流.txt");
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.write("缓冲字符流,你好");
bufferedWriter.close();
(缓冲输入字符流) BufferedReader
FileReader fileReader = new FileReader("缓冲字符流.txt");
BufferedReader bufferedReader = new BufferedReader(fileReader);
// char[] cs = new char[1024];
//
// int len = bufferedReader.read(cs);
//
// String string = new String(cs, 0, len);
// System.out.println(string);
//特有的方法 读一行
// String readLine = bufferedReader.readLine();
// System.out.println(readLine);
//一般使用方法
String s = "";
StringBuffer stringbuffer = new StringBuffer();
while((s = bufferedReader.readLine())!=null){
stringbuffer.append(s);
}
System.out.println(stringbuffer.toString());
bufferedReader.close();
(字节字符转换流)
//写
FileOutputStream fileOutputStream = new FileOutputStream("转换流.txt");
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream , "UTF-8");
outputStreamWriter.write("转换流你好");
outputStreamWriter.close();
//读
FileInputStream fileInputStream = new FileInputStream("转换流.txt");
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"UTF-8");
char[] cs = new char[1024];
int len = inputStreamReader.read(cs);
String string = new String(cs, 0, len);
System.out.println(string);
inputStreamReader.close();
(序列化输入流)ObjectInputStream
FileInputStream fileInputStream = new FileInputStream("序列化流.txt");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
Student readObject = (Student) objectInputStream.readObject();
System.out.println(readObject);
objectInputStream.close();
(序列化输出流)ObjectOutputStream
FileOutputStream fileOutputStream = new FileOutputStream("序列化流.txt");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
Student student = new Student("张三");
objectOutputStream.writeObject(student);
objectOutputStream.close();
网络编程
简单群聊系统
Server类
服务类,用于循环获取客户端的连接,并创建每个连接客户端伴生的服务子线程类
public class Server {
//list用于存储连接中的Socket(存储在线好友)一般用HashMap存储
//再使用list存储User类
private static ArrayList<Socket> list = new ArrayList<>();
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(37618);
System.out.println("等待连接中...........");
int i=0;
while (true)
{
Socket accept = serverSocket.accept();
list.add(accept);
System.out.println("连接成功");
new ServerThread(list,accept,i).start();
}
}
}
ServerThread类
public class ServerThread extends Thread{
private ArrayList<Socket> arrayList;
private Socket socket;
private int i;
public ServerThread(ArrayList<Socket> arrayList, Socket socket, int i) {
this.arrayList = arrayList;
this.socket = socket;
this.i = i;
}
@Override
public void run() {
while (true)
{
try {
InputStream inputStream = socket.getInputStream();
byte[] bs = new byte[1024];
int len = inputStream.read(bs);
String s = new String(bs, 0, len);
s=getId()+":"+s;
for (Socket s1:
arrayList) {
OutputStream outputStream = s1.getOutputStream();
outputStream.write(s.getBytes());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Client类
客户端类用来循环提示输入消息,并且发送至服务层
public class Client {
private static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",37618);
new ClientThread(socket).start(); //循环接收消息
System.out.println("请输入你要群发的消息:");
while (true)
{
String next = scanner.next();
OutputStream outputStream = socket.getOutputStream();
outputStream.write(next.getBytes());
}
}
}
ClientThread
客户端子线程类用来循环接收消息,并显示到控制台
public class ClientThread extends Thread{
private Socket socket;
public ClientThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
while (true){
try {
InputStream inputStream = socket.getInputStream();
byte[] bs = new byte[1024];
int len = inputStream.read(bs);
String s = new String(bs, 0, len);
System.out.println(s);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
-----------------------------------------
BasicsThree(java~Web)
数据库学习(MySQL)
最核心的为 对数据的增删改查
创建数据库
-- 创建数据库
CREATE DATABASE dataname;
使用数据库
-- 使用数据库
USE dataname;
创建数据表
-- 创建数据表 users
CREATE TABLE users(
-- 属性名 类型标识符(最大长度)
id INT PRIMARY KEY AUTO_INCREMENT,
-- 这里面的PRIMARY KEY是主键,不可重复,AUTO_INCREMEN是自增值
-- NOT NULL是不为空的意思
`name` VARCHAR(10) NOT NULL,
-- VARCHAR(10)的意思为字符串,最长10位
email VARCHAR(20),
`user` VARCHAR(20),
pwd VARCHAR(20),
pic VARCHAR(50)
);
查询数据
-- 查询所有
SELECT * FROM users;
-- 模糊查询 “山”
-- SELECT * FROM users WHERE `name` LIKE CONCAT('%','山','%');
-- 查询users表中 id=5的数据
-- SELECT * FROM hero WHERE id = 5;
增加数据
-- 往users数据表中添加数据
INSERT INTO users VALUES
(DEFAULT,'德','172655102@qq.com','wang','123','hai.png'),
(DEFAULT,'德','172655102@qq.com','wang','123','hai.png'),
(DEFAULT,'德','172655102@qq.com','wang','123','hai.png'),
(DEFAULT,'德','172655102@qq.com','wang','123','hai.png');
删除数据
-- 删除users表中所有数据
DELETE FROM users;
-- 删除users表中id=25的数据
DELETE FROM users WHERE id = 25;
更新数据(修改数据)
-- 修改users表中 id = 14的数据
UPDATE users SET
`name`='德',email='123',`user`='123',
pwd='123',pic='123.png' WHERE id = 14;
删除表
-- 删除users表
DROP TABLE users;
--------------------------------------
Web使用SSM框架简易连接MySQL
jar包需要使用,SSM整合jar包,Jackson.jar包,控制反转IOC整合包,连接数据库.jar包,MVC包
共需要17个jar包
!!!和上面的数据库不对应,此数据库需要新建
1.项目中新建resources文件夹 右键 Mark Directory as (Resources)
2.resources文件夹中创建mybatis.xml和spring.xml
Resources资源文件
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--扫描器,扫描cn.object包-->
<context:component-scan base-package="cn.object"/>
<!--声明mvc-->
<mvc:annotation-driven/>
<!--拼接WEB-INF中jsp中的jsp文件前缀和后缀--->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--将WEB-INF外的文件 调为可使用-->
<mvc:default-servlet-handler/>
<!--创建数据源并连接SQL-->
<bean class="com.alibaba.druid.pool.DruidDataSource" id="source">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/dataname"/>
<property name="username" value="root"/>
<property name="password" value="123"/>
</bean>
<!--创建工厂,并让工厂连接数据源-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="bean">
<property name="dataSource" ref="source"/>
<property name="configLocation" value="classpath:mybatis.xml"/>
</bean>
<!--使用工厂创建mapper-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.bw.dao"/>
<property name="sqlSessionFactoryBeanName" value="bean"/>
</bean>
</beans>
mybatis.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- dao层xml使用实体类简写-->
<typeAliases>
<package name="cn.bw.entity"/>
</typeAliases>
<!-- 实现分页-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
</configuration>
实体类
public class Person {
private Integer id;
private String title;
private String context;
private String lyt;
private String lid;
private String time;
@Override
public String toString() {
return "Person{" +
"id=" + id +
", title='" + title + '\'' +
", context='" + context + '\'' +
", lyt='" + lyt + '\'' +
", lid='" + lid + '\'' +
", time='" + time + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContext() {
return context;
}
public void setContext(String context) {
this.context = context;
}
public String getLyt() {
return lyt;
}
public void setLyt(String lyt) {
this.lyt = lyt;
}
public String getLid() {
return lid;
}
public void setLid(String lid) {
this.lid = lid;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public Person() {
}
public Person(Integer id, String title, String context, String lyt, String lid, String time) {
this.id = id;
this.title = title;
this.context = context;
this.lyt = lyt;
this.lid = lid;
this.time = time;
}
}
数据访问层(dao层)
创建一个接口类,和一个xml文件
接口类
public interface PersonDao {
//各种数据访问方法
List<Person> showAll(@Param("title") String title, @Param("sort") String sort, @Param("order") String order);
List<Person> showAlll();
Person getByid(Integer id);
boolean set(Person person);
boolean del(Integer id);
boolean add(Person person);
}
xml文件(mapper)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace指定对应的接口位置-->
<mapper namespace="cn.bw.dao.PersonDao">
<select id="showAll" resultType="person">
select *
from person where `title` like concat('%',#{title},'%')
order by ${sort} ${order}
</select>
<select id="getByid" resultType="person">
select * from person where id = #{id}
</select>
<update id="set">
update person
set title = #{title},context = #{context},lyt = #{lyt},lid = #{lid},`time` = #{time}
where id = #{id}
</update>
<delete id="del">
delete from person where id = #{id}
</delete>
<insert id="add">
insert into person (id,title,context,lyt,lid,`time`)
values (default,#{title},#{context},#{lyt},#{lid},#{time});
</insert>
<select id="showAlll" resultType="person">
select *
from person
</select>
</mapper>
业务逻辑层
@Service
public class MyService {
@Autowired
PersonDao personDao;
/**
* 分页排序获取集合
* @param title 标题搜索
* @param page 页数
* @param rows 条数
* @param sort 默认排序字段
* @param order 默认排序方法
* @return 每页的数据
*/
public PageData showAll(String title,Integer page,Integer rows,String sort,String order){
Page<Person> personPage = PageHelper.startPage(page, rows);
List<Person> people = personDao.showAll(title, sort, order);
PageData pageData = new PageData();
pageData.setTotal(personPage.getTotal());
pageData.setRows(people);
return pageData;
}
/**
* 获取person值
* @param id id
* @return person
*/
public Person getByid(Integer id){
Person byid = personDao.getByid(id);
return byid;
}
/**
* 设置person
* @param person 新的值
* @return 布尔
*/
public boolean set(Person person){
boolean set = personDao.set(person);
return set;
}
/**
* 删除
* @param id 删除数据的编号
* @return 布尔
*/
public boolean del(Integer id){
boolean del = personDao.del(id);
return del;
}
/**
* 添加
* @param person 添加的person
* @return 布尔
*/
public boolean add(Person person){
boolean add = personDao.add(person);
return add;
}
/**
* 所有数据
* @return
*/
public List<Person> showAlll(){
List<Person> people = personDao.showAlll();
return people;
}
}
分页展示实体类
public class PageData {
private Long total;
private List<Person> rows;
@Override
public String toString() {
return "PageData{" +
"total=" + total +
", rows=" + rows +
'}';
}
public Long getTotal() {
return total;
}
public void setTotal(Long total) {
this.total = total;
}
public List<Person> getRows() {
return rows;
}
public void setRows(List<Person> rows) {
this.rows = rows;
}
public PageData() {
}
public PageData(Long total, List<Person> rows) {
this.total = total;
this.rows = rows;
}
}
控制器类
@Controller
public class MyController {
@Autowired
MyService service;
/**
* 入口
* @return
*/
@GetMapping(value = {"","index.html"},produces = "text/html;charset=utf-8")
public String index(){
return "index";
}
/**
* 加载表格
*/
@ResponseBody
@PostMapping("index.do")
public PageData index_do(String title,Integer page,Integer rows,String sort,String order){
title = title==null?"":title;
PageData pageData = service.showAll(title, page, rows, sort, order);
return pageData;
}
/*
修改值
*/
@PostMapping("set.do")
public String set_do(Person person,Model model){
boolean set = service.set(person);
if (set){
model.addAttribute("msg","修改成功");
}else {
model.addAttribute("msg","修改失败");
}
return "set";
}
/*
获取值
*/
@GetMapping("set.html")
public String set(Integer id, Model model){
Person byid = service.getByid(id);
model.addAttribute("p",byid);
return "set";
}
/*
删除值
*/
@ResponseBody
@GetMapping("del.do")
public String del_do(Integer id){
boolean del = service.del(id);
return del?"true":"false";
}
/*
添加入口
*/
@GetMapping("add.html")
public String add(){
return "add";
}
/*
添加值
*/
@PostMapping("add.do")
public String add_do(Person person,Model model){
boolean add = service.add(person);
if (add){
model.addAttribute("msg","添加成功");
}else {
model.addAttribute("msg","添加失败");
}
return "add";
}
/*
生成数据
*/
@ResponseBody
@PostMapping(value = "print.do",produces = "text/html;charset=utf-8")
public String print(){
List<Person> people = service.showAlll();
String s = JSON.toJSONString(people);
return s;
}
}
WEB-INF内JSP文件(引用easyUI)
首页
<%--
Created by IntelliJ IDEA.
User: 怪歌
Date: 2021/4/14
Time: 13:34
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
<link rel="stylesheet" type="text/css" href="easyui/themes/material-teal/easyui.css">
<link rel="stylesheet" type="text/css" href="easyui/themes/icon.css">
<script type="text/javascript" src="easyui/jquery.min.js"></script>
<script type="text/javascript" src="easyui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="easyui/locale/easyui-lang-zh_CN.js"></script>
</head>
<body>
<a id="btn_bj" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-cut'">编辑</a>
<a id="btn_sc" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-cancel'">删除</a>
<a id="btn_zj" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-add'">增加</a>
<a id="btn_fz" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-filter'">复制</a>
<a id="btn_shc" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-print'">生成</a>
<table id="tab_main" class="easyui-datagrid" style="width:800px;height:450px"
data-options="url:'index.do',fitColumns:true,singleSelect:true,pagination:true,pageSize:10,pageList:[5,10,15,20],sortName:'id',sortOrder:'asc'">
<thead>
<tr>
<th data-options="field:'id',width:100,sortable:true">编码</th>
<th data-options="field:'title',width:100,sortable:true">标题</th>
<th data-options="field:'context',width:200,sortable:true">通知内容</th>
<th data-options="field:'lyt',width:100,sortable:true">旅游团</th>
<th data-options="field:'lid',width:100,sortable:true">线路编号</th>
<th data-options="field:'time',width:150,align:'right',sortable:true">发送时间</th>
</tr>
</thead>
</table>
<span id="text"></span>
</body>
<script type="text/javascript">
$(function () {
$("#btn_bj").click(function () {
var tab = $("#tab_main").datagrid("getSelected");
if (tab==null){
alert("请选择一条数据")
return false
}
window.location="set.html?id="+tab.id;
})
$("#btn_sc").click(function () {
var tab = $("#tab_main").datagrid("getSelected");
if (tab==null){
alert("请选择一条数据")
return false
}
$.ajax({
url:"del.do",
data:"id="+tab.id,
type:"get",
dataType:"text",
success:function (result) {
if (result=="true"){
$("#tab_main").datagrid("reload")
}else {
alert("删除失败")
}
}
})
})
$("#btn_zj").click(function () {
window.location="add.html";
})
$("#btn_fz").click(function () {
var tab = $("#tab_main").datagrid("getSelected");
if (tab==null){
alert("请选择一条数据")
return false
}
$.ajax({
url:"add.do",
data:"title="+tab.title+"&context="+tab.context+"&lyt="+tab.lyt+"&lid="+tab.lid+"&time="+tab.time,
type:"post",
dataType:"text",
success:function (result) {
$("#tab_main").datagrid("reload")
}
})
})
$("#btn_shc").click(function () {
$.ajax({
url:"print.do",
type:"post",
dataType:"text",
success:function (result) {
alert("giao")
$("#text").text(result)
}
})
})
})
</script>
</html>
添加页面(JS正则表达式验证)
<%--
Created by IntelliJ IDEA.
User: 怪歌
Date: 2021/4/14
Time: 15:23
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>增加</title>
</head>
<body>
<form action="add.do" id="myForm" method="post">
<table>
<tr>
<th>标题</th>
<td><input type="text" name="title" id="title" placeholder="请输入标题"></td>
</tr>
<tr>
<th>通知内容</th>
<td><input type="text" name="context" id="context" placeholder="请输入通知内容"></td>
</tr>
<tr>
<th>旅游团</th>
<td><input type="text" name="lyt" id="lyt" placeholder="请输入旅游团" ></td>
</tr>
<tr>
<th>路线编号</th>
<td><input type="text" name="lid" id="lid" placeholder="旅游团首字母和6位编号" ></td>
</tr>
<tr>
<th>发送时间</th>
<td><input type="text" id="time" name="time" placeholder="格式为****-**-** **:**"></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="增加">
<input type="reset" value="重置">
</td>
</tr>
</table>
</form>
<p>${msg}</p>
<a href="index.html"><button>返回首页</button></a>
</body>
<script type="text/javascript" src="easyui/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
$("#myForm").submit(function () {
var lyt = /^中青旅$|^国旅$|^携程$/;
var lid = /^((ZQL)|(GL)|(XC))\d{6}$/;
var time = /^\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}$/;
if (!lyt.test($("#lyt").val())){
alert("旅游团格式错误")
return false
}else if (!lid.test($("#lid").val())){
alert("路线编号格式错误")
return false
}else if (!time.test($("#time").val())){
alert("发送时间格式错误")
return false
}else {
return true
}
})
})
</script>
</html>
修改页面(JS正则表达式验证)
<%--
Created by IntelliJ IDEA.
User: 怪歌
Date: 2021/4/14
Time: 14:31
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>编辑</title>
</head>
<body>
<form action="set.do" id="myForm" method="post">
<table>
<input type="hidden" name="id" value="${p.id}">
<tr>
<th>标题</th>
<td><input type="text" name="title" id="title" placeholder="请输入标题" value="${p.title}"></td>
</tr>
<tr>
<th>通知内容</th>
<td><input type="text" name="context" id="context" placeholder="请输入通知内容" value="${p.context}"></td>
</tr>
<tr>
<th>旅游团</th>
<td><input type="text" name="lyt" id="lyt" placeholder="请输入旅游团" value="${p.lyt}"></td>
</tr>
<tr>
<th>路线编号</th>
<td><input type="text" name="lid" id="lid" placeholder="旅游团首字母和6位编号" value="${p.lid}"></td>
</tr>
<tr>
<th>发送时间</th>
<td><input type="text" id="time" name="time" placeholder="格式为****-**-** **:**" value="${p.time}"></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="修改">
<input type="reset" value="重置">
</td>
</tr>
</table>
</form>
<p>${msg}</p>
<a href="index.html"><button>返回首页</button></a>
</body>
<script type="text/javascript" src="easyui/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
$("#myForm").submit(function () {
var lyt = /^中青旅$|^国旅$|^携程$/;
var lid = /^((ZQL)|(GL)|(XC))\d{6}$/;
var time = /^\d{4}-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}$/;
if (!lyt.test($("#lyt").val())){
alert("旅游团格式错误")
return false
}else if (!lid.test($("#lid").val())){
alert("路线编号格式错误")
return false
}else if (!time.test($("#time").val())){
alert("发送时间格式错误")
return false
}else {
return true
}
})
})
</script>
</html>
-----------------------------------------
PhaseOne (Android)
View
所有控件的父类,中文翻译为视图
有着基础属性,例如background等
RadioGroup
用于包裹RadioButton的控件
radioButton在选择时,需要实现单选,这是就用到了RadioGroup
RadioButton
单选按钮 一般需要RadioGroup嵌套
android:text=“设置单选按钮后的文字”
style获取Android studio 自带图标
CheckBox
多选框控件,可以不用RadioGroup嵌套,
其余属性和RadioButton类似
Button
继承于TextView
按钮控件 android:text=“用于设置文字”
android:onClick=“设置点击事件方法名”
写完后(alt+enter)选择create会在java中创建点击事件
TextView
继承于View
按钮控件 android:text=“用于设置文字”,可设置点击事件,
textSize用于设置字体大小,textColor设置颜色等
ImageView
继承于View
显示图片控件,android:src=“设置图片位置”
小技巧:将宽和高其一设置为固定值,另一个设置为wrap_content可防止图片扭曲
ImageButton
继承于ImageView
用法与ImageView类似
ScrollView
可进行垂直滚动的控件,但其中仅可设置一个布局控件,
当内容溢出 即可垂直滑动
HorizontalScrollView
顾名知义,水平滚动控件,简介同上
EditText
继承于TextView
输入文本框控件,android:hint=“可用于设置提示文本”
ListView
可以以列表形式展现的控件,需要设置适配器,或者使用静态item,仅可使用一列
ListView布局
Activity代码
package com.example.csdn;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
//声明listView
private ListView listView;
//声明数据源
private List<String> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
//给listView设置布局
MyBaseAdapter myBaseAdapter = new MyBaseAdapter();
listView.setAdapter(myBaseAdapter);
}
//初始化listView和数据源
private void init() {
listView = findViewById(R.id.main_lv);
list = new ArrayList<>();
//给list添加几个字符串(随意添加)
list.add("坐下");
list.add("坐上我的副驾");
list.add("你打扮的还是一样");
list.add("很热辣");
list.add("我有时太忙");
list.add("忙着吧势力扩大");
list.add("但只要你需要我");
list.add("能把星星射下");
}
private class MyBaseAdapter extends BaseAdapter{
//这里一定要添加数据源的长度,不然会报空指针
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
HolderView holderView = new HolderView();
if (convertView==null){
//convertView是复用视图 如果它为空就要给他赋上值
//,这里的R.layout.item是listView每条的布局
//可以使用图文混排 需要布局加一个ImageView holderView中加一个ImageView
//并使用Glide或Picasso
convertView = LayoutInflater.from(MainActivity.this).inflate(R.layout.item,null);
//给holderView赋值数据
holderView.textView = convertView.findViewById(R.id.item_text);
//设置附属
convertView.setTag(holderView);
}else {
//如果复用视图有数据 就要给holderView赋值
holderView = (HolderView) convertView.getTag();
}
//设置显示数据
// 用于图片显示 Picasso.with(MainActivity.this).load("http://img.png").into(holderView.imageView);
//Glide.with(MainActivity.this).load("http://img.png").into(holderView.imageView);
holderView.textView.setText(list.get(position));
return convertView;
}
//利用holderView内部类 暂时存储每条数据 达到优化的效果
private class HolderView{
TextView textView;
}
}
}
效果
如果item够多而且超出屏幕 即可以进行垂直滑动 显示滚动条
GridView
可以使用多列的ListView
-----------------------------------------
One(Android)
Menu
系统Menu
系统menu会在header的右侧显示最小化菜单栏.
必要因素onCreateOptionMenu创建时
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.item,menu);
return super.onCreateOptionsMenu(menu);
}
必要因素onOptionsItemSelected点击时
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.option_one:
break;
case R.id.option_two:
break;
case R.id.option_three:
break;
}
return super.onOptionsItemSelected(item);
}
上下文Menu
ContextMenu需要绑定控件,并长按绑定空控件显示ContextMenu
必要因素onCreateContextMenu
//加载布局
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
getMenuInflater().inflate(R.menu.menu2, menu);
super.onCreateContextMenu(menu, v, menuInfo);
}
必要因素onContextItemSelected
//监听事件
@Override
public boolean onContextItemSelected(@NonNull MenuItem item) {
int itemId = item.getItemId();
switch (itemId) {
case R.id.hong:
tv1.setTextColor(Color.parseColor("#ff0000"));
break;
case R.id.lv:
break;
case R.id.lan:
break;
}
return super.onContextItemSelected(item);
}
自定义Menu(PopupMenu)
对比ContextMenu长按绑定控件显示来说,自定义Menu只需要单击绑定控件即可显示
使用比ContextMenu要灵活
public void tv1(View view) {
PopupMenu popupMenu = new PopupMenu(this,view);
popupMenu.inflate(R.menu.menu2);
popupMenu.show();
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
int itemId = item.getItemId();
switch (itemId) {
case R.id.hong:
tv2.setTextColor(Color.parseColor("#ff0000"));
break;
case R.id.lv:
tv2.setTextColor(Color.parseColor("#00ff00"));
break;
case R.id.lan:
tv2.setTextColor(Color.parseColor("#0000ff"));
break;
}
return false;
}
});
}
对话框builder
弹出对话框
普通对话框
普通对话框可以编写Message,编写icon(图标),编写title等
/**
* 普通对话框
* @param view
*/
public void btn1(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setIcon(R.drawable.icon);
builder.setTitle("删除");
builder.setMessage("您确定要删除此消息");
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "确定", Toast.LENGTH_SHORT).show();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "取消", Toast.LENGTH_SHORT).show();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
单选对话框
顾名知义,单选对话框就是有着radio控件的对话框
/**
* 单选对话框
* @param view
*/
public void btn2(View view) {
final int[] click = new int[1];
final String[] data = new String[]{"足球","篮球","唱歌","台球"};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setIcon(R.drawable.icon);
builder.setTitle("单选");
builder.setSingleChoiceItems(data, 0, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
click[0] = which;
}
});
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, data[click[0]].toString(), Toast.LENGTH_SHORT).show();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
多选对话框
//多选对话框
public void tion3(View view) {
//构建者
AlertDialog.Builder builder = new AlertDialog.Builder(this);
//设置属性
builder.setIcon(R.drawable.ic_launcher_background);
builder.setTitle("她们");
final String[] strings = {"小晓", "小齐", "小琳", "晓丽"};
boolean[] booleans = {true,true,false,false};
//参数 Sing数组 boolean数组 监听事件
builder.setMultiChoiceItems(strings, booleans, new DialogInterface.OnMultiChoiceClickListener() {//多选内容
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
}
});
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "确定", Toast.LENGTH_SHORT).show();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "取消", Toast.LENGTH_SHORT).show();
}
});
//创建
AlertDialog alertDialog = builder.create();
//显示
alertDialog.show();
}
进度条对话框
进度条对话框显示进度 一般用于加载数据中使用,这里仅仅是模拟 注意分辨
/**
* 进度条对话框
* @param view
*/
public void btn3(View view) {
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMax(100);
progressDialog.setTitle("进度条对话框");
progressDialog.setIcon(R.drawable.icon);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.show();
//Timer用于加载进度条 类似于一种循环
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
int i = 0;
@Override
public void run() {
if (i==progressDialog.getMax()){
timer.cancel();
progressDialog.dismiss();
}
progressDialog.setProgress(i+=1);
}
},0,50);
}
自定义对话框
自定义对话框类似于普通builder,只不过将原先的setMessage改为setView
/**
* 自定义对话框
* @param view
*/
public void btn4(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("自定义对话框");
builder.setIcon(R.drawable.icon);
View inflate = LayoutInflater.from(MainActivity.this).inflate(R.layout.menu, null);
builder.setView(inflate);
final AlertDialog alertDialog = builder.create();
alertDialog.show();
inflate.findViewById(R.id.btn_yes).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "确定", Toast.LENGTH_SHORT).show();
alertDialog.dismiss();
}
});
inflate.findViewById(R.id.btn_no).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "取消", Toast.LENGTH_SHORT).show();
alertDialog.dismiss();
}
});
}
自定义弹出窗口(PopupWindow)
PopupWindow使用比PopupMenu更加灵活,可以设置弹出位置
public void btn1(View view) {
PopupWindow popupWindow = new PopupWindow();
//宽高必须要有
popupWindow.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
popupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
//点击外部取消
popupWindow.setOutsideTouchable(true);
//遮罩效果
//WindowManager.LayoutParams attributes = getWindow().getAttributes();
//attributes.alpha = 0.5f;
//getWindow().setAttributes(attributes);
//恢复透明度
//popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
// @Override
// public void onDismiss() {
// WindowManager.LayoutParams attributes = getWindow().getAttributes();
// attributes.alpha = 1.0f;
// getWindow().setAttributes(attributes);
// }
//});
//加载布局
View inflate = LayoutInflater.from(this).inflate(R.layout.popu, null);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
popupWindow.setContentView(inflate);//设置布局
View activity_main = LayoutInflater.from(this).inflate(R.layout.activity_main, null);
//在activity_main布局的最下边
popupWindow.showAtLocation(activity_main, Gravity.BOTTOM,0,0);
//显示到某个控件的下边
//popupWindow.showAsDropDown(add);
//设置入场动画
//popupWindow.setAnimationStyle(R.style.popuoo);
//控件里的点击事件
inflate.findViewById(R.id.sao).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "hhhhhhh", Toast.LENGTH_SHORT).show();
}
});
}
简化版
public void btn1(View view) {
PopupMenu popupMenu = new PopupMenu(this,view);
PopupWindow popupWindow = new PopupWindow();
popupWindow.setWidth(300);
popupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
popupWindow.setOutsideTouchable(true);
View inflate1 = LayoutInflater.from(MainActivity.this).inflate(R.layout.menu, null);
popupWindow.setContentView(inflate1);
View inflate = LayoutInflater.from(MainActivity.this).inflate(R.layout.activity_main, null);
// popupWindow.showAtLocation(inflate, Gravity.RIGHT,0,-500);
RelativeLayout relativeLayout = findViewById(R.id.title);
popupWindow.showAsDropDown(relativeLayout,9999,0);
}
通知
notification在手机header显示
public void btn1(View view) {
//构造者
Notification.Builder builder = new Notification.Builder(this);
//小图标(必须设置,不然报错)
builder.setSmallIcon(R.drawable.ic_launcher_background);
//加载布局
RemoteViews remoteViews = new RemoteViews(getPackageName(),R.layout.notification);
//设置文字
//remoteViews.setTextViewText(R.id.text_id,"设置文字");
//设置图片
//remoteViews.setImageViewResource(R.id.img_id,R.drawable.ic_launcher_background);
//设置自定义布局
builder.setCustomContentView(remoteViews);
// Big
//builder.setCustomBigContentView(remoteViews);
//发通知
NotificationManager systemService = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
systemService.notify(1,builder.build());
}
Fragment(UI片段)
fragment配合RadioGroup和RadioButton可以实现 购物软件下方导航
创建Fragment
模拟购物界面
布局
<FrameLayout 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=".BlankFragment1">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="111111111111111111111111111111"/>
</FrameLayout>
Fragment类
public class BlankFragment1 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_blank_fragment1, container, false);
}
}
MainActivity类
activity是Android组件中最基本也是最为常见用的四大组件之一。Android四大组件有Activity,Service服务,Content Provider内容提供,BroadcastReceiver广播接收器。
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
//利用switch来切换不同的UI片段
switch (checkedId){
case R.id.index:
//管理者对象(片段管理器)
FragmentManager manager = getSupportFragmentManager();
//开启事务
FragmentTransaction fragmentTransaction = manager.beginTransaction();
//添加fragment
BlankFragment1 index = new BlankFragment1();
//替换片段
//其中R.id.ll是Main布局中的片段容器,
//index是Fragment
//另外add是添加,replace是替换
//fragmentTransaction.add(R.id.ll,index);
fragmentTransaction.replace(R.id.ll, index);
//提交事务
fragmentTransaction.commit();
break;
}
}
});
ViewPager (横向滑动Fragment)
主要思路
数据源
适配器
ViewPager适配
主要思路 --> 数据源 --> 适配器 --> ViewPager适配 |
在activity_main.xml中搭建框架 |
新建多个Fragment(自己想建几个建几个) |
新建Fragment适配器 继承FragmentAdapter → 把数据源传过来 |
在MainActivity中 |
初始化ViewPager (findbyid) |
新建数据源(List< Fragment> list = new ArrayList<>();) |
实例化适配器 |
适配到ViewPager(viewPager.setAdapter(适配器对象名)) |
举个栗子,搞一个可以实现左右滑动的连锁Fragment
框架布局 activity_main.xml
上半身的ViewPager是用来在Java类中插入Fragment的 |
使用单选框 去除按钮 并设置插入图片(android:drawableTop) |
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!-- 显示fragment 的控件 (ViewPager)-->
<androidx.viewpager.widget.ViewPager
android:id="@+id/main_vp"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="9"></androidx.viewpager.widget.ViewPager>
<!-- 单选框-->
<RadioGroup
android:id="@+id/main_radioGroup"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="0dp"
android:layout_weight="1.4">
<RadioButton
android:gravity="center"
android:button="@null"
android:id="@+id/index"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:drawableTop="@drawable/index"
android:checked="true"
android:text="首页"></RadioButton>
<RadioButton
android:drawableTop="@drawable/person"
android:gravity="center"
android:button="@null"
android:id="@+id/person"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="联系人"></RadioButton>
<RadioButton
android:drawableTop="@drawable/find"
android:gravity="center"
android:button="@null"
android:id="@+id/find"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="发现"></RadioButton>
<RadioButton
android:drawableTop="@drawable/mine"
android:gravity="center"
android:button="@null"
android:id="@+id/mine"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="我的"></RadioButton>
</RadioGroup>
</LinearLayout>
布局大概的效果是这样的 ↓↓↓↓↓↓↓↓↓↓
fragment布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:gravity="center"
tools:context=".BlankFragment1">
<!--随便加点什么都可,主要跟着自己思路走-->
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/png1"></ImageView>
</LinearLayout>
Fragment类
把该删的删掉就好,别的不用管
package com.example.viewpaper_210524;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class BlankFragment1 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View inflate = inflater.inflate(R.layout.fragment_blank_fragment1, container, false);
return inflate;
}
}
FragmentAdapter类 (Fragment适配器)
package com.example.viewpaper_210524;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import java.util.ArrayList;
public class FragmentAdapter extends FragmentPagerAdapter {
//将数据源传过来
private ArrayList<Fragment> fragments;
public FragmentAdapter(FragmentManager fm, @NonNull ArrayList<Fragment> list) {
super(fm);
this.fragments = list;
}
@Override
public Fragment getItem(int position) {
return fragments.get(position);
}
@Override
public int getCount() {
return fragments.size();
}
}
MainActivity类
package com.example.viewpaper_210524;
import android.os.Bundle;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.viewpager.widget.ViewPager;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ViewPager mainVp;
private RadioGroup mainRadioGroup;
private RadioButton index;
private RadioButton person;
private RadioButton find;
private RadioButton mine;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportActionBar().hide();
//初始化
initView();
//新建数据源
List<Fragment> list = new ArrayList<>();
list.add(new BlankFragment1());
list.add(new BlankFragment2());
list.add(new BlankFragment3());
list.add(new BlankFragment1());
//初始化Fragment适配器
FragmentAdapter fragmentAdapter = new FragmentAdapter(getSupportFragmentManager(),(ArrayList<Fragment>) list);
//适配到Viewpager上
mainVp.setAdapter(fragmentAdapter);
/**
* 点击导航RadioButton时 切换viewPager当前视图
*/
mainRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.index:
mainVp.setCurrentItem(0);
break;
case R.id.person:
mainVp.setCurrentItem(1);
break;
case R.id.find:
mainVp.setCurrentItem(2);
break;
case R.id.mine:
mainVp.setCurrentItem(3);
break;
}
}
});
/**
* 设置翻阅viewPaper时,切换选中radioButton导航
*/
mainVp.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
switch (position){
case 0:
mainRadioGroup.check(R.id.index);
break;
case 1:
mainRadioGroup.check(R.id.person);
break;
case 2:
mainRadioGroup.check(R.id.find);
break;
case 3:
mainRadioGroup.check(R.id.mine);
break;
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
private void initView() {
mainVp = (ViewPager) findViewById(R.id.main_vp);
mainRadioGroup = (RadioGroup) findViewById(R.id.main_radioGroup);
index = (RadioButton) findViewById(R.id.index);
person = (RadioButton) findViewById(R.id.person);
find = (RadioButton) findViewById(R.id.find);
mine = (RadioButton) findViewById(R.id.mine);
}
}
效果如下 ↓↓↓↓↓
引用TabLayout
和ViewPager配合使用效果 会很舒服
如果你的Android Studio没有自带
<com.google.android.material.tabs.TabLayout/>
这样的控件,那么就要引入一下的一个需求
implementation ‘com.android.support:design:30.0.0’
导入后 同步(sync Now)
Fragment类就不写了,和上面的一样
主要思路
和上面相似
数据源
适配器
ViewPager适配
设置Tabs
主要思路 --> 数据源 --> 适配器 --> ViewPager适配 --> 设置tab |
在activity_main.xml中搭建框架 |
新建多个Fragment(自己想建几个建几个) |
新建Fragment适配器 继承FragmentAdapter → 把数据源传过来 |
在MainActivity中 |
初始化ViewPager (findbyid) |
新建数据源(List< Fragment> list = new ArrayList<>();) |
(List< String> list = new ArrayList<>();) |
实例化适配器 |
适配到ViewPager(viewPager.setAdapter(适配器对象名)) |
设置tab到ViewPager上 |
activity_main.xml 框架布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".Main3Activity">
<!-- 这个是导航栏,也就是TabLayout-->
<com.google.android.material.tabs.TabLayout
android:id="@+id/main3_tabs"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"></com.google.android.material.tabs.TabLayout>
<!-- 这个是ViewPager主体-->
<androidx.viewpager.widget.ViewPager
android:id="@+id/main3_pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="9"></androidx.viewpager.widget.ViewPager>
</LinearLayout>
FragmentAdapter类(Fragment适配器类)
package com.example.viewpaper_210524;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import java.util.ArrayList;
public class FragmentAdapter extends FragmentPagerAdapter {
//数据源
private ArrayList<Fragment> fragments;
private ArrayList<String> strings = null;
//这个构造方法是用于适配不使用TabLayout的ViewPager(滑动视图)的
public FragmentAdapter(FragmentManager fm, @NonNull ArrayList<Fragment> list) {
super(fm);
this.fragments = list;
}
//这个是这次的主角,主要用它来传数据源
public FragmentAdapter(FragmentManager fm, @NonNull ArrayList<Fragment> list, ArrayList<String> str) {
super(fm);
this.fragments = list;
this.strings = str;
}
@Override
public Fragment getItem(int position) {
return fragments.get(position);
}
@Override
public int getCount() {
return fragments.size();
}
/**
* !!!!!!!!!!!!!!!!!!!!
* 注意这边多了一个strings数据源的索引
*/
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return strings.get(position);
}
}
MainActivity类
package com.example.viewpaper_210524;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.viewpager.widget.ViewPager;
import com.google.android.material.tabs.TabLayout;
import java.util.ArrayList;
public class Main3Activity extends AppCompatActivity {
private TabLayout main3Tabs;
private ViewPager main3Pager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
getSupportActionBar().hide();
//初始化
initView();
//UI片段集合
ArrayList<Fragment> list = new ArrayList<>();
list.add(new BlankFragment1());
list.add(new BlankFragment2());
list.add(new BlankFragment3());
//字符串集合(用于适配导航)
ArrayList<String> strs = new ArrayList<>();
strs.add("星河滚烫");
strs.add("人间理想");
strs.add("你看");
//实例化适配器
FragmentAdapter fragmentAdapter = new FragmentAdapter(getSupportFragmentManager(),list,strs);
//将适配器适配到PagerView上
main3Pager.setAdapter(fragmentAdapter);
//将导航和滑动视图产生关联
main3Tabs.setupWithViewPager(main3Pager);
}
private void initView() {
main3Tabs = (TabLayout) findViewById(R.id.main3_tabs);
main3Pager = (ViewPager) findViewById(R.id.main3_pager);
}
}
效果如下 ↓↓↓↓↓
Android轮播图(banner)
需要导入需求
implementation ‘com.youth.banner:banner:1.4.10’
布局文件
<com.youth.banner.Banner
android:id="@+id/child_tou_banner"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"></com.youth.banner.Banner>
java类中
ArrayList<Integer> imgs = new ArrayList<>();
imgs.add(R.drawable.png1);
imgs.add(R.drawable.png2);
imgs.add(R.drawable.png3);
ArrayList<String> strings = new ArrayList<>();
strings.add("png1");
strings.add("png2");
strings.add("png3");
childTouBanner.setImages(imgs);
childTouBanner.setBannerTitles(strings);
childTouBanner.setBannerStyle(BannerConfig.CIRCLE_INDICATOR_TITLE_INSIDE);
childTouBanner.setImageLoader(new ImageLoader() {
@Override
public void displayImage(Context context, Object path, ImageView imageView) {
imageView.setImageResource((Integer) path);
}
});
//设置轮播时间
childTouBanner.setDelayTime(2000);
childTouBanner.start();
效果如下 ↓↓↓↓
SharedPreferences
简称Sp,轻量级的数据存储方式,不可存入大型数据,会影响应用效率
一般存储到(/data/data/应用程序包名/shared_prefs)路径中
布局文件(写入两个供测试按钮即可)
<Button
android:id="@+id/write"
android:text="写数据"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></Button>
<Button
android:id="@+id/read"
android:text="读数据"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></Button>
MainActivity文件
很简单的存储方法,有时用于存储用户账号和密码(记住密码选项)
private Button write;
private Button read;
//往Android SD存储数据 和 读取数据(不可写入大型文件,否则会大大影响用户体验)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
//写入数据
write.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//创建SharedPreference对象 参数(文件名,模式) 当前模式为数据只能被本应用程序读写(MODE_PRIVATE)
SharedPreferences preferences = getSharedPreferences("text",MODE_PRIVATE);
//获取编译对象
SharedPreferences.Editor edit = preferences.edit();
//以键值对方式写入
edit.putString("username","Guai");
edit.putInt("age",19);
edit.putString("sex","男");
edit.putLong("id",172655102);
//执行(提交数据)
edit.commit();
}
});
//读取数据
read.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//创建SharedPreference对象 参数(文件名,模式) 当前模式为数据只能被本应用程序读写(MODE_PRIVATE)
SharedPreferences preferences = getSharedPreferences("text",MODE_PRIVATE);
//使用preference对象获取数据 参数(键名称,默认值)
String username = preferences.getString("username", "");
//非空判断 并Toast值
if (username!=""){
Toast.makeText(MainActivity.this, username, Toast.LENGTH_SHORT).show();
}
}
});
}
private void initView() {
write = (Button) findViewById(R.id.write);
read = (Button) findViewById(R.id.read);
}
读写SD卡
一般使用InputStream方法,边读边写 类似IO中的复制,
可以用于下载图片,或其他,
路径在(/storage/emulated/0/)
MainActivity类中
public class MainActivity extends AppCompatActivity {
private Button mainWriteBtn;
private Button mainReadBtn;
private Button mainDownBtn;
private ImageView img;
/**
* 允许权限与否后 将执行的操作
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == 101 && grantResults[0] == 0) {
Toast.makeText(this, "允许", Toast.LENGTH_SHORT).show();
} else {
finish();
}
}
/**
* 创建时
* @param savedInstanceState
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化
initView();
//危险权限需要用户同意,以下操作是允许权限与否的弹框
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE}, 101);
/**
* 往SD卡内写文件
*/
mainWriteBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
FileWriter fileWriter = new FileWriter("/storage/emulated/0/" + "123.txt");
BufferedWriter writer = new BufferedWriter(fileWriter);
writer.write("奥利给,兄弟们\n");
writer.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
/**
* 读SD卡内的文件
*/
mainReadBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
FileReader fileReader = new FileReader("/storage/emulated/0/" + "123.txt");
BufferedReader bufferedReader = new BufferedReader(fileReader);
String s = "";
StringBuffer strs = new StringBuffer();
while ((s = bufferedReader.readLine()) != null) {
strs.append(s);
}
String string = strs.toString();
Toast.makeText(MainActivity.this, string, Toast.LENGTH_SHORT).show();
bufferedReader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
/**
* 点击下载图片后的操作
*/
mainDownBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//异步刷新(获取百度图标)
new MyAsyncTask().execute("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png");
}
});
}
public class MyAsyncTask extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... strings) {
try {
//连接url
URL url = new URL(strings[0]);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//实例化输入流
InputStream inputStream = urlConnection.getInputStream();
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
//实例化输出流
FileOutputStream fileOutputStream = new FileOutputStream("/storage/emulated/0/" + "baidu.png");
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
//下面就是重要操作了
byte[] bytes = new byte[1024]; //new一个字节临时存储器
int len = 0; //这是每次读的长度
while ((len = bufferedInputStream.read(bytes)) != -1) { //如果没读完 就一直读
bufferedOutputStream.write(bytes, 0, len); //一边读一边写
}
bufferedInputStream.close();
bufferedOutputStream.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String s) {
Bitmap bitmap = BitmapFactory.decodeFile("/storage/emulated/0/" + "baidu.png");
img.setImageBitmap(bitmap); //设置img的图片 为baidu图标
}
}
private void initView() {
mainWriteBtn = (Button) findViewById(R.id.main_write_btn);
mainReadBtn = (Button) findViewById(R.id.main_read_btn);
mainDownBtn = (Button) findViewById(R.id.main_down_btn);
img = (ImageView) findViewById(R.id.img);
}
}
对Android数据库的增删改查
语句依旧是SQL语句
Android数据库一般在(/data/data/应用程序包名/databases)
mainActivity类中
public class MainActivity extends AppCompatActivity {
private SQLiteDatabase db;
private String toastPerson;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
PersonSQL personSQL = new PersonSQL(this,"day.09.db",null,1);
db = personSQL.getReadableDatabase();
}
public void add(View view) {
// 方式一
// db.execSQL("insert into person values(null,?,?)",new Object[]{"星星",18});
// 方式二
ContentValues contentValues = new ContentValues();
contentValues.put("name","冯书行");
contentValues.put("age","666");
db.insert("person",null,contentValues);
}
public void del(View view) {
// 方式一
// db.execSQL("delete from person where id = ?",new Object[]{"1"});
// 方式二
db.delete("person","id = ?",new String[]{"4"});
}
public void set(View view) {
// 方式一
// db.execSQL("update person set name = ?,age = ? where id = ?",new Object[]{"月亮","15","5"});
// 方式二
ContentValues contentValues = new ContentValues();
contentValues.put("name","王益德");
db.update("person",contentValues,"id = ?",new String[]{"2"});
}
public void query(View view) {
// 方式一
StringBuffer stringBuffer = new StringBuffer();
// Cursor cursor = db.rawQuery("select * from person",null);
// while (cursor.moveToNext()){
// String id = cursor.getString(cursor.getColumnIndex("id"));
// String name = cursor.getString(cursor.getColumnIndex("name"));
// String age = cursor.getString(cursor.getColumnIndex("age"));
// ShowPerson showPerson = new ShowPerson(id, name, age);
//
//
// }
//
// Toast.makeText(this, toastPerson, Toast.LENGTH_SHORT).show();
// 方式二
Cursor person = db.query("person", null, null, null, null, null, null);
while (person.moveToNext()){
String id = person.getString(person.getColumnIndex("id"));
String name = person.getString(person.getColumnIndex("name"));
String age = person.getString(person.getColumnIndex("age"));
ShowPerson showPerson = new ShowPerson(id,name,age);
stringBuffer.append(showPerson.toString());
}
Toast.makeText(this, toastPerson, Toast.LENGTH_SHORT).show();
stringBuffer.delete(0,stringBuffer.length());
}
}
SQLite类中
public class PersonSQL extends SQLiteOpenHelper {
//构造方法
public PersonSQL(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
//创建数据库的时候执行,只会执行一次
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table person" +
"(id integer primary key autoincrement," +
"name varchar(10)," +
"age int(5))");
}
//更新数据库的时候执行
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
内容提供者,内容解析者 Content Provider
Content Provider是Android的四大组件之一。Android四大组件有Activity,Service服务,Content Provider内容提供,BroadcastReceiver广播接收器。
实现APP之间数据共享,可以获取手机联系人,本地音乐等的资源。也可以通过获取权限,让别的app对自身app的数据表进行增删改查。
ContentProvider(内容提供者)
SQLite类
public class FoodSQLite extends SQLiteOpenHelper {
public FoodSQLite(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table foods(" +
"id integer primary key autoincrement," +
"title varchar(10) not null)");
db.execSQL("insert into foods values(null,?)",new Object[]{"星星还是那么靓"});
db.execSQL("insert into foods values(null,?)",new Object[]{"星星"});
db.execSQL("insert into foods values(null,?)",new Object[]{"星星123"});
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
MainActivity类
public class MainActivity extends AppCompatActivity {
private SQLiteDatabase db;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
//grantResults中 0表示同意 -1表示不同意
if (requestCode==100&&grantResults[0]==0){
}else {
finish();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取重要权限
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE},100);
//实例化SQLite类
FoodSQLite foodSQLite = new FoodSQLite(MainActivity.this,"foods",null,1);
//获取写入数据库对象
db = foodSQLite.getReadableDatabase();
}
}
创建ContentProvider类
这次uri填写“com.exeobject”
ContentProvider类
!!!这里仅仅是展示一个内容提供者类,提示参数设置。非本次使用的类
public class PersonContentProvider extends ContentProvider {
private SQLiteDatabase db;
public PersonContentProvider() {
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int person = db.delete("person", selection, selectionArgs);
return person;
}
@Override
public String getType(Uri uri) {
// TODO: Implement this to handle requests for the MIME type of the data
// at the given URI.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public Uri insert(Uri uri, ContentValues values) {
db.insert("person", null, values);
return uri;
}
@Override
public boolean onCreate() {
PersonSQL personSQL = new PersonSQL(getContext(),"app2.db",null,1);
db = personSQL.getReadableDatabase();
return db==null?false:true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
Cursor person = db.query("person", projection, selection, selectionArgs, null, null, sortOrder);
return person;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int person = db.update("person", values, selection, selectionArgs);
return person;
}
}
ContentResolver(内容解析者)
MainActivity类中
public class MainActivity extends AppCompatActivity {
private ContentResolver contentResolver;
private Uri uri;
private Button mainAdd;
private Button mainDel;
private Button mainSet;
private Button mainQuery;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//实例化
initView();
//获取内容解析对象
contentResolver = getContentResolver();
//uri要和内容提供者对应
uri = Uri.parse("content://com.exeobject");
//创建stringBuffer 用于拼接数据
final StringBuffer stringBuffer = new StringBuffer();
//按钮点击事件
mainQuery.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//内容解析对象.查询 uri一定要对应好
Cursor query = contentResolver.query(uri, null, null, null, null);
while (query.moveToNext()){
//获取表内数据
String id = query.getString(query.getColumnIndex("id"));
String title = query.getString(query.getColumnIndex("title"));
//拼接数据
stringBuffer.append(id+"---"+title+"\n");
}
//Toast一下
Toast.makeText(MainActivity.this, stringBuffer.toString(), Toast.LENGTH_SHORT).show();
//stringBuffer清空
stringBuffer.delete(0,stringBuffer.length());
}
});
}
private void initView() {
mainAdd = (Button) findViewById(R.id.main_add);
mainDel = (Button) findViewById(R.id.main_del);
mainSet = (Button) findViewById(R.id.main_set);
mainQuery = (Button) findViewById(R.id.main_query);
}
}
获取手机联系人和本地音乐(音乐播放器、电话簿)
获取手机联系人和音乐也是使用内容解析者ContentResolver的query(查询)
使用两个Activity 一个用来获取联系人 另一个用来获取本地音乐
这里我们使用listView适配上每首音乐,联系人也一样
音乐点击播放
联系人长按呼叫
创建实体类
联系人实体类(Person)
public class Person {
private String name,phone;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Person() {
}
public Person(String name, String phone) {
this.name = name;
this.phone = phone;
}
}
音乐实体类(Music)
public class Music {
private String title,artist,duration,data,size,album_id;
@Override
public String toString() {
return "Music{" +
"title='" + title + '\'' +
", artist='" + artist + '\'' +
", duration='" + duration + '\'' +
", data='" + data + '\'' +
", size='" + size + '\'' +
", album_id='" + album_id + '\'' +
'}';
}
public Music() {
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public String getDuration() {
return duration;
}
public void setDuration(String duration) {
this.duration = duration;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
public String getAlbum_id() {
return album_id;
}
public void setAlbum_id(String album_id) {
this.album_id = album_id;
}
public Music(String title, String artist, String duration, String data, String size, String album_id) {
this.title = title;
this.artist = artist;
this.duration = duration;
this.data = data;
this.size = size;
this.album_id = album_id;
}
}
创建适配器
音乐适配器(MusicAdapter)
public class MusicAdapter extends BaseAdapter {
private Context context;
private ArrayList<Music> list;
public MusicAdapter(Context context, ArrayList<Music> list) {
this.context = context;
this.list = list;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int i) {
return list.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder = new ViewHolder();
if (view==null){
view = LayoutInflater.from(context).inflate(R.layout.music_item,null);
viewHolder.artist = view.findViewById(R.id.artist);
viewHolder.img = view.findViewById(R.id.img);
viewHolder.title = view.findViewById(R.id.title);
viewHolder.duration = view.findViewById(R.id.duration);
view.setTag(viewHolder);
}else {
viewHolder = (ViewHolder) view.getTag();
}
//歌手
viewHolder.artist.setText(list.get(i).getArtist());
//歌名
viewHolder.title.setText(list.get(i).getTitle());
//时长
viewHolder.duration.setText(list.get(i).getDuration());
return view;
}
class ViewHolder{
ImageView img;
TextView title;
TextView artist;
TextView duration;
}
}
联系人适配器(PersonAdapter)
!!!这里类名不一样,注意分辨
public class MyBase extends BaseAdapter {
List<Person> list;
Context context;
public MyBase(List<Person> list, Context context) {
this.list = list;
this.context = context;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
HeroerView heroerView = new HeroerView();
if(convertView==null) {
convertView = LayoutInflater.from(context).inflate(R.layout.min,null);
heroerView.textView1 = convertView.findViewById(R.id.tv1);
heroerView.textView2 = convertView.findViewById(R.id.tv2);
convertView.setTag(heroerView);
}else {
heroerView = (HeroerView) convertView.getTag();
}
//姓名 和 手机号
heroerView.textView1.setText(list.get(position).getName());
heroerView.textView2.setText(list.get(position).getPhone());
return convertView;
}
public class HeroerView {
TextView textView1;
TextView textView2;
}
主要的
获取本地音乐(Main2activity)
可点击播放
public class Main2Activity extends AppCompatActivity {
MediaPlayer mediaPlayer = new MediaPlayer();
private ListView lv;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == 100 && grantResults[0] == 0) {
Toast.makeText(this, "允许授权", Toast.LENGTH_SHORT).show();
} else {
finish();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
initView();
//请求权限
requestPermissions(new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.READ_CONTACTS,
Manifest.permission.READ_SMS,
Manifest.permission.CALL_PHONE,
}, 100);
//读取所有的本地音乐
//1.导入本地音乐
//2.内容解析者,读取本地音乐
ContentResolver contentResolver = getContentResolver();
Cursor cursor = contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, null,null);
final ArrayList<Music> list = new ArrayList<>();
while (cursor.moveToNext()) {
String title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)); //歌名
String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));//歌手
String duration = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION));//总时长
String data = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA)); //地址(路径)
String size = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.SIZE)); //大小
String album_id = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID)); //专辑封面图片id
Music music = new Music(title, artist, duration, data, size, album_id);
list.add(music);
}
//适配器
MusicAdapter musicAdapter = new MusicAdapter(Main2Activity.this, list);
lv.setAdapter(musicAdapter);
//点击播放事件
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
try {
mediaPlayer.reset();//重置
String data = list.get(position).getData();
mediaPlayer.setDataSource(data); //设置数据源(路径)
mediaPlayer.prepareAsync();//准备
//监听是否准备完成
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override //准备完成
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();//播放
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
private void initView() {
lv = (ListView) findViewById(R.id.lv);
}
}
获取手机联系人(MainActivity)
可长按呼叫
public class MainActivity extends AppCompatActivity {
private ListView lv;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == 100 && grantResults[0] == 0) {
Toast.makeText(this, "允许授权", Toast.LENGTH_SHORT).show();
} else {
finish();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
//请求权限
requestPermissions(new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.READ_CONTACTS,
Manifest.permission.READ_SMS,
Manifest.permission.CALL_PHONE,
}, 100);
//获取所有的手机联系人
//内容解析者
ContentResolver contentResolver = getContentResolver();
Cursor cursor = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
final ArrayList<Person> list = new ArrayList<>();
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phone = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
Person person = new Person(name, phone);
list.add(person);
}
//数据源
System.out.println("-----------"+list);
//适配器
MyBase myBase = new MyBase(list, this);
lv.setAdapter(myBase);
//长按打电话
lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
Uri uri = Uri.parse("tel:" + list.get(position).getPhone());
intent.setData(uri);
startActivity(intent);
return true;
}
});
//长按发短信
// lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
// @Override
// public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
// Intent intent = new Intent();
// intent.setAction(Intent.ACTION_VIEW);
// Uri uri = Uri.parse("smsto:" + list.get(position).getPhone());
// intent.setData(uri);
// startActivity(intent);
// return true;
// }
// });
}
private void initView() {
lv = (ListView) findViewById(R.id.lv);
}
}
广播(BroadcastReceiver) 动态
BroadcastReceiver是Android的四大组件之一。Android四大组件有Activity,Service服务,Content Provider内容提供,BroadcastReceiver广播接收器。
在广播中不要进行耗时操作,或出现ANR情况,广播一般扮演启动其他组件的作用
创建广播接收者
注册广播
//实例化广播接收者对象
MyReceiver myReceiver = new MyReceiver();
//意图过滤器(Android系统会根据配置的 “意图过滤器” 来寻找可以响应该操作的组件,服务)
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("asdasdasd");
//注册动态广播接受者
registerReceiver(myReceiver,intentFilter);
发送广播
//创建intent
Intent intent = new Intent();
//在intent内 存值
intent.putExtra("msg","念天地之悠悠,独怆然而涕下");
intent.setAction("asdasdasd");
getActivity().sendBroadcast(intent);
接收广播
private class MyReceive extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("asdasdasd")) {
String title = intent.getStringExtra("msg");
Toast.makeText(context,title, Toast.LENGTH_SHORT).show();
}
}
}
静态与动态广播
动态广播
动态广播是使用Avtivity中的registerReceiver来注册的,灵活性高.
MainActivity类中
MyReceiver类(广播接收类)中
静态广播
静态广播是在清单文件中进行注册的,生命周期要比动态广播长很多,因为它是以系统时间进行监听的,比如当程序关闭后,如果来信息,静态广播还是可以接收到
MainActivity中
MyReceiver中
清单文件中
可设置触发条件
服务(Service)
service和Activity非常相似,一般启动Activity跳转需要调用Context的startAciticity(Intent intent)方法
而启动服务则需要调用Context的startService(Intent intent)方法
创建Service
MyService类
package com.example.service_210603;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
public MyService() {
}
//使用非绑定开启时 调用
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("---onStartCommand","非绑定开启时");
return super.onStartCommand(intent, flags, startId);
}
//使用绑定开启时 调用
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
Log.i("---onbind","绑定开启时");
throw new UnsupportedOperationException("Not yet implemented");
}
//重新绑定时 调用
@Override
public void onRebind(Intent intent) {
Log.i("---onRebind","重新绑定时");
super.onRebind(intent);
}
//解除绑定时 调用
@Override
public boolean onUnbind(Intent intent) {
Log.i("---onUnbind","解除绑定时");
return super.onUnbind(intent);
}
//销毁时 调用
@Override
public void onDestroy() {
Log.i("---onDestroy","销毁时");
}
}
MainActivity类
public class MainActivity extends AppCompatActivity {
private Button mainStartService;
private Button mainStopService;
//创建时
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
//使用非绑定启动服务方式
//按钮点击事件(启动服务)
mainStartService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,MyService.class);
startService(intent);
}
});
//按钮点击事件(停止服务)
mainStopService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,MyService.class);
stopService(intent);
}
});
}
private void initView() {
mainStartService = (Button) findViewById(R.id.main_start_service);
mainStopService = (Button) findViewById(R.id.main_stop_service);
}
}
音乐播放器
内含有前台服务,内容解析者,Service等
MainActivity类中
package com.example.musicservice;
import android.Manifest;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.MediaStore;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
public static List<MusicEntity> musics = new ArrayList<>();
private MusicService service1;
public static int MODE = 1;
private ServiceConnection serviceConnection;
private ListView mainListview;
public static CheckBox mainPlayBtn;
private ImageView mainPlayLast;
private ImageView mainPlayNext;
public static SeekBar mainSeek;
private ImageView mainPlayCurrent;
private ImageView mainPlayMode;
private Intent intent;
/**
* 允许或否定权限后的操作
*
* @param requestCode
* @param permissions
* @param grantResults
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
/*
允许权限后
*/
if (requestCode == 101 && grantResults[0] == 0) {
Toast.makeText(this, "允许", Toast.LENGTH_SHORT).show();
//启动Service
intent = new Intent(MainActivity.this, MusicService.class);
startService(intent);
/**
* 创建ServiceConnection对象 并获取Service对象
*/
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicService.MyBind myBind = (MusicService.MyBind) service;
service1 = myBind.getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
//绑定Service
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
//获取内容解析者
ContentResolver contentResolver = getContentResolver();
//获取query
Cursor query = contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, null, null, null, null);
while (query.moveToNext()) {
String title = query.getString(query.getColumnIndex(MediaStore.Audio.Media.TITLE));
String artist = query.getString(query.getColumnIndex(MediaStore.Audio.Media.ARTIST));
String duration = query.getString(query.getColumnIndex(MediaStore.Audio.Media.DURATION));
String data = query.getString(query.getColumnIndex(MediaStore.Audio.Media.DATA));
String size = query.getString(query.getColumnIndex(MediaStore.Audio.Media.SIZE));
String albumId = query.getString(query.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
//当时间小于10秒时,不作数
if (Integer.parseInt(duration) < 10000) {
continue;//跳出循环 并进行下一次循环
}
//设置时间为**:**格式
int i = Integer.parseInt(duration) / 1000 / 60;
int i1 = Integer.parseInt(duration) / 1000 % 60;
duration = i + ":" + i1;
//获取图片uri
Uri parse = Uri.parse("content://media/external/audio/albums/" + albumId);
//获取图片query
Cursor query1 = contentResolver.query(parse, null, null, null, null);
if (query1.moveToNext()) {
String album_art = query1.getString(query1.getColumnIndex("album_art"));
//替换
albumId = album_art;
}
//执行完上面之后 存到list集合中
MusicEntity musicEntity = new MusicEntity(title, artist, duration, data, size, albumId);
musics.add(musicEntity);
}
//适配器适配到listView上
MusicAdapter musicAdapter = new MusicAdapter();
mainListview.setAdapter(musicAdapter);
//listViewItem点击播放事件
mainListview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
try {
service1.play(position);
mainPlayBtn.setChecked(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
//播放按钮点击事件
mainPlayBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mainPlayBtn.isChecked()) {
mainPlayBtn.setChecked(true);
service1.playOrPause();
} else {
mainPlayBtn.setChecked(false);
service1.playOrPause();
}
}
});
//上一首按钮点击事件
mainPlayLast.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
service1.last();
}
});
//下一首按钮点击事件
mainPlayNext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
service1.next();
}
});
/**
* 播放方式(1顺序,2单曲,3随机)
*/
mainPlayMode.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final PopupWindow popupWindow = new PopupWindow();
popupWindow.setOutsideTouchable(true);
popupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
popupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
View inflate = LayoutInflater.from(MainActivity.this).inflate(R.layout.popup_music_mode, null);
popupWindow.setContentView(inflate);
popupWindow.showAsDropDown(mainPlayMode,0,-340);
inflate.findViewById(R.id.shunxu).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MODE = 1;
popupWindow.dismiss();
}
});
inflate.findViewById(R.id.only_one).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MODE = 2;
popupWindow.dismiss();
}
});
inflate.findViewById(R.id.randow).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MODE = 3;
popupWindow.dismiss();
}
});
}
});
}
/*
不允许权限后
*/
else {
Toast.makeText(this, "请打开读取内存权限", Toast.LENGTH_SHORT).show();
finish();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化
initView();
//申请权限
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE},
101);
}
private void initView() {
mainListview = (ListView) findViewById(R.id.main_listview);
mainPlayBtn = findViewById(R.id.main_play_btn);
mainPlayLast = (ImageView) findViewById(R.id.main_play_last);
mainPlayNext = (ImageView) findViewById(R.id.main_play_next);
mainSeek = (SeekBar) findViewById(R.id.main_seek);
mainPlayCurrent = (ImageView) findViewById(R.id.main_play_current);
mainPlayMode = (ImageView) findViewById(R.id.main_play_mode);
}
private class MusicAdapter extends BaseAdapter {
@Override
public int getCount() {
return musics.size();
}
@Override
public Object getItem(int position) {
return musics.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
HolderView holderView = new HolderView();
if (convertView == null) {
convertView = LayoutInflater.from(MainActivity.this).inflate(R.layout.music_lv_item, null);
holderView.pic = convertView.findViewById(R.id.music_item_pic);
holderView.artist = convertView.findViewById(R.id.music_item_artist);
holderView.duration = convertView.findViewById(R.id.music_item_duration);
holderView.title = convertView.findViewById(R.id.music_item_title);
convertView.setTag(holderView);
} else {
holderView = (HolderView) convertView.getTag();
}
Bitmap bitmap = BitmapFactory.decodeFile(musics.get(position).getAlbumId());
holderView.pic.setImageBitmap(bitmap);
holderView.title.setText(musics.get(position).getTitle());
holderView.duration.setText(musics.get(position).getDuration());
holderView.artist.setText(musics.get(position).getArtist());
return convertView;
}
private class HolderView {
ImageView pic;
TextView title;
TextView artist;
TextView duration;
}
}
@Override
protected void onDestroy() {
unbindService(serviceConnection);
stopService(intent);
super.onDestroy();
}
}
服务类
package com.example.musicservice;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.RemoteAction;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;
import android.widget.RemoteViews;
import android.widget.SeekBar;
import android.widget.Toast;
import java.io.IOException;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
public class MusicService extends Service {
Timer timer;
public MediaPlayer mediaPlayer = new MediaPlayer();
private int index = 0;
private boolean playing = false;
public MusicService() {
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "启动服务", Toast.LENGTH_SHORT).show();
/**
* 注册动态广播接收者
*/
MyReceiver myReceiver = new MyReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("play");
intentFilter.addAction("pause");
intentFilter.addAction("next");
intentFilter.addAction("last");
registerReceiver(myReceiver,intentFilter);
/**
* 滑动进度条监听事件
*/
MainActivity.mainSeek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
int progresss = 0;
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser) {
progresss = progress;
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
mediaPlayer.pause();
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
playOrPause();
mediaPlayer.seekTo(progresss);
}
});
//播放完毕监听事件
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
switch (MainActivity.MODE) {
case 1:
next();
break;
case 2:
play(index);
break;
case 3:
Random random = new Random();
int i = random.nextInt(MainActivity.musics.size() - 1);
play(i);
break;
}
notifyi();
}
});
return super.onStartCommand(intent, flags, startId);
}
/**
* 绑定时执行
* @param intent
* @return
*/
@Override
public IBinder onBind(Intent intent) {
return new MyBind();
}
/**
* 上一首
*/
public void last() {
--index;
if (index<0){
index = MainActivity.musics.size()-1;
}
play(index);
}
/**
* 下一首
*/
public void next() {
++index;
if (index>=MainActivity.musics.size()){
index = 0;
}
play(index);
}
/**
* 用于实例化Service对象
*/
public class MyBind extends Binder{
public MusicService getService(){
return MusicService.this;
}
}
/**
* 点击歌曲进行播放
* @param i
*/
public void play(int i) {
index = i;
try {
mediaPlayer.reset();
mediaPlayer.setDataSource(MainActivity.musics.get(index).getData());
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
MainActivity.mainSeek.setMax(mediaPlayer.getDuration());
/**
* 设置playing的值(通知需要)
*/
if (mediaPlayer.isPlaying()){
playing = true;
}else {
playing = false;
}
//通知
notifyi();
}
});
} catch (IOException e) {
e.printStackTrace();
}
/*
用于设置进度条自动
*/
if (timer!=null){
timer.cancel();
}
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
MainActivity.mainSeek.setProgress(mediaPlayer.getCurrentPosition());
}
},0,1000);
}
/**
* 播放或暂停
*/
public void playOrPause(){
if (mediaPlayer.isPlaying()){
mediaPlayer.pause();
}else {
mediaPlayer.start();
}
/*
设置playing的值(通知需要)
*/
if (mediaPlayer.isPlaying()){
playing = true;
}else {
playing = false;
}
//通知
notifyi();
}
/**
* 通知
*/
private void notifyi(){
//实例化
Notification.Builder notification = new Notification.Builder(this);
//设置小图标
notification.setSmallIcon(R.drawable.play_false);
//加载布局
RemoteViews remoteViews = new RemoteViews(getPackageName(),R.layout.notifiction_view);
//设置布局
notification.setCustomContentView(remoteViews);
//播放暂停广播
PendingIntent play = PendingIntent.getBroadcast(this, 1, new Intent("play"),0);
remoteViews.setOnClickPendingIntent(R.id.music_nft_play,play);
//图标更改判断//同步主页play图标
if (playing){
remoteViews.setImageViewResource(R.id.music_nft_play,R.drawable.play_true);
MainActivity.mainPlayBtn.setChecked(true);
}else {
remoteViews.setImageViewResource(R.id.music_nft_play,R.drawable.play_false);
MainActivity.mainPlayBtn.setChecked(false);
}
//下一首广播
PendingIntent next = PendingIntent.getBroadcast(this, 1, new Intent("next"),0);
remoteViews.setOnClickPendingIntent(R.id.music_nft_next,next);
//上一首广播
PendingIntent last = PendingIntent.getBroadcast(this, 1, new Intent("last"),0);
remoteViews.setOnClickPendingIntent(R.id.music_nft_last,last);
//更新图片
Bitmap bitmap = BitmapFactory.decodeFile(MainActivity.musics.get(index).getAlbumId());
remoteViews.setImageViewBitmap(R.id.music_nft_img,bitmap);
//更新文字
remoteViews.setTextViewText(R.id.music_nft_title,MainActivity.musics.get(index).getTitle());
//启动通知
startForeground(1,notification.build());
}
@Override
public boolean onUnbind(Intent intent) {
mediaPlayer.stop();
onDestroy();
return super.onUnbind(intent);
}
public class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
/**
* 接受广播执行操作
*/
String action = intent.getAction();
if (action.equals("play")){
playOrPause();
}else if (action.equals("next")){
next();
}else if (action.equals("last")){
last();
}
notifyi();
}
}
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "服务器已关闭", Toast.LENGTH_SHORT).show();
}
}
实体类
package com.example.musicservice;
public class MusicEntity {
private String title;
private String artist;
private String duration;
private String data;
private String size;
private String albumId;
public MusicEntity() {
}
public MusicEntity(String title, String artist, String duration, String data, String size, String albumId) {
this.title = title;
this.artist = artist;
this.duration = duration;
this.data = data;
this.size = size;
this.albumId = albumId;
}
@Override
public String toString() {
return "MusicEntity{" +
"title='" + title + '\'' +
", artist='" + artist + '\'' +
", duration='" + duration + '\'' +
", data='" + data + '\'' +
", size='" + size + '\'' +
", albumId='" + albumId + '\'' +
'}';
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getArtist() {
return artist;
}
public void setArtist(String artist) {
this.artist = artist;
}
public String getDuration() {
return duration;
}
public void setDuration(String duration) {
this.duration = duration;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
public String getAlbumId() {
return albumId;
}
public void setAlbumId(String albumId) {
this.albumId = albumId;
}
}
可能会有些许的BUG,大佬们请指正
-------------------------------
PhaseTwo(Android)
OkHttp(MVC)
从网络中获取或传递数据的方式,主要为Get和PostJson、PostForm,引用MVC框架
MVC分为
M:Model 数据访问层
V:View 视图层
C:Controller 业务逻辑层
单例类
真正获取数据,进行数据访问的类
public class HttpManager {
private static HttpManager manager;
//线程切换 (弱应用问题)
private Handler handler;
//请求客户端
private OkHttpClient client;
//懒汉式单例
public static HttpManager getInstance() {
if (manager == null) {
manager = new HttpManager();
}
return manager;
}
public HttpManager() {
client = new OkHttpClient.Builder()
.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.connectTimeout(2, TimeUnit.MINUTES)
.writeTimeout(2, TimeUnit.MINUTES)
.readTimeout(2, TimeUnit.MINUTES)
.build();
handler = new Handler();
}
/**
* Get请求
*
* @param url
* @param callBack
*/
public void doGet(String url, MyCallBack callBack) {
doGet(url,null,callBack);
}
/**
* 重载方法
*
* @param url
* @param callBack
*/
public void doGet(String url, Map<String, String> headMap, final MyCallBack callBack) {
//添加url和post方法一样 都是在rb内.url添加
Request.Builder rb = new Request.Builder().url(url);
if (headMap != null && headMap.size() > 0) {
for (String key : headMap.keySet()) {
rb.addHeader(key, headMap.get(key));
}
}
client.newCall(rb
.get()
.build()).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
if (callBack != null) {
callBack.fail(e.getMessage());
}
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
if (response.code() == 200) {
//前程切换到主线程,执行回调
handler.post(new Runnable() {
@Override
public void run() {
if (callBack != null) {
callBack.success(response);
}
}
});
} else {
if (callBack != null) {
callBack.fail(response.message());
}
}
}
});
}
/**
* post表单提交方法
* @param url
* @param formBody
* @param callBack
*/
public void doPostFrom(String url, FormBody formBody, final MyCallBack callBack) {
client.newCall(new Request.Builder()
.url(url)
.post(formBody)
.build()).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
if (callBack != null) {
callBack.fail(e.getMessage());
}
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
if (response.code() == 200) {
//前程切换到主线程,执行回调
handler.post(new Runnable() {
@Override
public void run() {
if (callBack != null) {
callBack.success(response);
}
}
});
} else {
if (callBack != null) {
callBack.fail(response.message());
}
}
}
});
}
/**
* post以JSON提交的方法
* @param url
* @param headMap
* @param callBack
*/
public void doPostJson(String url, Map<String, String> headMap, final MyCallBack callBack) {
JSONObject jsonObject = new JSONObject();
if (headMap != null && headMap.size() > 0) {
for (String key : headMap.keySet()) {
try {
jsonObject.put(key, headMap.get(key));
} catch (JSONException e) {
e.printStackTrace();
}
}
}
RequestBody body = RequestBody.create(MediaType.parse("application/json"), jsonObject.toString());
client.newCall(new Request.Builder()
.url(url)
.post(body)
.build()).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
if (callBack != null) {
callBack.fail(e.getMessage());
}
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
if (response.code() == 200) {
//前程切换到主线程,执行回调
handler.post(new Runnable() {
@Override
public void run() {
if (callBack != null) {
callBack.success(response);
}
}
});
} else {
if (callBack != null) {
callBack.fail(response.message());
}
}
}
});
}
/**
* 回调方法(用于表示成功或失败信息)
*/
public interface MyCallBack {
void success(Response response);
void fail(String msg);
}
}
单例类中需要的拦截器
public class HeadInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
//在网络请求当中 Request 一但修改原有 Request 不可以使用,你需要构建新的对象
Request request = chain.request();
return chain.proceed(request.newBuilder().addHeader("head","android").build());
}
}
M层(Model模块)
数据访问层
public class MVCLoginModel {
/**
* 数据访问层中的请求登录方法
* @param username
* @param pwd
* @param callBack
*/
public void requestLogin(String username, String pwd, HttpManager.MyCallBack callBack) {
//判断是否有网
if (NetworkUtils.isConnected()) {
//formbody传递数据 并回调
FormBody formBody = new FormBody.Builder()
.add("username", username)
.add("pwd", pwd)
.build();
//调用单例类中的doPOstForm方法 并且回调
HttpManager.getInstance().doPostFrom("http://39.98.153.96:8082/api/WeekTest/login?username=" + username + "&pwd=" + pwd,
formBody, callBack);
}else {
//如果没有移动数据网络 就响应成功
ResponseBody responseBody = ResponseBody.create(MediaType.parse("application/json"),"");
//回调成功(这里仅仅做一个效果)
callBack.success(new Response.Builder()
.body(responseBody)
.build());
}
}
}
C层(Controller控制器层)
业务逻辑层
/**
* 业务逻辑层
*/
public class MVCLoginController {
private MVCLoginModel model;
/**
* 创建this时,同时实例化model
*/
public MVCLoginController() {
model = new MVCLoginModel();
}
/**
* 登录方法(一般用于验证)
* @param username
* @param pwd
* @param callBack
*/
public void login(String username, String pwd, HttpManager.MyCallBack callBack){
if (username.length()==0){
ToastUtils.showShort("请输入用户名");
}else {
model.requestLogin(username,pwd,callBack);
}
}
}
V层(View视图层)
视图层为主要的显示层
这里的Activity为了方便,加上一个框架,使用接口和抽象类
IActivity
public interface IActivity {
//初始化数据方法
void initData();
//初始化视图方法
void initView();
//绑定主视图方法
@LayoutRes int initLayout();
}
BaseActivity
主要用于继承
public abstract class BaseActivity extends AppCompatActivity implements IActivity, View.OnClickListener {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//绑定主视图操作
setContentView(initLayout());
//初始化视图 findViewById等操作
initView();
//初始化数据 GetData等操作
initData();
}
/**
* 点击事件
* @param v
*/
@Override
public void onClick(View v) {
}
}
IFragment
/**
* 继承IActivity接口
*/
public interface IFragment extends IActivity {
//findViewById操作
<T extends View> T findViewById(@LayoutRes int id);
}
BaseFragment
public abstract class BaseFragment extends Fragment implements IFragment {
private View mBaseView;
@Nullable
@Override
/**
* 创建时,设置主视图
*/
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return mBaseView = inflater.inflate(initLayout(),container,false);
}
/**
* 创建后初始化视图和数据
* @param view
* @param savedInstanceState
*/
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initView();
initData();
}
/**
* findViewById方法
* @param id
* @param <T>
* @return
*/
@SuppressLint("ResourceType")
@Override
public <T extends View> T findViewById(int id) {
return mBaseView.findViewById(id);
}
}
自定义Activity
!!!!最主要的MainActivity
public class MVCLoginActivity extends BaseActivity implements HttpManager.MyCallBack{
private EditText loginUsername;
private EditText loginPassword;
private Button loginBtn;
//控制器
private MVCLoginController controller;
//加载数据
@Override
public void initData() {
loginPassword.setText("123456");
loginUsername.setText("1903001");
}
//加载控件
@Override
public void initView() {
loginUsername = (EditText) findViewById(R.id.login_username);
loginPassword = (EditText) findViewById(R.id.login_password);
loginBtn = (Button) findViewById(R.id.login_btn);
controller = new MVCLoginController();
}
//加载主视图
@Override
public int initLayout() {
return R.layout.activity_main;
}
//点击事件
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.login_btn:
String username = loginUsername.getText().toString();
String pwd = loginPassword.getText().toString();
controller.login(username,pwd,this);
break;
}
}
//成功
@Override
public void success(Response response) {
Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
}
//失败
@Override
public void fail(String msg) {
Toast.makeText(this, "登录失败", Toast.LENGTH_SHORT).show();
}
}