反射、io流、正则、网编、MySql、JavaWeb、Android等等等等等等等等等等等等等等等等等~~~~~~

Java-Android

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">
                &emsp;
                <input type="submit" value="增加">
                &emsp;&emsp;
                <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">
                &emsp;
                <input type="submit" value="修改">
                &emsp;&emsp;
                <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();
    }
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值