当前位置: 首页 > news >正文

Android Studio实现解析HTML获取图片URL将图片保存到本地

目录

        • 效果
        • activity_main.xml
        • MainActivity
        • ImageItem
        • ImageAdapter

效果

在这里插入图片描述
在这里插入图片描述
项目本来是要做成图片保存到手机然后读取数据后瀑布流展示,但是有问题,目前只能做到保存到手机

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"tools:context=".MainActivity"android:orientation="horizontal"><Buttonandroid:id="@+id/button"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="生成瀑布流"tools:ignore="MissingConstraints" /><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recycler_view"android:layout_width="match_parent"android:layout_height="match_parent" /></LinearLayout>

MainActivity

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;import android.Manifest;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.FileUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;public class MainActivity extends AppCompatActivity {private ImageView imageView;private static final String TAG = "MainActivity";private static final int PERMISSION_REQUEST_CODE = 1;private Button mButton;private List<ImageItem> mImageList;private RecyclerView mRecyclerView;private ImageAdapter mAdapter;@SuppressLint("MissingInflatedId")@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mButton = findViewById(R.id.button);mImageList = new ArrayList<>();mRecyclerView = findViewById(R.id.recycler_view);mRecyclerView.setLayoutManager(new LinearLayoutManager(this));mAdapter = new ImageAdapter(mImageList, this);mRecyclerView.setAdapter(mAdapter);mButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},PERMISSION_REQUEST_CODE);} else {// 开始解析HTML并下载图片startParsingAndDownloading();imageView = findViewById(R.id.image_view);Log.e(TAG,"开始解析HTML并下载图片");}}});}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == PERMISSION_REQUEST_CODE) {if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {// 写入外部存储权限已授予,解析HTML并下载图片new ParseHtmlTask().execute("https://example.com"); // 替换为你要解析的HTML网页URL} else {// 用户拒绝了权限请求,可以根据需要进行处理}}}//开始解析HTMLprivate void startParsingAndDownloading() {new ParseHtmlTask().execute("https://home.meishichina.com/show-top-type-recipe.html");}private class ParseHtmlTask extends AsyncTask<String, Void, List<ImageItem>> {@Overrideprotected List<ImageItem> doInBackground(String... urls) {String url = urls[0];Document document = null;try {document = Jsoup.connect(url).get();Elements imgElements = document.select("div.pic");for (Element element : imgElements) {String imgUrl = element.select("a").select("img").attr("data-src");mImageList.add(new ImageItem(imgUrl));downloadImage(imgUrl);}} catch (IOException e) {Log.e(TAG,"111");//throw new RuntimeException(e);}return mImageList;}@Overrideprotected void onPostExecute(List<ImageItem> imageList) {mAdapter.notifyDataSetChanged();}private void downloadImage(String imgUrl) {Glide.with(MainActivity.this).downloadOnly().load(imgUrl).into(new CustomTarget<File>() {@Overridepublic void onResourceReady(@NonNull File resource, @Nullable Transition<? super File> transition) {// 下载完成后的处理逻辑,可根据需求进行保存或其他操作// 这里将图片文件保存到手机的公共图片目录下String fileName = "image_" + System.currentTimeMillis() + ".jpg";File destFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), fileName);try {copyFile(resource, destFile);} catch (IOException e) {e.printStackTrace();}}@Overridepublic void onLoadCleared(@Nullable Drawable placeholder) {// 可选的清除逻辑}});}private void copyFile(File sourceFile, File destFile) throws IOException {InputStream inputStream = null;OutputStream outputStream = null;try {inputStream = new FileInputStream(sourceFile);outputStream = new FileOutputStream(destFile);byte[] buffer = new byte[1024];int length;while ((length = inputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, length);}} finally {if (inputStream != null) {inputStream.close();}if (outputStream != null) {outputStream.close();}}}

ImageItem

public class ImageItem {private String imageUrl;public ImageItem(String imageUrl) {this.imageUrl = imageUrl;}public String getImageUrl() {return imageUrl;}
}

ImageAdapter

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;import com.bumptech.glide.Glide;import java.util.List;public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ViewHolder> {private List<ImageItem> imageList;private Context context;public ImageAdapter(List<ImageItem> imageList, Context context) {this.imageList = imageList;this.context = context;}@NonNull@Overridepublic ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = LayoutInflater.from(context).inflate(R.layout.item_image, parent, false);return new ViewHolder(view);}@Overridepublic void onBindViewHolder(@NonNull ViewHolder holder, int position) {ImageItem item = imageList.get(position);String imageUrl = item.getImageUrl();// 使用Glide加载图片Glide.with(context).load(imageUrl).into(holder.imageView);}@Overridepublic int getItemCount() {return imageList.size();}public class ViewHolder extends RecyclerView.ViewHolder {ImageView imageView;public ViewHolder(@NonNull View itemView) {super(itemView);imageView = itemView.findViewById(R.id.image_view);}}
}

相关文章:

Android Studio实现解析HTML获取图片URL将图片保存到本地

目录 效果activity_main.xmlMainActivityImageItemImageAdapter 效果 项目本来是要做成图片保存到手机然后读取数据后瀑布流展示&#xff0c;但是有问题&#xff0c;目前只能做到保存到手机 activity_main.xml <?xml version"1.0" encoding"utf-8"?…...

单例模式的理论与实践

本文实践代码仓库&#xff1a;https://github.com/goSilver/my_practice 文章目录 一、定义二、作用三、实现3.1 饿汉式3.2 懒汉式3.3 双重检查3.4 静态内部类3.5 枚举 四、总结4.1 单例存在哪些问题&#xff1f;4.2 单例有什么替代解决方案&#xff1f; 一、定义 单例模式是一…...

深入了解MongoDB:灵活的文档型数据库与应用案例

什么是MongoDB ? MongoDB 是由C语言编写的&#xff0c;是一个基于分布式文件存储的开源数据库系统。 在高负载的情况下&#xff0c;添加更多的节点&#xff0c;可以保证服务器性能。 MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。 MongoDB 将数据存储为一个…...

【HarmonyOS北向开发】-01 HarmonyOS概述

飞书原文链接-【HarmonyOS北向开发】-01 HarmonyOS概述https://fvcs2dhq8qs.feishu.cn/docx/TDf2d2KMaoPSUUxnvg2cASDdnCe?fromfrom_copylink...

Node.js入门

安装 前往官网下载即可&#xff1a;https://nodejs.org/zh-cn 安装之后检查是否成功并查看版本&#xff0c;winr --> 输入cmd --> 确认 --> 进入命令提示符窗口 --> 输入 node -v --> 出现以下就代表成功了&#xff0c;这也是node的版本号 什么是Node.js Nod…...

指针、数组、sizeof、strlen相关知识与练习题目

目录 前提回顾&#x1f50d;&#xff1a; 关于一维数组&#x1f92e;&#xff1a; 关于二维数组&#x1f600;&#xff1a; sizeof与strlen&#x1f415;&#xff1a; sizeof&#x1f3c0;&#xff1a; strlen&#x1f413;&#xff1a; 相关练习&#x1f4da;&#xff1a…...

分类预测 | MATLAB实现WOA-CNN-BiLSTM-Attention数据分类预测

分类预测 | MATLAB实现WOA-CNN-BiLSTM-Attention数据分类预测 目录 分类预测 | MATLAB实现WOA-CNN-BiLSTM-Attention数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.MATLAB实现WOA-CNN-BiLSTM-Attention数据分类预测&#xff0c;运行环境Matlab2023b及以上…...

MyBatis动态SQL:打造灵活可变的数据库操作

目录 if标签trim标签where标签set标签foreach标签 动态SQL就是根据不同的条件或需求动态地生成查询语句&#xff0c;比如动态搜索条件、动态表或列名、动态排序等。 if标签 在我们填写一些信息时&#xff0c;有些信息是必填字段&#xff0c;有的则是非必填的&#xff0c;这些…...

nginx代理请求到内网不同服务器

需求&#xff1a;之前用的是frp做的内网穿透&#xff0c;但是每次电脑断电重启&#xff0c;路由或者端口会冲突&#xff0c;现在使用汉土云盒替换frp。 需要把公网ip映射到任意一台内网服务器上&#xff0c;然后在这台内网服务器上用Nginx做代理即可访问内网其它服务器&#xf…...

【C# 基础精讲】文件读取和写入

文件读取和写入是计算机程序中常见的操作&#xff0c;用于从文件中读取数据或将数据写入文件。在C#中&#xff0c;使用System.IO命名空间中的类来进行文件读写操作。本文将详细介绍如何在C#中进行文件读取和写入&#xff0c;包括读取文本文件、写入文本文件、读取二进制文件和写…...

设计模式——经典单例

0、核心要素 // 构造、析构函数私有化&#xff08;一个进程只允许一个对象存在&#xff09; // 对象私有化、静态化&#xff08;因为接口静态函数&#xff09; // 对象调用接口静态化&#xff08;因为静态函数脱离了类对象&#xff0c;可以直接调用&#xff09; 一、懒汉 唯…...

【HarmonyOS】鸿蒙应用获取华为帐号手机号码步骤(API7及以下)

【写在前面】 本文主要介绍使用API7及以下版本开发HarmonyOS应用时&#xff0c;通过华为帐号SDK和云侧接口获取手机号码的主要开发步骤&#xff0c;注意&#xff1a;开发过程中集成的华为帐号SDK仅支持API7及以下版本的HarmonyOS应用。 【前提准备】 1、HarmonyOS应用已申请获…...

webpack相关面试

运行 npm run xxx 的时候发生了什么&#xff1f; npm run xxx的时候&#xff0c;首先会去项目的package.json文件里找scripts 里找对应的xxx&#xff0c;然后执行 xxx的命令 npm i 的时候&#xff0c;npm 读到该配置后&#xff0c;就将该文件软链接到 ./node_modules/.bin 目录…...

如何使用ChatGPT创建个性化的健身锻炼计划

ChatGPT广泛应用于各个行业&#xff0c;健身也不例外。 ChatGPT 在健身领域的一个常用案例是创建个性化的锻炼计划。 在要求 ChatGPT 创建锻炼计划时&#xff0c;简单地输入自己的目标和当前的健身水平是一个很好的开始。完成此操作后&#xff0c;你还可以使用其他提示和措施来…...

人工智能与云计算实训室建设方案

一、 人工智能与云计算系统概述 人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;是一种模拟人类智能的科学和工程&#xff0c;通过使用计算机系统来模拟、扩展和增强人类的智能能力。人工智能涉及多个领域&#xff0c;包括机器学习、深度学习、自然…...

使用 Apache Kafka 和 Go 将数据引入 OpenSearch

需要编写自定义集成层来满足数据管道中的特定要求&#xff1f;了解如何使用 Go 通过 Kafka 和 OpenSearch 实现此目的。 可扩展的数据摄取是OpenSearch等大规模分布式搜索和分析引擎的一个关键方面。构建实时数据摄取管道的方法之一是使用Apache Kafka。它是一个开源事件流平台…...

2.SpringMvc中Model、ModelMap和ModelAndView使用详解

1.前言 最近SSM框架开发web项目&#xff0c;用得比较火热。spring-MVC肯定用过&#xff0c;在请求处理方法可出现和返回的参数类型中&#xff0c;最重要就是Model和ModelAndView了&#xff0c;对于MVC框架&#xff0c;控制器Controller执行业务逻辑&#xff0c;用于产生模型数据…...

Spark repartition和coalesce的区别

repartition只是coalesce接口中shuffle为true的实现。不经过 shuffle&#xff0c;也就是coaleasce shuffle为false&#xff0c;是无法增加RDD的分区数的&#xff0c;比如你源RDD 100个分区&#xff0c;想要变成200个分区&#xff0c;只能使用repartition&#xff0c;也就是coal…...

微服务最佳实践,零改造实现 Spring Cloud Apache Dubbo 互通

作者&#xff1a;孙彩荣 很遗憾&#xff0c;这不是一篇关于中间件理论或原理讲解的文章&#xff0c;没有高深晦涩的工作原理分析&#xff0c;文后也没有令人惊叹的工程数字统计。本文以实际项目和代码为示例&#xff0c;一步一步演示如何以最低成本实现 Apache Dubbo 体系与 S…...

leetcode 力扣刷题 两数/三数/四数之和 哈希表和双指针解题

两数/三数/四数之和 题目合集 哈希表求解1. 两数之和454. 四数相加Ⅱ 双指针求解15.三数之和18. 四数之和 这个博客是关于&#xff1a;找出数组中几个元素&#xff0c;使其之和等于题意给出的target 这一类题目的&#xff0c;但是各个题之间又有些差异&#xff0c;使得需要用不…...

不止是拆网卡:以联想ThinkCentre M7131z为例,聊聊老旧一体机的升级改造可能性

联想ThinkCentre M7131z改造指南&#xff1a;从拆网卡到全面性能升级 老旧商用一体机往往被贴上"性能瓶颈"的标签&#xff0c;但联想ThinkCentre M7131z系列却隐藏着令人惊喜的改造潜力。这台发布于2015年前后的商用一体机&#xff0c;凭借其模块化设计和充足的内部空…...

游戏多开检测技术深度解析与实战绕过方案

1. 游戏多开检测技术全景解析 游戏多开检测本质上是一种防止同一程序重复运行的技术手段。我在逆向分析各类游戏客户端时发现&#xff0c;现代游戏通常会采用组合拳式的检测策略&#xff0c;从简单的进程查找到复杂的驱动级验证&#xff0c;防御层级越来越深。对于开发者而言&a…...

TPAMI 2026 | 雨雾噪模糊全搞定!CPL 框架让图像复原告别单一任务限制

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶” 重磅干货&#xff0c;第一时间送达在日常拍摄中&#xff0c;一张照片可能同时遭遇噪声、雾霾、雨滴等多种退化问题&#xff0c;而传统图像复原方法要么只能处理单一退化类型&#xff0c;要么在多任务场景下…...

Transformer位置编码避坑指南:手把手教你用RoPE解决长文本外推难题(附Torch复现)

Transformer长文本处理实战&#xff1a;RoPE位置编码的工程化解决方案 在构建现代NLP系统时&#xff0c;处理长文本序列一直是Transformer架构面临的重大挑战。当序列长度超过模型预训练时的最大位置编码范围时&#xff0c;传统方法的性能会显著下降。这种现象在构建聊天机器人…...

图片去水印 API 接口实战:网站如何实现自动去水印(Python / PHP / C#)

在做网站或后台系统时&#xff0c;一个很常见但容易被忽视的问题是&#xff1a; &#x1f449; 用户上传的图片自带水印 &#x1f449; 平台展示希望统一成干净版本 &#x1f449; 还要支持批量、自动化处理 &#x1f449; 最好能无缝接入现有系统 如果你正在找&#xff1a; …...

从“Hello World”到区域赛银牌:我的ACM算法打怪升级全记录(附各阶段工具包)

从“Hello World”到区域赛银牌&#xff1a;我的ACM算法打怪升级全记录 记得大一刚接触编程时&#xff0c;连最简单的冒泡排序都要调试半天。三年后站在领奖台上&#xff0c;回想这段旅程&#xff0c;最珍贵的不是奖牌&#xff0c;而是那些深夜debug的坚持和突破自我的瞬间。这…...

5分钟精通Meld文件对比工具:效率倍增的3大场景实战指南

5分钟精通Meld文件对比工具&#xff1a;效率倍增的3大场景实战指南 【免费下载链接】meld Read-only mirror of https://gitlab.gnome.org/GNOME/meld 项目地址: https://gitcode.com/gh_mirrors/me/meld Meld是一款开源的可视化文件对比工具&#xff0c;能够帮助开发者…...

Java实现海康萤石摄像头实时监控与视频流获取全攻略

1. 海康萤石摄像头接入前的准备工作 第一次接触海康萤石摄像头开发时&#xff0c;我花了整整两天时间才搞明白整个接入流程。这里把踩过的坑都总结出来&#xff0c;让你少走弯路。首先需要明确的是&#xff0c;萤石开放平台提供了完整的API文档和SDK支持&#xff0c;但实际开发…...

用快马平台快速原型你的技能学习器:AI一键生成交互式教程项目

最近在尝试做一个交互式Python技能学习生成器&#xff0c;发现用InsCode(快马)平台可以特别高效地完成原型验证。这个工具的核心思路是让用户输入想学习的技能&#xff0c;系统就能自动生成完整的学习项目&#xff0c;包含理论、示例和练习。下面分享下具体实现过程&#xff1a…...

别再写低效循环了:深入理解Qt隐式共享与C++17的std::as_const

别再写低效循环了&#xff1a;深入理解Qt隐式共享与C17的std::as_const 在代码审查中&#xff0c;你是否经常看到这样的写法&#xff1f; const QStringList& list oldList; for (auto& str : list) {// 处理字符串 }这种看似"规范"的写法&#xff0c;实际上…...