使用阿里云OSS免费实现APP远程更新

注册阿里云(新用户免费试用3个月)

试用 OSS存储

在这里插入图片描述

进入控制台

Bucket列表新建自定义Bucket

在这里插入图片描述

上传文件至Bucket中

在这里插入图片描述

获取文件的网络地址

在这里插入图片描述

设置为公共读写

在项目中添加阿里云sdk

在这里插入图片描述

创建accessKey

在这里插入图片描述

展示网络图片


```java
 imageUrls.add("https://up.oss-cn-hangzhou.aliyuncs.com/APP/banner.png");
     

private void setBannerImageS(){
        for (String imageUrl : imageUrls) {
            Glide.with(requireActivity())
                    .asBitmap()
                    .load(imageUrl)
                    //缓存
//                    .diskCacheStrategy(DiskCacheStrategy.NONE)
//                    .skipMemoryCache(true)
                    .placeholder(R.mipmap.banner3)
                    .into(new CustomTarget<Bitmap>() {
                        @Override
                        public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
                            // 加载成功
                            loadedBitmaps.add(resource);
                            loadedCount++;
                            checkLoadComplete(); // 检查是否所有图片都已加载
                        }

                        @Override
                        public void onLoadCleared(@Nullable Drawable placeholder) {
                            // 清除资源时调用,可以不做处理
                        }

                        @Override
                        public void onLoadFailed(@Nullable Drawable errorDrawable) {
                            super.onLoadFailed(errorDrawable);
                            // 加载失败
                            Log.e("Glide", "图片加载失败: " + imageUrl);
                            loadedCount++;
                            checkLoadComplete();//检查是否所有图片都已加载
                        }
                    });

        }
    }

    private void checkLoadComplete() {
        if (loadedCount == imageUrls.size()) {
            // 所有图片加载完成
            if (loadedBitmaps.size() > 0) {
                // 至少有一张图片加载成功,使用加载成功的图片
                binding.banner.setAdapter(new BannerBitmapAdapter(loadedBitmaps))
                        .setIndicator(new CircleIndicator(getActivity()))
                        .setIndicatorSpace(6)
                        .setIndicatorGravity(IndicatorConfig.Direction.CENTER)
                        .setLoopTime(6000)
                        .setOnBannerListener((data, position) -> {
                            // 图片点击事件
                        }).start();
            } else {
                // 所有图片都加载失败,使用默认图片
                binding.banner.setAdapter(new BannerImageAdapter(imagesUrl))
                        .setIndicator(new CircleIndicator(getActivity()))
                        .setIndicatorSpace(6)
                        .setIndicatorGravity(IndicatorConfig.Direction.CENTER)
                        .setLoopTime(6000)
                        .setOnBannerListener((data, position) -> {
                            // 图片点击事件
                        }).start();
            }
        }
    }

用于远程升级APP


    String ak = "ak";
    String sk = "sk";

    // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
    String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";

    OSSCredentialProvider credentialProvider = new OSSPlainTextAKSKCredentialProvider(ak, sk);
 private void init() {
        ossClient = new OSSClient(requireActivity().getApplicationContext(), endpoint, credentialProvider);

        GetObjectRequest get = new GetObjectRequest("senappup", "APP/app.apk");

        ossClient.asyncGetObject(get, new OSSCompletedCallback<GetObjectRequest, GetObjectResult>() {
            @Override
            public void onSuccess(GetObjectRequest request, GetObjectResult result) {
                // 使用 ExecutorService 代替 AsyncTask 进行文件处理
                ExecutorService executor = Executors.newSingleThreadExecutor();
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        File file = downloadAndSaveFile(result);
                        if (file != null) {
                            // 在主线程安装 APK
                            installApk(requireActivity().getApplicationContext(), file.getAbsolutePath());
                        } else {
                            // 在主线程显示错误信息
                            requireActivity().runOnUiThread(() -> Toaster.showShort("下载或写入文件失败"));
                        }
                    }
                });
            }

            @Override
            public void onFailure(GetObjectRequest request, ClientException clientException, ServiceException serviceException) {
                // 在主线程显示错误信息
                requireActivity().runOnUiThread(() -> {
                    if (clientException != null) {
                        Toaster.showShort("网络请求失败:" + clientException.toString());
                        Log.e("TAG", "onFailure ClientException:" + clientException.toString());
                    }
                    if (serviceException != null) {
                        Toaster.showShort("OSS 服务错误:" + serviceException.toString());
                        Log.e("TAG", "onFailure ServiceException:" + serviceException.toString());
                    }
                });
            }
        });
    }

    private File downloadAndSaveFile(GetObjectResult result) {
        long length = result.getContentLength();
        if (length > 0) {
            byte[] buffer = new byte[(int) length];
            int readCount = 0;
            try {
                while (readCount < length) {
                    int read = result.getObjectContent().read(buffer, readCount, (int) length - readCount);
                    if (read == -1) break; // 检查是否读取到文件末尾
                    readCount += read;
                }
            } catch (IOException e) {
                OSSLog.logInfo(e.toString());
                return null; // 返回 null 表示写入失败
            } finally {
                try {
                    result.getObjectContent().close(); // 确保关闭输入流
                } catch (IOException e) {
                    OSSLog.logInfo(e.toString());
                }
            }

            try {
                String fileName = "your_app.apk";
                File file = new File(requireActivity().getApplicationContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), fileName);
                FileOutputStream fout = new FileOutputStream(file);
                fout.write(buffer);
                fout.close();
                return file; // 返回 File 对象
            } catch (Exception e) {
                OSSLog.logInfo(e.toString());
                return null; // 返回 null 表示写入失败
            }
        }
        return null; // 返回 null 表示文件长度为 0
    }

    /**
     * 安装apk
     */
    private static void installApk(Context mContext, String fileName) {
        Log.d("SelfUpdate", fileName);
        File apk = new File(fileName);
        try {
            // 这里有文件流的读写,需要处理一下异常
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                //如果SDK版本>=24,即:Build.VERSION.SDK_INT >= 24
                String packageName = mContext.getApplicationContext().getPackageName();
                String authority = new StringBuilder(packageName).append(".fileprovider").toString();
                Uri uri = FileProvider.getUriForFile(mContext, authority, apk);
                intent.setDataAndType(uri, "application/vnd.android.package-archive");
            } else {
                Uri uri = Uri.fromFile(apk);
                intent.setDataAndType(uri, "application/vnd.android.package-archive");
            }
            Log.d("SelfUpdate", "installApk");
            mContext.startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
            // 安装的时候会进行版本自动检测,更新版本小于已有版本,是会走当前异常的,注意!
        }
    }
### ThinkPHP 8 中集成阿里云 OSS 的方法 为了实现文件上传到阿里云对象存储服务 (OSS),需要先安装必要的依赖库。通过 Composer 安装 `aliyun/oss-sdk-php` 库可以方便地操作 OSS API[^1]。 #### 一、环境准备 确保项目已引入 SDK: ```bash composer require aliyun/oss-sdk-php ``` 配置 `.env` 文件中的 Aliyun OSS 参数,以便后续调用时读取这些设置值[^2]。 ```ini ALIOSS_ACCESS_KEY_ID=your-access-key-id ALIOSS_ACCESS_KEY_SECRET=your-access-key-secret ALIOSS_BUCKET_NAME=bucket-name ALIOSS_ENDPOINT=http://oss-cn-hangzhou.aliyuncs.com ``` #### 二、创建工具类用于处理 OSS 请求 定义一个新的 PHP 类来封装与 OSS 进行交互的方法,比如上传图片等功能逻辑[^3]。 ```php <?php namespace app\common\service; use OssClient; use think\Exception; class AliOssService { private $accessKeyId; private $accessKeySecret; private $bucketName; private $endpoint; public function __construct() { try{ $this->accessKeyId = config('app.ALIYUN_OSS.ACCESS_KEY_ID'); $this->accessKeySecret = config('app.ALIYUN_OSS.ACCESS_KEY_SECRET'); $this->bucketName = config('app.ALIYUN_OSS.BUCKET_NAME'); $this->endpoint = config('app.ALIYUN_OSS.ENDPOINT'); if(empty($this->accessKeyId)){ throw new Exception("Access Key ID is empty"); } if(empty($this->accessKeySecret)){ throw new Exception("Access Key Secret is empty"); } if(empty($this->bucketName)){ throw new Exception("Bucket Name is empty"); } if(empty($this->endpoint)){ throw new Exception("Endpoint is empty"); } }catch(Exception $e){ echo 'Error:'.$e->getMessage(); } } /** * Upload file to oss server. * * @param string $localFilePath Local path of the file you want upload. * @return array Return an associative array containing object name and url after successful uploading, otherwise return false on failure. */ public function uploadFile(string $localFilePath): ?array { try { // Initialize client instance with your AccessKeyId, AccessKeySecret, Endpoint. $ossClient = new OssClient( $this->accessKeyId, $this->accessKeySecret, $this->endpoint ); // Define Object key in such format "folder/file.ext". $objectKey = basename($localFilePath); // Call putObject method which uploads local file content as a whole into specified bucket under given object name. $result = $ossClient->putObject($this->bucketName,$objectKey,file_get_contents($localFilePath)); // If no exception thrown during execution then it means operation was successfully completed so we can generate URL link pointing towards uploaded resource using provided endpoint address along with generated object identifier returned by previous call. return [ 'name' => $objectKey, 'url' => sprintf('%s/%s', rtrim($this->endpoint,'/'),$objectKey), ]; } catch(OssException $e) { printf(__FUNCTION__ . ": FAILED\n"); printf($e->getMessage() . "\n"); return null; } } } ``` 上述代码展示了如何构建一个简单的 `AliOssService` 工具类来进行基本的对象存储操作,包括初始化客户端实例以及执行具体的上传动作[^4]。 #### 三、控制器内使用该服务完成实际业务需求 当接收到前端传来的文件流之后,在对应的 Controller 方法里实例化之前编写的 Service 并调用相应接口即可轻松实现文件上载至云端的功能[^5]。 ```php public function uploadImage(){ // 获取表单上传文件 $file = request()->file('image'); if ($file){ // 移动到框架应用根目录下的uploads目录中并重命名 $info = $file -> move(ROOT_PATH.'public'.DS.'uploads'); if($info !== false){ // 实例化自定义的服务层组件 $aliOssSvc = new \app\common\service\AliOssService(); // 调用其提供的API函数进行远程服务器上的资源管理活动 $res = $aliOssSvc->uploadFile('.' . DS .'uploads'. DS .$info->getSaveName()); if(!is_null($res)){ // 返回给浏览器端JSON格式的结果集 json(['code'=>0,'msg'=>'success','data'=>$res]); }else{ json(['code'=>-1,'msg'=>"failed"]); } } else{ // 上传失败给出错误信息 json(['code'=>-1,'msg'=>"move failed"]); } }else{ json(['code'=>-1,'msg'=>"no file selected"]); } } ``` 此部分说明了怎样在一个典型的 Web 应用场景下利用刚刚建立起来的帮助程序去达成预期目的——即把用户提交的数据保存到了第三方平台之上[^6]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值