吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 11061|回复: 143
收起左侧

[其他原创] deepseek开发安卓APP教程(以zipsaver(百度网盘不限速)为例)

    [复制链接]
liuxiaomei 发表于 2025-2-22 15:27
本帖最后由 liuxiaomei 于 2025-3-19 13:26 编辑

最近,不少零基础DeepSeek编程的教程涌现出来。我看到有的老师用DeepSeek开发了签到软件,用的是HTML开发。确实,相对于用Java、C++来开发,HTML不用编译,不用装环境,直接用浏览器就能运行。而使用Android Studio来开发APP要困难得多。
我以前学过安卓软件的开发,现在基本上忘得差不多,不过对一些基本的流程还是熟悉的,大模型刚开始火的时候尝试过,文心一言,Kimi之类的软件,但是把代码放进Android studio之后,报错的不少,修改起来很乱。


这几天deepseek比较火,心血来潮我就又试了一下,r1太卡了,我使用的用的是v3模型,让我感到震惊的是,我直接把代码复制进去,居然没有报错,虽然也经历过一些毛病,好在我了解一点安卓开发的流程,APP基本还算能用。然后我还加了一下功能,比如选择保存的后缀名,一件清空保存目录。用文心一言画了个图标。


我开发的这个软件叫zipsaver,起因是我发现百度网盘直接打开200M以下的文件的时候是不限速的,还可以选择其他应用打开,但是保存到本地的缓存文件是加了权限的,正常情况下打不开。



不过百度网盘加载完文件之后可以选择其他应用打开,这个时候其他应用就有了读取这个文件的权限。


我想能不能把那个要下载的文件改成zip,再做一个假应用直接把那个文件保存起来,这样也算是不限速下载文件了。



虽然只能下载保存200M以内的。

于是利用这个原理,我们开发一个可以打开zip,apk的文件的APP(假装能打开),然后拿到这个文件之后,直接保存在本地。


第一步我们先把需求告诉ai
屏幕截图 2025-02-22 125335.png


上面是ai列出来的步骤,最好是能理解为什么要这么做,
  • 比如我先要声明告诉系统能处理zip格式的文件
  • 再通过Intent 获取百度网盘传递的 ZIP 文件,因为应用间是可以通过Intent通信的。
  • 将接收到的 ZIP 文件保存到本地存储,保存文件肯定是需要权限的。

屏幕截图 2025-02-22 133746.png

接着让它把每一行代码都给我写注释。
于是它给你完整的代码和注释,这里已经可以用了,但是它是用java写的我们让它用kotlin写,并且告诉我们一步一步怎么在最新的Android Studio开发这个软件。
最好是分步骤进行,不要一句话几个指令。
屏幕截图 2025-02-22 134325.png
怎么下载安装Android Studio我就不说了,然后创建项目,具体有点出入,毕竟Android Studio版本在更新。
顺带提一下,创建项目会下载一些东西,要下很久,开热点可能快点。
好了现在我们已经有了一个基础的项目了
但是Android Studio默认已经不生成activity_main.xml了
而deepseek代码里面用的是它,可以用选择创建一个,也可以继续提要求。
屏幕截图 2025-02-22 134921.png
什么!报错了,可以用Android Studio的自动修复试试,也可以直接丢给AI
屏幕截图 2025-02-22 135303.png
按它的修改
如果有错误,继续试试上面两个方法。
好的,无论如何,现在已经不报错了。
测试一下
把文件名称修改从zip,然后直接加载,nice!
Screenshot_20250222_140047_com.baidu.netdisk.jpg
好啊,可恶,那我试试源文件就是zip的。
Screenshot_20250222_140109_com.baidu.netdisk.jpg
玩我呢,明明之前还可以,好在修改成apk格式还可以就加载
修改需求
屏幕截图 2025-02-22 140625.png
Screenshot_20250222_140827_com.baidu.netdisk.jpg
Screenshot_20250222_140835_com.example.zipsaver.jpg
很好,我觉得我又能行了。:Dweeqw

但是。。。。
文件去哪了。。。我们看一下代码,看不懂就问下ai。
果不其然,被保存在这个软件的私有目录下了。没有权限打开,这不就和原来的百度网盘一样了吗:'(weeqw
无妨,我们已经离成功很近了。
屏幕截图 2025-02-22 144751.png
遇到没看懂的直接问
屏幕截图 2025-02-22 145040.png
下面它给出了完整代码,稍微看一下,没什么大问题,直接复制粘贴,好的OK没报错
屏幕截图 2025-02-22 145250.png

到这里软件已经能够使用了
Screenshot_20250222_150023_com.example.zipsaver.jpg
接下来我们再做一些功能的完善
屏幕截图 2025-02-22 145446.png
修复图标没有显示在桌面
屏幕截图 2025-02-22 145825.png

修改图标,具体可以在网上搜索更详细准确
屏幕截图 2025-02-22 150214.png
屏幕截图 2025-02-22 150429.png
再添加一键清空按钮
屏幕截图 2025-02-22 150637.png
但是代码是用xml控制的,继续修改
屏幕截图 2025-02-22 150826.png
好像主界面有点空白了,加个图片到里面显示


屏幕截图 2025-02-22 151121.png
但是不断报错,修复也没用,后来仔细看了一下它的说明发现它理解错了
换一种问法
屏幕截图 2025-02-22 151406.png
这个它正确理解了,但是我后来才发现安卓的资源不能以数字开头,需要再修改代码。
比较简单我就直接手动重命名,然后改了一下代码里的名字,再把图片放进它说的那个目录

这是成品。

Screenshot_20250222_105104_com.example.zipsaver.jpg
我想能跟到这里的应该不需要我再说怎么用这个软件吧
不过我还是说一下
  • 文件改名apk
  • 点击打开选择zipsaver


Screenshot_20250222_105238_com.baidu.netdisk.jpg
Screenshot_20250222_105243_com.example.zipsaver.jpg
  • 保存成功,在目录名:百度网盘保存   里面。



这里是详细的代码(kotlin)及其注释
[Java] 纯文本查看 复制代码
package com.restartaltair.zipsaver

import android.annotation.SuppressLint
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Context.MODE_PRIVATE
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.provider.OpenableColumns
import android.provider.Settings
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 检查并请求 MANAGE_EXTERNAL_STORAGE 权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            if (!Environment.isExternalStorageManager()) {
                // 请求 MANAGE_EXTERNAL_STORAGE 权限
                val intent = Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)
                startActivity(intent)
            }
        }

        setContent {
            APKSaverApp(intent)
        }
    }
}

@Composable
fun APKSaverApp(intent: Intent) {
    val context = LocalContext.current
    var message by remember { mutableStateOf("等待接收文件...") }
    var fileType by remember { mutableStateOf(getSavedFileType(context)) } // 获取上次保存的文件类型
    var inputType by remember { mutableStateOf("") } // 用户输入的文件类型

    // 检查 Intent 的 Action 是否是 VIEW(即从其他 App 打开文件)
    if (Intent.ACTION_VIEW == intent.action) {
        // 获取文件的 Uri
        val fileUri = intent.data
        if (fileUri != null) {
            // 检查是否有写入外部存储的权限
            if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
                // 如果没有权限,请求权限
                ActivityCompat.requestPermissions(context as ComponentActivity,
                    arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE), 1)
            } else {
                // 如果有权限,直接保存文件
                saveFileToLocal(context, fileUri, fileType) { success ->
                    message = if (success) "文件保存成功" else "文件保存失败"
                }
            }
        }
    }

    // 显示 UI
    Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
        Column(
            modifier = Modifier.fillMaxSize(),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            // 显示图片的框框
            Box(
                modifier = Modifier
                    .size(200.dp)
                    .clip(RoundedCornerShape(8.dp))
            ) {
                Image(
                    painter = painterResource(id = R.drawable.image_123), // 加载 res/drawable 目录下的 image_123.jpg.png
                    contentDescription = "App 自带图片",
                    modifier = Modifier.fillMaxSize()
                )
            }

            Spacer(modifier = Modifier.height(16.dp))

            Text(text = message, style = MaterialTheme.typography.headlineMedium)

            Spacer(modifier = Modifier.height(16.dp))

            // 输入文件类型
            TextField(
                value = inputType,
                onValueChange = { inputType = it },
                label = { Text("输入保存类型(默认 mp4)") }
            )

            Spacer(modifier = Modifier.height(16.dp))

            // 保存文件类型按钮
            Button(onClick = {
                if (inputType.isNotEmpty()) {
                    fileType = inputType
                    saveFileType(context, fileType) // 保存文件类型
                    message = "保存类型已修改为:$fileType"
                }
            }) {
                Text("确定")
            }

            Spacer(modifier = Modifier.height(16.dp))

            // 一键清空按钮
            Button(onClick = {
                clearFiles(context) { success ->
                    message = if (success) "已清空所有文件" else "清空文件失败"
                }
            }) {
                Text("一键清空")
            }

            Spacer(modifier = Modifier.height(16.dp))

            // 复制路径按钮
            Button(onClick = {
                val folderPath = File(Environment.getExternalStorageDirectory(), "百度网盘保存").absolutePath
                copyToClipboard(context, folderPath)
                message = "路径已复制到剪贴板"
            }) {
                Text("复制保存路径")
            }
        }
    }
}

// 将文件保存到本地
@SuppressLint("Range")
private fun saveFileToLocal(context: android.content.Context, fileUri: Uri, fileType: String, onResult: (Boolean) -> Unit) {
    try {
        // 创建文件夹路径
        val folder = File(Environment.getExternalStorageDirectory(), "百度网盘保存")
        if (!folder.exists()) {
            folder.mkdirs() // 如果文件夹不存在,创建它
        }

        // 获取原始文件名
        val fileName = context.contentResolver.query(fileUri, null, null, null, null)?.use { cursor ->
            if (cursor.moveToFirst()) {
                cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
            } else {
                "downloaded_file"
            }
        } ?: "downloaded_file"

        // 获取文件名(不含后缀)
        val fileNameWithoutExtension = fileName.substringBeforeLast(".") // 获取文件名(不含后缀)

        // 创建输出文件
        val outputFile = File(folder, "$fileNameWithoutExtension.$fileType") // 直接修改后缀名

        // 通过 ContentResolver 打开文件的输入流
        val inputStream: InputStream? = context.contentResolver.openInputStream(fileUri)
        // 创建输出流
        val outputStream = FileOutputStream(outputFile)

        // 定义缓冲区
        val buffer = ByteArray(1024)

        // 读取输入流并写入输出流
        while (true) {
            val readLength = inputStream?.read(buffer) // 读取数据
            if (readLength == null || readLength <= 0) break // 如果读取失败或结束,退出循环
            outputStream.write(buffer, 0, readLength) // 写入数据
        }

        // 关闭输入流和输出流
        inputStream?.close()
        outputStream.close()

        // 返回保存成功
        onResult(true)
    } catch (e: IOException) {
        e.printStackTrace()
        // 返回保存失败
        onResult(false)
    }
}

// 清空文件夹中的所有文件
private fun clearFiles(context: android.content.Context, onResult: (Boolean) -> Unit) {
    try {
        val folder = File(Environment.getExternalStorageDirectory(), "百度网盘保存")
        if (folder.exists() && folder.isDirectory) {
            val files = folder.listFiles()
            if (files != null) {
                for (file in files) {
                    if (file.isFile) {
                        file.delete()
                    }
                }
            }
            onResult(true)
        } else {
            onResult(false)
        }
    } catch (e: Exception) {
        e.printStackTrace()
        onResult(false)
    }
}

// 保存文件类型到 SharedPreferences
private fun saveFileType(context: android.content.Context, fileType: String) {
    val sharedPreferences: SharedPreferences = context.getSharedPreferences("AppSettings", MODE_PRIVATE)
    with(sharedPreferences.edit()) {
        putString("fileType", fileType)
        apply()
    }
}

// 从 SharedPreferences 获取保存的文件类型
private fun getSavedFileType(context: android.content.Context): String {
    val sharedPreferences: SharedPreferences = context.getSharedPreferences("AppSettings", MODE_PRIVATE)
    return sharedPreferences.getString("fileType", "mp4") ?: "mp4" // 默认类型为 mp4
}

// 复制路径到剪贴板
private fun copyToClipboard(context: android.content.Context, text: String) {
    val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
    val clip = ClipData.newPlainText("保存路径", text)
    clipboard.setPrimaryClip(clip)
}


只是提供一个ai开发安卓应用的思路而已,这个应用不知道会不会和谐,也不知道还有什么小毛病,只能说勉强能用吧。
个人建议把网盘的文件修改成改成apk然后预览,zip有的时候直接让你开会员解压压缩包了。
(图片是文小言生成的)(突然发现忘记去水印了)

image.png
我又更新了一下内容,修复了保存后缀是直接添加而不是修改的问题,加上了打开目录。不过这个版本暂时还没上传,因为还有点问题。


免费评分

参与人数 47威望 +1 吾爱币 +65 热心值 +41 收起 理由
moze + 1 + 1 用心讨论,共获提升!
mjhwzwg6 + 1 + 1 用心讨论,共获提升!
云之从 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
傻傻的小鸟 + 1 + 1 热心回复!
m-chris + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
jimmyzang + 3 + 1 我很赞同!
hackMyself + 1 + 1 谢谢@Thanks!
jessegold + 1 + 1 谢谢@Thanks!
junjia215 + 1 + 1 用心讨论,共获提升!
四君子 + 1 我很赞同!
tooooony + 1 + 1 我很赞同!
qmsy273 + 1 我很赞同!
KnowledgeARI + 1 + 1 我很赞同!
Mackenzie + 1 + 1 我很赞同!
Zombie6888 + 1 + 1 谢谢@Thanks!
Pablo + 1 + 1 谢谢@Thanks!
斜雨孤泪 + 1 我很赞同!
李不白哟 + 1 + 1 热心回复!
celebrition + 1 + 1 我很赞同!
小死闺女1号 + 1 + 1 谢谢@Thanks!
zachary0311 + 1 鼓励转贴优秀软件安全工具和文档!
redscop + 1 + 1 我很赞同!
BYSJ86 + 1 热心回复!
nado112 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
wbc008 + 1 + 1 谢谢@Thanks!
halou + 1 + 1 大佬NBPlus!膜拜!
supercc + 2 谢谢@Thanks!
Trayler0309 + 1 谢谢@Thanks!
xliuling + 1 + 1 思路很好,有了思路,可以去寻找实现的路径
AlexMason + 1 + 1 思路很重要!感谢分享
xuhao8588 + 1 + 1 我很赞同!
JinxBoy + 1 谢谢@Thanks!
xintian + 1 + 1 牛逼,大佬厉害
antclt + 1 + 1 我很赞同!
pyjiujiu + 1 + 1 用心讨论,共获提升!
gqdsc + 1 + 1 这也太优秀了吧!
dbu00956 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
shd1971 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
shangtaijai + 1 我很赞同!
bd2856 + 1 + 1 热心回复!
苏紫方璇 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
evalPrivateJS + 1 + 1 我很赞同!
13250020098 + 1 + 1 我很赞同!
RobinMaas + 1 + 1 用心讨论,共获提升!
liuxuming3303 + 1 + 1 谢谢@Thanks!
jtjt68 + 1 真的体会到现在的AI越来越厉害了
zkyuan + 1 + 1 热心回复!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| liuxiaomei 发表于 2025-2-23 13:31
本帖最后由 liuxiaomei 于 2025-2-24 18:27 编辑

更新1.1,修改了包名,可以删掉之前那个老版本
添加了复制保存目录
修复了保存后缀是直接添加而不是修改的问题
修改向下兼容安卓9(没测试能不能用)
去掉了图片的水印
这里下载https://wwsl.lanzoul.com/iVpgw2omej5c
image.png
gaoxiaoao 发表于 2025-2-22 21:50
beichen1031 发表于 2025-3-26 16:15
Lyss07 发表于 2025-2-22 17:05
好详细的流程,收藏学习
shaosw 发表于 2025-2-22 20:47
这个也太棒了吧,谢谢大佬 。
qpqp1414 发表于 2025-2-22 22:28

很详细,可以照猫画猫了。
xm65R 发表于 2025-2-22 23:53
让我大开眼界
老龙王 发表于 2025-2-23 06:45
用得那家部署得deepseek,响应快吗
zkyuan 发表于 2025-2-22 17:14
很详细,可以照猫画猫了。
 楼主| liuxiaomei 发表于 2025-2-22 17:46
好奇怪,之前不小心传入几个图片附件,删掉之后还有,显示在文章最后面了,编辑帖子也删不了
JieRoud 发表于 2025-2-22 21:23
谢谢分享
自在小鱼 发表于 2025-2-22 21:54
看不懂,所以楼主好厉害
hygqx6 发表于 2025-2-22 22:26
这个真不错,思路步骤详细
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-12-18 06:38

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表