Service&BroadcastReceiver&Activity

Android四大组件与Service、BroadcastReceiver、ContentProvider的应用与实践
本文深入探讨Android四大组件(Activity、Service、BroadcastReceiver、ContentProvider)的应用与实践,详细解析了各组件的实现原理与代码示例,包括Service的生命周期、BroadcastReceiver的注册与发送广播、ContentProvider的使用等,同时提供了实例代码帮助开发者快速理解并应用到实际项目中。

Android四大组建相信大家对Activity都不陌生吧,但是相对serivice和BroadcastReceiver相对抽象的控件大家应该接触的比较少吧,Contentprovider这个比较形象直观,而且相比之下是用的比较多的,日后的博客会写到,好废话不多说,上代码:

首先看一下主页面的布局:


这里广播下载图片没有做,以后会补上的,用静态变量模拟了一下登录的实现,成功与不成功跳转到不同的页面,电量可以实时监控,但是时间博主不应该那么放的,应该放在线程或者handler里面,不然直接放在UI主线程是不会更新的,当时没考虑到

mainactivity

package cn.edu.sjzc.service.activity;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.webkit.WebChromeClient.CustomViewCallback;
import android.widget.Button;
import android.widget.RemoteViews;
import android.widget.TextView;
import android.widget.Toast;
import cn.edu.sjzc.service.service.MusicService;
import cn.edu.sjzc.service.R;

public class MainActivity extends BaseActivity implements OnClickListener {

    private Button start, end, bind, unbind, login, exit, sign, broad, shut,
            broad_two, shut_two;
    private TextView mtime;
    private TextView battery;

    private static String TAG = "生命周期";
    private static String nowbattery;

    private boolean isBind = false;

    private BatteryBroadcastReceiver batteryBroadcastReceiver;

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

        Log.i(TAG, "onCreate方法执行");

        initView();
        trendsBroad();

    }

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        // 取消注册
        // unregisterReceiver(batteryBroadcastReceiver);
    }

    private void trendsBroad() {
        IntentFilter mFilter = new IntentFilter();
        mFilter.addAction("android.intent.action.BATTERY_CHANGED");
        batteryBroadcastReceiver = new BatteryBroadcastReceiver();
        registerReceiver(batteryBroadcastReceiver, mFilter);
    }

    private void initView() {
        this.start = (Button) MainActivity.this.findViewById(R.id.start);
        this.start.setOnClickListener(this);

        this.end = (Button) MainActivity.this.findViewById(R.id.end);
        this.end.setOnClickListener(this);

        this.bind = (Button) MainActivity.this.findViewById(R.id.bind);
        this.bind.setOnClickListener(this);

        this.unbind = (Button) MainActivity.this.findViewById(R.id.unbind);
        this.unbind.setOnClickListener(this);

        this.login = (Button) MainActivity.this.findViewById(R.id.denglu);
        this.login.setOnClickListener(this);

        this.exit = (Button) MainActivity.this.findViewById(R.id.tuichu);
        this.exit.setOnClickListener(this);

        this.sign = (Button) MainActivity.this.findViewById(R.id.sign);
        this.sign.setOnClickListener(this);

        this.broad = (Button) MainActivity.this.findViewById(R.id.broad);
        this.broad.setOnClickListener(this);

        this.shut = (Button) MainActivity.this.findViewById(R.id.shut);
        this.shut.setOnClickListener(this);

        this.broad_two = (Button) MainActivity.this.findViewById(R.id.kaishi);
        this.broad_two.setOnClickListener(this);

        this.shut_two = (Button) MainActivity.this.findViewById(R.id.tingzhi);
        this.shut_two.setOnClickListener(this);

        this.mtime = (TextView) MainActivity.this.findViewById(R.id.mtime);
        this.mtime.setText(getNowTime());

        this.battery = (TextView) MainActivity.this.findViewById(R.id.battery);

    }

    private String getNowTime() {
        SimpleDateFormat formatter = new SimpleDateFormat(
                "yyyy年MM月dd日 HH:mm:ss ");
        Date curDate = new Date(System.currentTimeMillis());
        return formatter.format(curDate);
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub

        Intent intent = new Intent(MainActivity.this, MusicService.class);

        switch (v.getId()) {
            case R.id.start:
                startService(intent);
                break;
            case R.id.end:
                stopService(intent);
                break;
            case R.id.bind:
                isBind = true;
                bindService(intent, conn, BIND_AUTO_CREATE);
                break;
            case R.id.unbind:
                if (isBind) {
                    isBind = false;
                    unbindService(conn);
                } else {
                    Toast.makeText(getApplicationContext(), "请先绑定",
                            Toast.LENGTH_SHORT).show();
                }
                break;
            case R.id.denglu:
                mlogin();
                break;
            case R.id.tuichu:
                isLogin = false;
                Toast.makeText(getApplicationContext(), "退出!!!isLogin = false",
                        Toast.LENGTH_SHORT).show();
                break;
            case R.id.sign:
                Intent it_sign = new Intent(MainActivity.this, SignActivity.class);
                startActivity(it_sign);
                break;
            case R.id.broad:
                Intent it_broad = new Intent().setAction(
                        "cn.edu.sjzc.fanyafeng.start").putExtra("music",
                        "xuliang's qimiaozhongdejiyi");
                sendBroadcast(it_broad);
                break;
            case R.id.shut:
                Intent it_shut = new Intent().setAction(
                        "cn.edu.sjzc.fanyafeng.shut").putExtra("stop",
                        "shut down the music");
                sendBroadcast(it_shut);
                break;
            case R.id.kaishi:
                Intent it_broad_two = new Intent().setAction(
                        "cn.edu.sjzc.fanyafeng.broad.two").putExtra("broad download",
                        "broad download one");
                sendBroadcast(it_broad_two);
                break;
            case R.id.tingzhi:
                Intent it_shut_two = new Intent().setAction(
                        "cn.edu.sjzc.fanyafeng.shut.two").putExtra("shut music",
                        "shut the music");
                sendBroadcast(it_shut_two);
                break;

            default:
                break;
        }

    }

    private void mlogin() {
        if (isLogin == false) {
            Toast.makeText(getApplicationContext(), "请先注册!!!isLogin = false",
                    Toast.LENGTH_SHORT).show();
            Intent it_failed = new Intent(MainActivity.this,
                    LoginFailedActivity.class);
            startActivity(it_failed);
        }
        if (isLogin == true) {
            Toast.makeText(getApplicationContext(), "登陆成功!!!isLogin = true",
                    Toast.LENGTH_SHORT).show();
            Intent it_login = new Intent(MainActivity.this,
                    LoginSuccessActivity.class);
            startActivity(it_login);
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        // TODO Auto-generated method stub
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            MainActivity.this.finish();
        }
        return super.onKeyDown(keyCode, event);
    }

    final ServiceConnection conn = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub

        }
    };

    public class BatteryBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            // TODO Auto-generated method stub

            if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
                int level = intent.getIntExtra("level", 0);

                int scale = intent.getIntExtra("scale", 100);

                nowbattery = "电池电量:" + ((level * 100) / scale) + "%";
                Log.i("现在的电池电量", nowbattery);
                MainActivity.this.battery.setText(nowbattery);

                if (level < 15) {
                    Toast.makeText(context, "请充电", Toast.LENGTH_SHORT).show();
                }

            }

        }

    }

}

下面是布局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" >

    <Button
        android:id="@+id/unbind"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/bind"
        android:layout_alignBottom="@+id/bind"
        android:layout_alignParentRight="true"
        android:layout_marginRight="88dp"
        android:text="解绑" />

    <Button
        android:id="@+id/start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView1"
        android:layout_toLeftOf="@+id/unbind"
        android:text="开启音乐播放" />

    <Button
        android:id="@+id/bind"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/start"
        android:layout_below="@+id/end"
        android:layout_marginTop="22dp"
        android:text="绑定Service" />

    <Button
        android:id="@+id/end"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/start"
        android:layout_below="@+id/start"
        android:layout_marginTop="16dp"
        android:text="停止音乐播放服务" />

    

    <Button
        android:id="@+id/denglu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_marginBottom="86dp"
        android:layout_marginLeft="21dp"
        android:text="登录" />

    <Button
        android:id="@+id/sign"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/denglu"
        android:layout_alignBottom="@+id/denglu"
        android:layout_marginLeft="17dp"
        android:layout_toRightOf="@+id/end"
        android:text="注册去" />

    <Button
        android:id="@+id/tuichu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/sign"
        android:layout_centerHorizontal="true"
        android:text="退出" />

    <Button
        android:id="@+id/broad"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="18dp"
        android:layout_toLeftOf="@+id/tuichu"
        android:text="广播进行播放音乐" />

    <Button
        android:id="@+id/shut"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/broad"
        android:layout_alignLeft="@+id/unbind"
        android:text="广播进行取消播放音乐" />

    <TextView
        android:id="@+id/mtime"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/bind"
        android:layout_toLeftOf="@+id/unbind"
        android:text="时间显示" />

    <Button
        android:id="@+id/kaishi"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/denglu"
        android:layout_below="@+id/mtime"
        android:text="广播开始(下载图片)" />

    <Button
        android:id="@+id/tingzhi"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/denglu"
        android:layout_alignRight="@+id/unbind"
        android:layout_marginBottom="16dp"
        android:text="广播开始(下载图片,支持断点下载)" />

    <TextView
        android:id="@+id/battery"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/start"
        android:layout_alignRight="@+id/sign"
        android:text="电量显示" />

</RelativeLayout>

musicservice

package cn.edu.sjzc.service.service;

import cn.edu.sjzc.service.R;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

public class MusicService extends Service {
    // 定义输入日志
    private static String TAG = "生命周期";
    // 定义音乐播放变量
    private MediaPlayer mPlayer;

    private MyBinder mBinder = new MyBinder();

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        Log.i(TAG, "onBind()执行");
//		mPlayer.start();
        return mBinder;
    }

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        Log.i(TAG, "onCreate()执行");//第一个执行
        //R.raw.xxxx其中raw不能换成其他的名称,不然Android识别不出来,囧
        mPlayer = MediaPlayer.create(getApplicationContext(), R.raw.qimiaozhongdejiyi);
        //设置音乐循环播放,这个大家可以想一下Handler其中的Looper
        mPlayer.setLooping(true);
        super.onCreate();
    }



    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        Log.i(TAG, "onDestroy()执行");//停止播放时执行
        mPlayer.stop();
        super.onDestroy();
    }



    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        Log.i(TAG, "onStartCommand()执行");//第二个执行
        mPlayer.start();
        return super.onStartCommand(intent, flags, startId);
    }




    @Override
    public boolean onUnbind(Intent intent) {
        // TODO Auto-generated method stub
        Log.i(TAG, "onUnbind()执行");
        return super.onUnbind(intent);
    }

    @SuppressWarnings("deprecation")
    @Override
    public void onStart(Intent intent, int startId) {
        // TODO Auto-generated method stub
        //onStart方法被谷歌打上了横杠,不建议大家使用
        Log.i(TAG, "onStart()执行");//第三个执行
        //start()方法放在onStartCommand
//		mPlayer.start();
        super.onStart(intent, startId);
    }

    public class MyBinder extends Binder{
        MusicService getService(){
            return MusicService.this;
        }
    }

}
下面是Receiver里面

package cn.edu.sjzc.service.receiver;


import cn.edu.sjzc.service.activity.MainActivity;
import cn.edu.sjzc.service.R;

import android.app.Notification;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class MyBroadReceiver extends BroadcastReceiver {

    private NotificationManager mNotificationManager;

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub

        if (intent.getAction().equals("cn.edu.sjzc.fanyafeng.start")) {

            Log.i("接收的信息为:", "xuliang's qimiaozhongdejiyi");
            // 播放音乐,每次当收到广播都会新建一个任务,这样,虽然下面可以收到停止的广播系统也停止不了
            // 播放音乐,不仅如此,每次都会新建一个任务,这样,当你多次点击广播播放时就会听到有一首歌
            // 在分不同的起点进行播放
            // 那么肯定有人想通过广播既能开始又能停止,绑定Service即可实现
            MediaPlayer.create(context, R.raw.qimiaozhongdejiyi).start();

        }
        if (intent.getAction().equals("cn.edu.sjzc.fanyafeng.shut")) {
            Log.i("接收的信息为:", "shut down the music");
            // 停止播放音乐
            MediaPlayer.create(context, R.raw.qimiaozhongdejiyi).stop();
        }

        if (intent.getAction().equals("cn.edu.sjzc.fanyafeng.broad.two")) {
            Log.i("接收的信息为:", "broad download one");
            // 下载图片

        }
        if (intent.getAction().equals("cn.edu.sjzc.fanyafeng.shut.two")) {
            Log.i("接收的信息为:", "shut the music");
            // 支持断点下载

        }
        if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
            Log.i("接收的信息为:", "系统启动完成");
            // 系统启动完成,测试3.0以下的版本可以检测到此广播,3.1以后收不到此广播,具体的大家可以查查资料
            /**
             * 经过查资料得 Android 3.1开始, 由于安全性的考虑.
             * 程序在安装后,用户没有通过自己的操作来启动程序的话,那么这个程序将收不到android
             * .intent.action.BOOT_COMPLETED这个Intent; 用户通过自己的操作启动过一次程序后,
             * receiver将被激活, 从而收的到android.intent.action.BOOT_COMPLETED Intent.
             */

            Toast.makeText(context, "系统启动完成", Toast.LENGTH_SHORT).show();
        }

    }

    @Override
    public IBinder peekService(Context myContext, Intent service) {
        // TODO Auto-generated method stub
        //查了查资料不知道干嘛的,没看google源码
        return super.peekService(myContext, service);
    }


}
清单文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="cn.edu.sjzc.service">
    <!-- SDCard中创建与删除文件权限 -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <!-- SDCard写入数据权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!-- 联网权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>


    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity
            android:name=".activity.MainActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />


                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service
            android:name="cn.edu.sjzc.service.service.MusicService"
            android:exported="true" >
        </service>


        <receiver android:name="cn.edu.sjzc.service.receiver.MyBroadReceiver" >
            <intent-filter>
                <action android:name="cn.edu.sjzc.fanyafeng.start" />
            </intent-filter>
            <intent-filter>
                <action android:name="cn.edu.sjzc.fanyafeng.shut" />
            </intent-filter>
            <intent-filter>
                <action android:name="cn.edu.sjzc.fanyafeng.broad.two" />
            </intent-filter>
            <intent-filter>
                <action android:name="cn.edu.sjzc.fanyafeng.shut.two" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>


        <activity
            android:name="cn.edu.sjzc.service.activity.LoginSuccessActivity"
            android:label="@string/title_activity_first" >
        </activity>
        <activity
            android:name="cn.edu.sjzc.service.activity.LoginFailedActivity"
            android:label="@string/title_activity_second" >
        </activity>
        <activity
            android:name="cn.edu.sjzc.service.activity.SignActivity"
            android:label="@string/title_activity_third" >
        </activity>


    </application>


</manifest>

四大组建都需要进行清单文件的配置的,否则程序是运行不了的

下面这个下载用了一下notification

package cn.edu.sjzc.service.activity;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.RemoteViews;
import android.widget.TextView;
import android.widget.Toast;
import cn.edu.sjzc.service.R;
import cn.edu.sjzc.service.thread.FileDownloadThread;

public class LoginSuccessActivity extends BaseActivity implements
        OnClickListener {
    private Button download, download_two;
    private ProgressBar progressBar, notificationProgress;
    private NotificationManager manager;
    private TextView notificationTitle, notificationPercent, progresstext;
    private int progress, msize;
    private PendingIntent contentIntent;
    // NotificationManager的滚动提示
    /**
     * NotificationManager的图标,一般不要用彩色,我测试是用系统默认的
     * 还有就是系统带的图片是int类型的,测试Listview显示本地图片时时记得定义int类型 但是如果是网络图片要定义为string类型
     */
    private int icon_download = android.R.drawable.stat_sys_download;
    private String tickerText = "开始下载XXXXXXX";

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

    private void initView() {
        this.download = (Button) LoginSuccessActivity.this
                .findViewById(R.id.download);
        this.download.setOnClickListener(this);

        this.progresstext = (TextView) LoginSuccessActivity.this
                .findViewById(R.id.progresstext);
        this.progressBar = (ProgressBar) LoginSuccessActivity.this
                .findViewById(R.id.progressBar);
        this.notificationTitle = (TextView) LoginSuccessActivity.this
                .findViewById(R.id.notificationTitle);
        this.notificationPercent = (TextView) LoginSuccessActivity.this
                .findViewById(R.id.notificationPercent);
        this.notificationProgress = (ProgressBar) LoginSuccessActivity.this
                .findViewById(R.id.notificationProgress);

        manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        // Notification的Intent,即点击后转向的Activity
        Intent it_notification = new Intent(this, this.getClass());
        it_notification.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        contentIntent = PendingIntent.getActivity(this, 0, it_notification, 0);
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        switch (v.getId()) {
            case R.id.download:
                doDownload();
                break;

            default:
                break;
        }

    }

    /**
     * 使用Handler更新UI界面信息
     */
    @SuppressLint("HandlerLeak")
    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // 创建Notification
            Notification mNotification = new Notification(icon_download,
                    tickerText, System.currentTimeMillis());
            // 设定Notification出现时的声音,看过好多资料都说不建议自定义
            mNotification.defaults |= Notification.DEFAULT_SOUND;
            // 设置是否震动
            mNotification.defaults |= Notification.DEFAULT_VIBRATE;
            // 指定Flag,Notification.FLAG_AUTO_CANCEL意指点击这个Notification后立刻取消自身
            // 符合一般的Notification的运作规范,左划不消失类似QQ
            // mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
            // 通知被左划后消失
            mNotification.flags |= Notification.FLAG_AUTO_CANCEL;
            // 创建RemoteViews用在Notification
            RemoteViews contentView = new RemoteViews(getPackageName(),
                    R.layout.notification_view_download);
            contentView.setTextViewText(R.id.notificationTitle,
                    "Download:正在下载中...");

            progressBar.setProgress(msg.getData().getInt("size"));
            float temp = (float) progressBar.getProgress()
                    / (float) progressBar.getMax();
            int progress = (int) (temp * 100);
            if (progress == 100) {
                // Activity显示
                Toast.makeText(LoginSuccessActivity.this, "下载完成!",
                        Toast.LENGTH_LONG).show();
                // Notification显示
                mNotification.icon = R.drawable.down_success;
                contentView.setTextViewText(R.id.notificationTitle,
                        "Download:下载完成!");

            }
            // notification显示
            contentView.setTextViewText(R.id.notificationPercent, progress + "%");
            contentView.setProgressBar(R.id.notificationProgress, 100,progress, false);
            mNotification.contentView = contentView;
            mNotification.contentIntent = contentIntent;
            manager.notify(1, mNotification);
            // activity显示
            progresstext.setText("下载进度:" + progress + " %");

        }
    };

    /**
     * 下载准备工作,获取SD卡路径、开启线程
     */
    private void doDownload() {

        // 获取SD卡路径
        String path = Environment.getExternalStorageDirectory()
                + "/amosdownload/";
        File file = new File(path);
        // 如果SD卡目录不存在创建
        if (!file.exists()) {
            file.mkdir();
        }
        // 设置progressBar初始化
        progressBar.setProgress(0);

        // 简单起见,我先把URL和文件名称写死,其实这些都可以通过HttpHeader获取到
        String downloadUrl = "http://gdown.baidu.com/data/wisegame/91319a5a1dfae322/baidu_16785426.apk";
        String fileName = "baidu_16785426.apk";
        int threadNum = 5;
        String filepath = path + fileName;

        downloadTask task = new downloadTask(downloadUrl, threadNum, filepath);
        task.start();
    }

    /**
     * 多线程文件下载
     *
     *
     * @2014-8-7
     */
    class downloadTask extends Thread {
        private String downloadUrl;// 下载链接地址
        private int threadNum;// 开启的线程数
        private String filePath;// 保存文件路径地址
        private int blockSize;// 每一个线程的下载量

        public downloadTask(String downloadUrl, int threadNum, String fileptah) {
            this.downloadUrl = downloadUrl;
            this.threadNum = threadNum;
            this.filePath = fileptah;
        }

        @Override
        public void run() {

            FileDownloadThread[] threads = new FileDownloadThread[threadNum];
            try {
                URL url = new URL(downloadUrl);
                URLConnection conn = url.openConnection();
                // 读取下载文件总大小
                int fileSize = conn.getContentLength();
                if (fileSize <= 0) {
                    System.out.println("读取文件失败");
                    return;
                }
                // 设置ProgressBar最大的长度为文件Size
                progressBar.setMax(fileSize);

                // 计算每条线程下载的数据长度
                blockSize = (fileSize % threadNum) == 0 ? fileSize / threadNum
                        : fileSize / threadNum + 1;

                File file = new File(filePath);
                for (int i = 0; i < threads.length; i++) {
                    // 启动线程,分别下载每个线程需要下载的部分
                    threads[i] = new FileDownloadThread(url, file, blockSize,
                            (i + 1));
                    threads[i].setName("Thread:" + i);
                    threads[i].start();
                }

                boolean isfinished = false;
                int downloadedAllSize = 0;
                while (!isfinished) {
                    isfinished = true;
                    // 当前所有线程下载总量
                    downloadedAllSize = 0;
                    for (int i = 0; i < threads.length; i++) {
                        downloadedAllSize += threads[i].getDownloadLength();
                        if (!threads[i].isCompleted()) {
                            isfinished = false;
                        }
                    }
                    // 通知handler去更新视图组件
                    Message msg = mHandler.obtainMessage();
                    msg.getData().putInt("size", downloadedAllSize);
                    mHandler.sendMessage(msg);
                    // Log.d(TAG, "current downloadSize:" + downloadedAllSize);
                    Thread.sleep(1000);// 休息1秒后再读取下载进度
                }

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }

}

时间的话可以和更新进度一样进行更新




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值