安卓第二版下载实例(个人记录)

okhttp实现下载功能

1.导包
    implementation 'com.squareup.okhttp3:okhttp:4.0.1'
2.创建Java文件
1.DownloadListener.java
public interface DownloadListener {
    void onProgress(int 下载进度);//下载进度
    void onSuccess();//下载成功
    void onFailed();//下载失败
    void onPaused();//下载暂停
    void onCanceled();//下载取消

}

2.DownloadService.java

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Binder;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.widget.Toast;

import androidx.core.app.NotificationCompat;

import java.io.File;

public class DownloadService extends Service {


    //先创建这两个变量
    //通知管理器
    private NotificationManager notimanger;
    private Notification notification;

    private DownloadTask downloadTask;

    private String downloadurl;

    private DownloadListener listener = new DownloadListener() {
        @Override
        public void onProgress(int 下载进度) {
            getNotificationManager().notify(1,getNotification("下载中...",下载进度));



        }



        @Override
        public void onSuccess() {
            downloadTask = null;
            //下载成功时将前台服务通知关闭,并创建一个下载成功的通知
            stopForeground(true);
            getNotificationManager().notify(1,getNotification("下载成功",-1));
            Toast.makeText(DownloadService.this,"下载成功",Toast.LENGTH_SHORT).show();

        }

        @Override
        public void onFailed() {
            downloadTask = null;
            //下载成功时将前台服务通知关闭,并创建一个下载失败的通知
            stopForeground(true);
            getNotificationManager().notify(1,getNotification("下载失败",-1));
            Toast.makeText(DownloadService.this,"下载失败",Toast.LENGTH_SHORT).show();

        }

        @Override
        public void onPaused() {
            downloadTask = null;
            //下载成功时将前台服务通知关闭,并创建一个下载暂停的通知
            Toast.makeText(DownloadService.this,"已暂停",Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onCanceled() {
            downloadTask = null;
            //下载成功时将前台服务通知关闭,并创建一个下载取消的通知
            stopForeground(true);
            Toast.makeText(DownloadService.this,"已取消",Toast.LENGTH_SHORT).show();

        }
    };
    private DownloadBinder mBuilder =new DownloadBinder();


    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return mBuilder;
    }


    class DownloadBinder extends Binder {
        public void startDownload(String url) {
            if (downloadTask == null) {
                downloadurl = url;
                downloadTask = new DownloadTask(listener);
                downloadTask.execute(downloadurl);
                startForeground(1, getNotification("下载中...", 0));
                Toast.makeText(DownloadService.this, "下载中...", Toast.LENGTH_SHORT).show();
            }
        }

        public void pauseDownload() {
            if (downloadTask != null) {
                downloadTask.pauseDownload();
            }
        }

        public void cancelDownload() {
            if (downloadTask != null) {
                downloadTask.cancelDownload();
            } else {
                if (downloadurl != null) {
                    //取消下载时需要将文件删除,并将通知关闭
                    String fileName = downloadurl.substring(downloadurl.lastIndexOf("/"));
                    String directory = Environment.getExternalStoragePublicDirectory
                            (Environment.DIRECTORY_DOWNLOADS).getPath();
                    File file = new File(directory + fileName);
                    if (file.exists()) {
                        file.delete();
                    }
                    getNotificationManager().cancel(1);
                    stopForeground(true);
                    Toast.makeText(DownloadService.this, "已取消", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }


    private Notification getNotification(String title ,int progress) {
        //获取系统通知器
        notimanger = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        //判断低版本系统无法使用

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

            //创建一个渠道("一个通知"这个随便写)
            NotificationChannel noc =  new NotificationChannel("notiid", "一个通知", NotificationManager.IMPORTANCE_HIGH);
            notimanger.createNotificationChannel(noc);

        }



        Intent intent = new Intent(this,MainActivity.class);
        PendingIntent pi = PendingIntent.getActivity(this,0,intent,0);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this,"notiid");//添加渠道
        builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),
                R.mipmap.ic_launcher));
          builder.setSmallIcon(R.drawable.ic_launcher_background);//通知图标,自己准备
        builder.setContentIntent(pi);
        builder.setContentTitle(title);
        if (progress>0){
            //当前进度大于0或等于0时显示下载进度
            builder.setContentText(progress+"%");
            builder.setProgress(100,progress,false);
        }
return builder.build();
    }
    private NotificationManager getNotificationManager() {
        return this.notimanger;
    }

    public DownloadService() {
    }




}
3.DownloadTask.java

import android.os.AsyncTask;
import android.os.Environment;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class DownloadTask extends AsyncTask<String , Integer,Integer> {


    public static final int TYPE_SUCCESS =0;
    public static final int TYPE_FAILED = 1;
    public static final int TYPE_PAUSED = 2;
    public static final int TYPE_CANCELED = 3;

    private DownloadListener listener;
    private boolean isCanceled = false;
    private boolean isPaused = false;
    private int lastProgress;

    public DownloadTask(DownloadListener listener){
        this.listener = listener;
    }



    @Override
    protected Integer doInBackground(String... params) {
        InputStream is = null;
        RandomAccessFile saveFile = null;
        File file = null;
        try {
        long downloadedLength = 0; //记录已经下载的长度
        String downloadurl = params[0];
        String fileName = downloadurl.substring(downloadurl.lastIndexOf("/"));
        String directory = Environment.
                getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();

        file = new File(directory + fileName);
        if (file.exists()){

            downloadedLength = file.length();
        }
        long contentLenght= 0;//文件总字节

            contentLenght = getContentLenght(downloadurl);

        if (contentLenght==0){
            return TYPE_SUCCESS;
        }

        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .addHeader("RANGE","bytes="+downloadedLength+"-")
                .url(downloadurl)
                .build();

        Response response = client.newCall(request).execute();
        if (response!=null){
            is = response.body().byteStream();
            saveFile =new RandomAccessFile(file ,"rw");
            saveFile.seek(downloadedLength);//跳过已经下载的字节
            byte[] b = new byte[1024];
            int total = 0;
            int len;
            while ((len = is.read(b)) != -1){
                if (isPaused){
                    return TYPE_CANCELED;
                }else if (isPaused){
                    return TYPE_PAUSED;
                }else {
                    total +=len;
                    saveFile.write(b,0,len);
                    //计算已下载的百分比
                    int progress = (int) ((total + downloadedLength)*100/contentLenght);
                    publishProgress(progress);
                }
            }
            response.body().contentLength();
            return TYPE_SUCCESS;
        }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
            if (is!=null){
                is.close();
            }
            if (saveFile!=null){
                saveFile.close();
            }
            if (isCanceled&&file!=null){
                file.delete();
            }
        }catch (Exception e){
                e.printStackTrace();
            }}
        return TYPE_FAILED;
    }


    @Override
    protected void onProgressUpdate(Integer... values) {
        int progress = values[0];
        if (progress>lastProgress){
            listener.onProgress(progress);
            lastProgress = progress;
        }
        super.onProgressUpdate(values);
    }

    @Override
    protected void onPostExecute(Integer status) {
        switch (status){
            case TYPE_SUCCESS:
                listener.onSuccess();
                break;
            case TYPE_FAILED:
                listener.onFailed();
                break;
            case TYPE_PAUSED:
                listener.onPaused();
                break;
            case TYPE_CANCELED:
                listener.onCanceled();
            default:
                break;
        }
       super.onPostExecute(status);
    }

    public void pauseDownload(){
        isPaused = true;
    }
    public void cancelDownload(){
        isCanceled = true;
    }














    private long getContentLenght(String downloadurl) throws IOException {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(downloadurl)
                .build();
        Response response = client.newCall(request).execute();
        if (response!= null &&response.isSuccessful()){
            long contentLength = response.body().contentLength();
            response.close();
            return contentLength;
        }
return 0;

    }
}

4.MainActivity.java
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.app.Activity;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button 开始,暂停,取消;

    private DownloadService.DownloadBinder downloadBinder;
    private ServiceConnection serviceConnection =new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            downloadBinder = (DownloadService.DownloadBinder) iBinder;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        开始 = findViewById(R.id.start);
        暂停 = findViewById(R.id.pause);
        取消 = findViewById(R.id.cancel);

        开始.setOnClickListener(this);
        暂停.setOnClickListener(this);
        取消.setOnClickListener(this);
        Intent intent = new Intent(this,DownloadService.class);
        startService(intent);//启动服务
        bindService(intent,serviceConnection,BIND_AUTO_CREATE);//绑定服务
        if (ContextCompat.checkSelfPermission(MainActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(MainActivity.this,new
                    String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
        }



    }
    public void downloadUI(){


    }

    @Override
    public void onClick(View view) {
        if (downloadBinder==null){
            return;
        }else {
            switch (view.getId()){
                case R.id.start:
                    String XZ="http://app.p4p.sogou.com/1/18859786/7918223/e29b11c44d566fc7ead8b809f443eb77/channel_99315971_1122495_e29b11c44d566fc7ead8b809f443eb77.apk?c=0f5d0d470c48f37d15d3fabc1b699e93&sg_vid=Rt0F32_H49t65qPS-gbu5LRO_sXR6CAOo26QmLO66666667rou1R6666666";
                    downloadBinder.startDownload(XZ);
                    break;
                case R.id.pause:
                    downloadBinder.pauseDownload();
                    break;
                case R.id.cancel:
                    downloadBinder.cancelDownload();
           break;
                default:
                    break;
            }
        }

    }


    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode){
            case 1:
                if (grantResults.length>0&& grantResults[0]!= PackageManager.PERMISSION_GRANTED){
                    Toast.makeText(this,"拒绝权限将无法使用程序",Toast.LENGTH_SHORT).show();

                }
                break;
        }

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    unbindService(serviceConnection);
    }
}

3.创建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">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="开始下载"
        tools:layout_editor_absoluteX="75dp"
        tools:layout_editor_absoluteY="60dp"
        tools:ignore="MissingConstraints" />

    <Button
        android:id="@+id/pause"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="暂停下载"
        tools:layout_editor_absoluteX="71dp"
        tools:layout_editor_absoluteY="113dp"
        tools:ignore="MissingConstraints" />

    <Button
        android:id="@+id/cancel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="取消下载"
        tools:layout_editor_absoluteX="75dp"
        tools:layout_editor_absoluteY="170dp"
        tools:ignore="MissingConstraints" />

</LinearLayout>

4.完成注册表


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mny.myllq">

    <!-- 网络权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

    <application

        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplication"

        android:usesCleartextTraffic="true"
            //这里是安卓10.0必要操作{分区存储},不然无法下载
        android:requestLegacyExternalStorage="true">
        <meta-data
            android:name="com.google.android.actions"
            android:resource="@xml/actions" />

                
                //注册服务不用多说了
        <service
            android:name=".DownloadService"
            android:enabled="true"
            android:exported="true" />

        <activity
            android:name=".MainActivity"

            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

根据Android 第一行代码(第2版)总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值