《第一行代码》笔记(17)——后台下载案例

package com.zjw.myservice4;

import android.Manifest;
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.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

//10.6 p365 服务的最佳实践——完整的下载示例
/*
大概:
1.加上OkHttp的依赖(黄油刀依赖),权限:联网,读取存储卡
2.定义监听接口DownloadListener
3.用AsyncTask来实现下载功能
4.保证AsyncTask可在后台一直运行,创建一个DownloadService服务
5.主布局UI:三个Button,开始,暂停,取消下载
6.主代码
 */

public class PracticeOfService extends AppCompatActivity {

    @BindView(R.id.btn_start_download)
    Button mBtnStartDownload;
    @BindView(R.id.btn_pause_download)
    Button mBtnPauseDownload;
    @BindView(R.id.btn_cancel_download)
    Button mBtnCancelDownload;

    private DownloadService.DownloadBinder mDownloadBinder;

    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mDownloadBinder = (DownloadService.DownloadBinder) service;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_practice_of_service);
        ButterKnife.bind(this);

        //开启服务,绑定服务
        Intent intent = new Intent(this, DownloadService.class);
        startService(intent);
        bindService(intent, mServiceConnection, BIND_AUTO_CREATE);

        //运行时权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
        }
    }

    //点击事件
    @OnClick({R.id.btn_start_download, R.id.btn_pause_download, R.id.btn_cancel_download})
    public void onViewClicked(View view) {
        if(mDownloadBinder==null){
           return;
        }
        switch (view.getId()) {
            case R.id.btn_start_download:
                String url= "https://raw.githubusercontent.com/guolindev/eclipse/master/eclipse-inst-win64.exe";
                mDownloadBinder.startDownload(url);
                break;
            case R.id.btn_pause_download:
                mDownloadBinder.pauseDownload();
                break;
            case R.id.btn_cancel_download:
                mDownloadBinder.cancelDownload();
                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, "You denid the permission,the program will be close", Toast.LENGTH_SHORT).show();
                    finish();
                }
                break;
            default:
                break;
        }
    }

    //解绑
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mServiceConnection);//解绑
    }
}
package com.zjw.myservice4;

import android.app.Notification;
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.Environment;
import android.os.IBinder;
import android.support.v7.app.NotificationCompat;
import android.widget.Toast;

import java.io.File;

public class DownloadService extends Service {
    private DownloadTask mDownloadTask;//后台任务
    private String mDownloadUrl;//下载路径
    //重写监听器的方法
    private DownloadListener mDownloadListener = new DownloadListener() {
        @Override
        public void onProgress(int progress) {
            getNotificationManager().notify(1, getNotification("Downloading...", progress));
        }

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

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

        @Override
        public void onPause() {
            mDownloadTask = null;
            Toast.makeText(DownloadService.this, "Paused", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onCanceled() {
            mDownloadTask = null;
            stopForeground(true);
            Toast.makeText(DownloadService.this, "Canceled", Toast.LENGTH_SHORT).show();
        }
    };

    private DownloadBinder mDownloadBinder = new DownloadBinder();

    @Override
    public IBinder onBind(Intent intent) {
        return mDownloadBinder;
    }

    class DownloadBinder extends Binder {
        public void startDownload(String url) {
            if (mDownloadTask == null){
                mDownloadUrl=url;
                mDownloadTask=new DownloadTask(mDownloadListener);
                mDownloadTask.execute(mDownloadUrl);
                startForeground(1,getNotification("Downloading...",0));
                Toast.makeText(DownloadService.this, "Downloading...", Toast.LENGTH_SHORT).show();
            }
        }

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

        public void cancelDownload() {
            if (mDownloadTask != null){
                mDownloadTask.cancelDownload();
            }else{
                if (mDownloadUrl != null){
                    //取消下载时需要将文件删除,并将通知关闭
                    String fileName = mDownloadUrl.substring(mDownloadUrl.lastIndexOf("/"));//从地址最后的"/"后截取文件名
                    //下载到Environment.DIRECTORY_DOWNLOADS即SD卡的downloads目录
                    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, "Download canceled", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }

    private NotificationManager getNotificationManager() {
        return (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    }

    private Notification getNotification(String title, int progress) {
        Intent intent = new Intent(this, PracticeOfService.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        builder.setContentTitle(title);
        builder.setSmallIcon(R.mipmap.ic_launcher);
        builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
        builder.setContentIntent(pendingIntent);
        if (progress > 0) {
            //进度大于等于0时才需要显示下载进度
            builder.setContentText(progress + "%");
            builder.setProgress(100, progress, false);//参数:最大进度,当前进度,是否使用模糊进度条
        }
        return builder.build();
    }
}
package com.zjw.myservice4;

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;

/**
 * Created by hp on 2017/7/27.
 */

/*
<String,Integer,Integer>
1.传入一个字符串给后台任务
2.表示整形数据为进度显示单位
3.整型数据反馈执行结果
 */
public class DownloadTask extends AsyncTask<String, Integer, Integer> {

    //定义下载状态
    private static final int TYPE_SUCCESS = 0;//下载成功
    private static final int TYPE_FAILED = 1;//下载失败
    private static final int TYPE_PAUSED = 2;//下载暂停
    private static final int TYPE_CANCELED = 3;//下载取消

    //监听器
    private DownloadListener mDownloadListener;

    private boolean isCancelled = false;
    private boolean isPaused = false;

    private int lastProcess;

    //构造方法,获取监听器
    public DownloadTask(DownloadListener downloadListener) {
        mDownloadListener = downloadListener;
    }

    @Override
    protected Integer doInBackground(String... params) {
        //在后台执行下载操作
        InputStream inputStream = null;
        RandomAccessFile savedFile = null;
        File file = null;
        try {
            long downloadedLength = 0;//记录下已经下载的文件长度
            String downloadUrl = params[0];//从传入的参数获取下载地址

            String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/"));//从地址最后的"/"后截取文件名
            //下载到Environment.DIRECTORY_DOWNLOADS即SD卡的downloads目录
            String directory = Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_DOWNLOADS).getPath();
            file = new File(directory, fileName);//组装成完整文件路径,创建文件

            //判断文件存不存在
            if (file.exists()) {
                //如果存在的话读取已经下载的字节数,便于后面的断点续传功能
                downloadedLength = file.length();
            }
            //获取下载文件的总长度
            long contentLength = getContentLength(downloadUrl);
            if (contentLength <= 0) {//文件长度不对,直接下载失败
                return TYPE_FAILED;
            } else if (downloadedLength == contentLength) {//如果下载文件大小和已下载文件大小相同,说明已下完
                return TYPE_SUCCESS;
            }

            //网络请求
            OkHttpClient okHttpClient = new OkHttpClient();
            Request request = new Request.Builder()
                    .addHeader("RANGE", "bytes=" + downloadedLength + "-")//告诉服务器要从哪一个字节开始下载
                    .url(downloadUrl)
                    .build();
            Response response = okHttpClient.newCall(request).execute();

            //处理请求结果
            if (response != null) {
                inputStream = response.body().byteStream();
                savedFile = new RandomAccessFile(file, "rw");
                savedFile.seek(downloadedLength);//跳过已下载的字节
                byte[] b = new byte[1024];
                int len;
                int total = 0;
                while ((len = inputStream.read(b)) != -1) {
                    if (isCancelled) {
                        return TYPE_CANCELED;
                    } else if (isPaused) {
                        return TYPE_PAUSED;
                    } else {
                        total += len;
                        savedFile.write(b, 0, len);
                        //计算已经下载的百分比
                        int progress = (int) ((total + downloadedLength) * 100 / contentLength);
                        publishProgress(progress);
                    }
                }
                response.body().close();
                return TYPE_SUCCESS;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (savedFile != null) {
                    savedFile.close();
                }
                if (isCancelled && (file != null)) {
                    file.delete();
                }
            } catch (Exception e) {
            }
        }
        return TYPE_FAILED;
    }


    @Override
    protected void onProgressUpdate(Integer... values) {
        int process = values[0];
        if (process > lastProcess) {
            mDownloadListener.onProgress(process);
            lastProcess = process;
        }
    }

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

    public void pauseDownload() {
        isPaused = true;
    }

    public void cancelDownload() {
        isCancelled = true;
    }

    //获取下载文件的总长度
    private long getContentLength(String downloadUrl) {
        try {
            //网络请求
            OkHttpClient okHttpClient = new OkHttpClient();
            Request request = new Request.Builder()
                    .url(downloadUrl)
                    .build();
            Response response = okHttpClient.newCall(request).execute();
            if (response != null&&response.isSuccessful()) {
                long contentLength=response.body().contentLength();
                response.close();
                return contentLength;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0;
    }
}
package com.zjw.myservice4;

/**
 * Created by hp on 2017/7/27.
 */

public interface DownloadListener {
    void onProgress(int progress);//通知当前下载进度
    void onSuccess();//通知下载成功事件
    void onFailed();//通知下载失败事件
    void onPause();//通知下载暂停事件
    void onCanceled();//通知下载取消事件
}

转载于:https://my.oschina.net/u/3620480/blog/1491761

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,下面是SparkSQL代码笔记03——连接Hive的中文回复: 在SparkSQL中,我们可以通过以下步骤连接Hive: 1. 首先,需要在SparkSession中启用Hive支持,可以使用以下代码: ``` from pyspark.sql import SparkSession spark = SparkSession.builder \ .appName("SparkSQL Hive Example") \ .config("spark.sql.warehouse.dir", "/user/hive/warehouse") \ .enableHiveSupport() \ .getOrCreate() ``` 其中,`enableHiveSupport()`方法启用了Hive支持,`config("spark.sql.warehouse.dir", "/user/hive/warehouse")`指定了Hive元数据存储的目录。 2. 接下来,我们可以使用`spark.sql()`方法执行Hive SQL语句,例如: ``` spark.sql("show databases").show() ``` 这将显示所有的Hive数据库。 3. 如果需要在SparkSQL中访问Hive表,可以使用以下代码: ``` df = spark.sql("select * from my_hive_table") ``` 其中,`my_hive_table`是Hive中的表名。 4. 如果需要在SparkSQL中创建Hive表,可以使用以下代码: ``` spark.sql("create table my_hive_table (id int, name string)") ``` 这将在Hive中创建一个名为`my_hive_table`的表,包含两个列:`id`和`name`。 以上就是连接Hive的基本步骤。需要注意的是,连接Hive需要在Spark集群中安装Hive,并且需要将Hive的JAR包添加到Spark的CLASSPATH中。 ### 回答2: SparkSQL是Apache Spark的一个组件,它提供了用于分布式数据处理的高级SQL查询引擎。SparkSQL支持连接多种数据源,其中之一就是Hive。 如何连接Hive? 在开始连接Hive之前,我们需要确保Hadoop和Hive的配置已经被正确的设置好了,以便Spark能够访问Hive元数据和数据。 首先,我们需要在Spark环境中添加Hive支持。运行下面的代码: `from pyspark.sql import SparkSession spark = SparkSession.builder \ .appName("hive_support") \ .enableHiveSupport() \ .getOrCreate()` 其中,`.enableHiveSupport()`将启用hive支持。 接下来,我们可以使用SparkSession连接Hive。运行下面的代码: `hive_df = spark.sql("SELECT * FROM default.student")` 其中,“default”是Hive的默认数据库,“student”是Hive数据库中的表名。 如果你要访问非默认的Hive数据库,可以使用下面的代码: `hive_df = spark.sql("SELECT * FROM dbname.student")` 其中,“dbname”是非默认的Hive数据库名。 我们还可以使用HiveContext来连接Hive。运行下面的代码: `from pyspark.sql import HiveContext hive_context = HiveContext(sc)` 其中,“sc”是SparkContext对象。 我们可以像这样从Hive中检索数据: `hive_df = hive_ctx.sql("SELECT * FROM default.student")` 现在你已经成功地连接Hive并从中检索了数据,你可以使用SparkSQL的强大功能对数据进行分析。而在连接Hive之外,在SparkSQL中还可以连接其他数据源,包括MySQL、PostgreSQL、Oracle等。 ### 回答3: Spark SQL是一个强大的分布式计算引擎,它可以支持处理多种数据源,并可通过Spark SQL shell、Spark应用程序或JDBC/ODBC接口等方式进行操作。其中,连接Hive是Spark SQL最常用的数据源之一。下面,将介绍如何通过Spark SQL连接Hive。 1、在Spark配置中设置Hive Support 要连接Hive,首先需要在Spark配置中开启Hive Support。在启动Spark Shell时,可以添加如下参数: ``` ./bin/spark-shell --master local \ --conf spark.sql.warehouse.dir="/user/hive/warehouse" \ --conf spark.sql.catalogImplementation=hive \ --conf spark.sql.hive.metastore.version=0.13 \ --conf spark.sql.hive.metastore.jars=maven ``` 这里以本地模式为例,设置Spark SQL的元数据存储在本地文件系统中,设置Hive为catalog实现,以及为Hive Metastore设置版本和JAR文件路径。根据实际情况,还可以指定其他参数,如Hive Metastore地址、数据库名称、用户名和密码等。 2、创建SparkSession对象 在连接Hive之前,需要先创建SparkSession对象。可以通过调用SparkSession.builder()静态方法来构建SparkSession对象,如下所示: ``` val spark = SparkSession.builder() .appName("SparkSQLTest") .config("spark.sql.warehouse.dir", "/user/hive/warehouse") .enableHiveSupport() .getOrCreate() ``` 这里通过builder()方法指定应用程序名称、元数据存储路径以及启用Hive Support,最后调用getOrCreate()方法创建SparkSession对象。 3、通过Spark SQL操作Hive表 通过Spark SQL连接Hive后,就可以通过Spark SQL语句来操作Hive表了。例如,我们可以使用select语句查询Hive表中的数据: ``` val df = spark.sql("SELECT * FROM tablename") df.show() ``` 其中,select语句指定要查询的列和表名,然后通过show()方法来显示查询结果。 除了查询数据之外,Spark SQL还可以通过insertInto语句将数据插入到Hive表中: ``` val data = Seq(("Alice", 25), ("Bob", 30)) val rdd = spark.sparkContext.parallelize(data) val df = rdd.toDF("name", "age") df.write.mode(SaveMode.Append).insertInto("tablename") ``` 这里先创建一个包含数据的RDD对象,然后将其转换为DataFrame对象,并指定列名。接着,通过insertInto()方法将DataFrame对象中的数据插入到Hive表中。 总之,通过Spark SQL连接Hive可以方便地查询、插入、更新和删除Hive表中的数据,从而实现更加灵活和高效的数据处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值