> 文档中心 > Android期末项目(超详细附下载链接)

Android期末项目(超详细附下载链接)

【第一部分】历史文章:
Android学习笔记(一)——创建第一个Android项目
Android学习笔记(二)android studio基本控件及布局(实现图片查看器)
Android学习笔记(三)android studio中CheckBox自定义样式(更换复选框左侧的勾选图像)
Android学习笔记(四)Android 中Activity页面的跳转及传值
Android学习笔记(五)——Toast提示、Dialog对话框、Menu菜单
Android学习笔记(六)——自定义ListView布局+AsyncTask异步任务
Android学习笔记(七)——数据存储(共享参数SharedPreferences)
Android学习笔记(八)——数据存储(SD卡文件操作)
Android学习笔记(九)——网络技术
Android学习笔记(十)——实现新闻列表案例
Android学习笔记(十一)——一些高级控件的使用
Android学习笔记(十二)——数据存储(SQLite数据库)
Android学习笔记(十三)——数据存储(LitePal操作数据库)
Android学习笔记(十四)——内容提供器
Android学习笔记(十五)——侧滑容器(ViewPager)
【第二部分】主要问题解决:
Android Studio(存)读取不了SD卡上的文件——【已解决】
【第三部分】期末项目:
Android期末项目(一)—— 解析二维数组对象
Android期末项目(二)——欢迎界面(实现倒计时+点击跳转+判断是否登录)


Android期末大作业——今日头条

一、主要的功能介绍

模块 主要功能 相关描述
登录、注册页面 LitePal操作数据库 数据的插入、查询操作;数据校验
引导首页 封面展示+倒计时进入 定时器
首页导航 共四个板块—主页、西瓜视频、系统设置、我的 对应四个碎片
主页 共五个板块—推荐、国内、体育、社会、军事 对应五个碎片分别显示不同类别的新闻
西瓜视频 播放视频
系统设置 我的消息、清理缓存、头条封面、头条热榜等 通知、访问网络接口、数据解析
我的 扫一扫、上传头像、账号管理、我的收藏、个人资料、登录等操作 更改密码、收藏新闻展示、个人资料的设置
发布按钮 进行拍照 使用多媒体
上传头像 选择相册
底部弹出框 个人资料中使用 有相应的字数限制,城市选择三级联动等
权限设置 用户未登录的状态 查看相关新闻、头像框显示未登录、账号管理、我的收藏、个人资料,只有登录后才可访问、用户不可评论与收藏
验证码 注册的时候 进行判断用户输入的验证码是否与生成的一致
用户登录成功后 可以进行一系列的操作 更改个人资料,收藏新闻、评论、查看收藏、评论等

二、准备工作

用到的接口:头条新闻数据、头条热榜。

http://v.juhe.cn/toutiao/index?type=top&key=

https://api.storeapi.net/api/68/177?format=json&weibo_top=1594&appid=2307&sign=

注:接口可以到聚合数据去申请。

(一)头条新闻接口数据分析:

  • uniquekey :唯一标识
  • title :新闻标题
  • date :时间
  • category :新闻类别
  • author_name :新闻名称
  • url :新闻具体内容url
  • thumbnail_pic_s :新闻图片url

注:type取值(正好头部可以显示不同类别的新闻!!!)

top   yule   tiyu   caijing    guoji   guonei    junshi   keji    shehui  shishang

注:下面是使用Postman测试的接口数据
在这里插入图片描述
(二)头条热榜接口数据分析:

  • w_time:时间
  • w_key:关键词
  • w_hot:相关数据
  • w_label:标签
    注:下面是使用Postman测试的接口数据
    在这里插入图片描述
    注:对该接口数据进行数据解析:请参考Android期末项目(一)—— 解析二维数组对象

三、用到的数据存储

  • 登录、注册:使用的是LitePal
  • 收藏新闻:使用的是SQLite
  • 记住密码:sharepreference
  • 保存用户信息:sharepreference(用户显示用户名、权限的判断)
  • 保存个人资料信息:使用的是LitePal
  • 新闻评论:使用的是LitePal

(1)登录、注册操作。

  • 注册:填入用户名、密码、确认密码、验证码,进行注册。
  • 登录:判断用户名是否已经注册、没有注册的话,写入数据库。

(2)收藏新闻。

  • 用户点击新闻展示页面中的收藏按钮,进行新闻的收藏。
  • 进行插入数据库(新闻标题、新闻具体url、时间、新闻来源、图片的url)。

(3)保存个人资料信息。

  • 插入数据库信息(用户名、昵称、介绍、性别、地区等)

四、主页设计(展示新闻列表)

4.1、使用的主要控件:

  • FrameLayout (碎片,各类新闻的切换)
  • ImageView (底部导航的图片)
  • TextView(底部的导航标题)

发生的事情:显示新闻列表——>点每一个新闻列表中的删除图标——>对话框弹出(问你:确定删除吗?)——>确定的话(该条新闻从数据源中移出)——>点击每一条新闻——>跳到新闻详情页面——>在新闻详情页面对新闻进行收藏操作(涉及到页面之间的传值,存数据库操作)——>为后面的查看收藏做好准备!!!

4.2、推荐碎片:推荐类新闻的实现fragment_tuijian.xml

1、在fragment_tuijian.xml中添加ListView。

2、列表项使用的主要控件。(共6个)

  • TextView :显示新闻标题、新闻的来源、新闻的时间。
  • ImageView:显示新闻的图片、删除图标图片。
  • View :列表项与列表项之间的水平横线。
水平横线的设计:    <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#DCDCDC" />

3、具体实现,参考老师上课的那个(第六课)——其实没有什么区别!!!

4.3、以上用到的知识点

  • 布局的设计
  • ListView列表的应用(三要素:数据源、控件、数据适配器)
  • json数据解析(用的是上课时讲的那种方式)
  • 活动之间的跳转及传值
  • OkHttp访问网络
  • AsyncTask异步任务
  • FrameLayout的使用(参考老师的那个:这是财经新闻。。。的那个案例!!!)
  • WebView展示新闻详情页面
    等等吧!!!

4.4、点击新闻跳转到新闻详情页面

  • 点击新闻列表中的每一项后,进行跳转页面;把新闻的标题、新闻具体内容url、时间、新闻来源、图片url等数据传递。
  • 在新闻详情页面,进行获取到以上传过去的值,用WebView显示新闻的具体内容。
  • 在新闻详情页面中,添加收藏按钮。

4.5、新闻详情页面点击收藏图标(用户登录后)

  • 当点击收藏按钮时,插入数据库,这里用的时SQLite的方式。
  • 插入数据库的目的,用户在我的板块可以查看所收藏的新闻。

4.6、新闻的评论(用户登录后)

在新闻详情页中,输入评论内容,点击发送按钮,即可评论。

4.7、点击右上角的发布按钮

  • 点击后,从底部弹出页面栏,点击拍小视频,可以打开相机。

4.8、其他

对于不同的类别的新闻展示,其实具体代码与推荐类的新闻代码一样,只需要把新闻接口的type属性改下即可。
Android期末项目(超详细附下载链接)

五、西瓜视频设计(展示视频列表)

部分关键代码:
在这里插入图片描述
在这里插入图片描述

六、系统设置设计

  • 我的消息 :(Notification通知相关的使用)
  • 清理缓存
  • 夜间模式
  • H5广告过滤
  • 头条封面 (跳到引导页面)
  • 广告设置 :
  • 头条热榜 :访问网络接口进行展示
  • 我的发现

6.1、清理缓存
点击清理缓存按钮:

im_qinglihuancun.setOnClickListener(new View.OnClickListener() {     @Override     public void onClick(View v) {  try{      String size = ClearCache.getTotalCacheSize(getContext());      ClearCache.clearAllCache(getContext());      Toast.makeText(getContext(), size + "缓存清除完成", Toast.LENGTH_SHORT).show();  }catch (Exception e){      e.printStackTrace();  }     } });

ClearCache.java

package cn.edu.hznu.com.utils;import android.content.Context;import android.os.Environment;import java.io.File;import java.math.BigDecimal;public class ClearCache {    /**     * 获取缓存大小     * @param context     * @return     * @throws Exception     */    public static String getTotalCacheSize(Context context) throws Exception { long cacheSize = getFolderSize(context.getCacheDir()); if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {     cacheSize += getFolderSize(context.getExternalCacheDir()); } return getFormatSize(cacheSize);    }    /***     * 清理所有缓存     * @param context     */    public static void clearAllCache(Context context) { deleteDir(context.getCacheDir()); if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {     deleteDir(context.getExternalCacheDir()); }    }    private static boolean deleteDir(File dir) { if (dir != null && dir.isDirectory()) {     String[] children = dir.list();     for (int i = 0; i < children.length; i++) {  boolean success = deleteDir(new File(dir, children[i]));  if (!success) {      return false;  }     } } return dir.delete();    }    // 获取文件    //Context.getExternalFilesDir() --> SDCard/Android/data/你的应用的包名/files/ 目录,一般放一些长时间保存的数据    //Context.getExternalCacheDir() --> SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据    public static long getFolderSize(File file) throws Exception { long size = 0; try {     File[] fileList = file.listFiles();     for (int i = 0; i < fileList.length; i++) {  // 如果下面还有文件  if (fileList[i].isDirectory()) {      size = size + getFolderSize(fileList[i]);  } else {      size = size + fileList[i].length();  }     } } catch (Exception e) {     e.printStackTrace(); } return size;    }    /**     * 格式化单位     *     * @param size     * @return     */    public static String getFormatSize(double size) { double kiloByte = size / 1024; if (kiloByte < 1) {//     return size + "Byte";     return "0K"; } double megaByte = kiloByte / 1024; if (megaByte < 1) {     BigDecimal result1 = new BigDecimal(Double.toString(kiloByte));     return result1.setScale(2, BigDecimal.ROUND_HALF_UP)      .toPlainString() + "KB"; } double gigaByte = megaByte / 1024; if (gigaByte < 1) {     BigDecimal result2 = new BigDecimal(Double.toString(megaByte));     return result2.setScale(2, BigDecimal.ROUND_HALF_UP)      .toPlainString() + "MB"; } double teraBytes = gigaByte / 1024; if (teraBytes < 1) {     BigDecimal result3 = new BigDecimal(Double.toString(gigaByte));     return result3.setScale(2, BigDecimal.ROUND_HALF_UP)      .toPlainString() + "GB"; } BigDecimal result4 = new BigDecimal(teraBytes); return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString()  + "TB";    }}

七、我的设计

  • 头像上传
  • 扫一扫
Intent intent = new Intent();intent.setComponent(new ComponentName("com.tencent.mm", "com.tencent.mm.ui.LauncherUI"));intent.putExtra("LauncherUI.From.Scaner.Shortcut", true);intent.setFlags(335544320);intent.setAction("android.intent.action.VIEW");getContext().startActivity(intent);
  • 账号管理
    进行密码更改的操作
  • 我的收藏
    展示收藏的新闻数据
  SQLiteDatabase db = myDatabaseHelper.getReadableDatabase();      Cursor cursor = db.rawQuery("select * from coll_news_table", null);      if (cursor.getCount() != 0) {   if (cursor.moveToFirst()) {do {    String title = cursor.getString(cursor.getColumnIndex("title"));    String date = cursor.getString(cursor.getColumnIndex("date"));    String author = cursor.getString(cursor.getColumnIndex("author"));    String imgurl = cursor.getString(cursor.getColumnIndex("imgurl"));    String url = cursor.getString(cursor.getColumnIndex("url"));    News news = new News(imgurl, title, url, date, author);    list.add(news);} while (cursor.moveToNext());
  • 个人资料
    用户名、昵称、介绍、性别、地区。
    在介绍添加了 输入字数的限制功能(20字以内):
 ed_jieshao.addTextChangedListener(new TextWatcher() {     private CharSequence wordNum;//记录输入的字数     private int selectionStart;     private int selectionEnd;     private int num=20;     @Override     public void beforeTextChanged(CharSequence s, int start, int count, int after) {}     @Override     public void onTextChanged(CharSequence s, int start, int before, int count) {  wordNum= s;//实时记录输入的字数     }     @Override     public void afterTextChanged(Editable s) {  int number = num - s.length();  //TextView显示剩余字数  ed_zishu.setText("剩余" + number+"字");  selectionStart=ed_jieshao.getSelectionStart();  selectionEnd = ed_jieshao.getSelectionEnd();  if (wordNum.length() > num) {      //删除多余输入的字(不会显示出来)      s.delete(selectionStart - 1, selectionEnd);      int tempSelection = selectionEnd;      ed_jieshao.setText(s);      ed_jieshao.setSelection(tempSelection);//设置光标在最后  }     } });
  • 版本升级
  AlertDialog.Builder builder=new AlertDialog.Builder(getContext()); //创建一个AlertDialog的构造器      builder.setIcon(R.drawable.tanhao);   //设置图标      builder.setTitle("温馨提示");  //设置标题      builder.setMessage("当前已是最新版本");  //设置消息内容      builder.create().show();
  • 退出登录

八、遇到的问题

在使用前面第二个数据接口的时候,数据解析一直报错,出现空指针异常。得不到数据。

通过询问老师:最终得到了解决方案😀,数据成功显示。

Android期末项目(一)—— 解析二维数组对象

九、总结

通过本学期的Android课程的学习,基本掌握了Android应用程序的开发的一般流程,对常用的控件基本掌握及用法,对其事件的监听方法也基本掌握。学习Android不仅是对前沿开发技术的了解,也是对编程知识的一次提升。

十、项目效果

在这里插入图片描述

若文章中有错误的地方欢迎大家反馈或者留言,十分感谢!!!