演示







简介

从Android 2.3开始新增了一个下载管理类,在SDK的文档中我们查找android.app.DownloadManager可以看到。下载管理类可以长期处理多个HTTP下载任务,客户端只需要给出请求的Uri和存放目标文件的位置即可,下载管理使用了一个AIDL服务器,所以可以放心的在后台执行,同时实例化的方法需要使用getSystemService(Context.DOWNLOAD_SERVICE) ,我们可以轻松的通过新增的这个API实现Android平台上的文件下载操作。

DownloadManager类提供了以下几种方法来处理,
long  enqueue(DownloadManager.Request request)   //存入队列一个新的下载项
ParcelFileDescriptor  openDownloadedFile(long id)  //打开一个下载后的文件用于读取,参数中的long型id是一个provider中的一条记录
Cursor  query(DownloadManager.Query query)  //查询一个下载,返回一个Cursor
int  remove(long... ids)  //取消下载,同时从下载管理中移除这些条
 
我们可以看到提供的方法都比较简单,给我们操作的最终封装成为一个provider数据库的方式进行添加、查询和移除,但是对于查询和添加任务的细节,我们要看看DownloadManager.Request类和DownloadManager.Query 类了。

DownloadManager.Request类
addRequestHeader(String header, String value)  // 添加一个Http请求报头,比如说User-Agent值可以为Android123或Windows XP等等了,主要是给服务器提供标识
setAllowedNetworkTypes(int flags)  //设置允许使用的网络类型,目前仅有两种定义,分别为NETWORK_MOBILE(移动网络)和NETWORK_WIFI,可以使用"|"运算
setAllowedOverMetered(boolean allow)  //是否允许“计量式的网络连接”执行下载操作,默认是true允许的
setAllowedOverRoaming(boolean allowed)  //是否允许使用漫游,默认是true允许的
setDescription(CharSequence description)  //设置Notification的描述信息
setDestinationInExternalFilesDir(Context context, String dirType, String subPath)  //设置将文件存储在【data/data/包名/files】目录;第2个参数是files目录下新建目录的目录名,不存在会自己创建;第3个参数是文件名,如果第3个参数带路径,要确保路径存在;不设置会存在【data/data/com.Android.provider.downloads/cache/】下面
setDestinationInExternalPublicDir(String dirType, String subPath)  //设置将文件存储在sd卡目录
setDestinationUri(Uri uri)  //设置需要下载目标的Uri,可以是http、ftp等等了
setMimeType(String mimeType)  //设置mime类型,这里看服务器配置,一般国家化的都为utf-8编码
setShowRunningNotification(boolean show)  //是否显示下载进度的提示,设为false需要权限【DOWNLOAD_WITHOUT_NOTIFICATION】,已经被废弃了
setNotificationVisibility(int visibility)  //设置Notification的显示和隐藏。取值:DownloadManager.Request.VISIBILITY_VISIBLE(默认值,在下载任务执行的过程中显示,下载完成后自动消失),_VISIBLE_NOTIFY_COMPLETED(下载进行时和完成之后都会显示),_HIDDEN(权限),_VISIBLE_NOTIFY_ONLY_COMPLETION(只有当任务完成时才会显示)
setTitle(CharSequence title)  //设置Notification的标题
setVisibleInDownloadsUi(boolean isVisible)  //设置下载管理类在处理过程中的界面是否显示。Set whether this download should be displayed in the system's Downloads UI. True by default
Google还提供了一个简单的方法来实例化本类,这个构造方法为DownloadManager.Request(Uri uri) ,我们直接填写一个Uri即可,上面的设置使用默认情况。

DownloadManager.Query类
对于当前下载内容的状态,我们可以使用DownloadManager.Query类来获取,本类比较简单,仅仅提供了两个方法。
setFilterById(long... ids)  //根据id来过滤查找
setFilterByStatus(int flags) //根据任务的状态来查找
 

定义的常量

下载的状态完成均是以广播的形式通知大家,目前定义了下面三种Action:
ACTION_DOWNLOAD_COMPLETE//下载完成的动作
ACTION_NOTIFICATION_CLICKED //当用户单击notification中下载管理的某项时触发
ACTION_VIEW_DOWNLOADS //查看下载项

设置Notification的显示和隐藏:
DownloadManager.Request.VISIBILITY_VISIBLE//默认值,在下载任务执行的过程中显示,下载完成后自动消失
DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED//下载进行时和完成之后都会显示
DownloadManager.Request.VISIBILITY_HIDDEN//将不会显示,如果设置该属性的话,必须添加权限android.permission.DOWNLOAD_WITHOUT_NOTIFICATION
DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION//只有当任务完成时才会显示  

DownloadManager类提供的query方法返回一个Cursor对象,其中定义的属性有以下几种:

任务目前的状态保存在这个游标的COLUMN_STATUS 字段中,任务的状态有:
STATUS_FAILED  //失败
STATUS_PAUSED  //暂停
STATUS_PENDING  //等待将开始
STATUS_RUNNING  //正在处理中
STATUS_SUCCESSFUL  //已经下载成功

对于一个尚未完成的项,在Cursor中我们查找COLUMN_REASON字段,可能是以下定义:
ERROR_CANNOT_RESUME  //不能够继续,由于一些其他原因
ERROR_DEVICE_NOT_FOUND  //外部存储设备没有找到,比如SD卡没有插入
ERROR_FILE_ALREADY_EXISTS  //要下载的文件已经存在了,下载管理类是不会覆盖已经存在的文件,所以如果需要重新下载,请先删除以前的文件
ERROR_FILE_ERROR  //可能由于SD卡原因导致了文件错误
ERROR_HTTP_DATA_ERROR  //在Http传输过程中出现了问题
ERROR_INSUFFICIENT_SPACE  //由于SD卡空间不足造成的
ERROR_TOO_MANY_REDIRECTS  //这个Http有太多的重定向,导致无法正常下载
ERROR_UNHANDLED_HTTP_CODE  //无法获取http出错的原因,比如说远程服务器没有响应

ERROR_UNKNOWN  //未知的错误类型


有关暂停的一些状态,同样COLUMN_REASON字段的值,可能是以下定义:
PAUSED_QUEUED_FOR_WIFI  //由于移动网络数据问题,等待WiFi连接能用后再重新进入下载队列。
PAUSED_UNKNOWN  //未知原因导致了任务下载的暂停.
PAUSED_WAITING_FOR_NETWORK  //可能由于没有网络连接而无法下载,等待有可用的网络连接恢复。.

PAUSED_WAITING_TO_RETRY  //由于重重原因导致下载暂停,等待重试。


关于下载目录

指定下载位置,及文件名称
1、request.setDestinationInExternalFilesDir(context,"TestDownload","Test.apk")
官方说明:Set the local destination for the downloaded file to a path within the application's external files directory (as returned by getExternalFilesDir(String).
翻译:给下载文件 “制定” 一个路径,文件路径的“特性”跟 getExternalFilesDir(String)类似。
关于getExternalFilesDir(String):
这个方法的返回值是一个文件夹,这个文件夹是被创建在【/data/data/包名/files/】目录下的,他一般是用来存储你的app运行所需的文件的(如图片的缓存)。默认情况下这个文件夹只有当前app有访问权限,当你的应用程序被卸载之后这个文件夹中的数据也会被清除。

2、request.setDestinationInExternalPublicDir("TestDownload","Test.apk");
官方说明:Set the local destination for the downloaded file to a path within the public external storage directory (as returned by getExternalStoragePublicDirectory(String)).
翻译:这个方法也是用来“制定”一个路径的,这个路径的特性类似于getExternalStoragePublicDirectory(String))
关于getExternalStoragePublicDirectory(String):
这个方法的返回值是一个文件夹,这个文件夹是被创建在你的SD卡根目录的【mnt/sdcard/】
这个文件夹中的内容其他程序都是可以访问的,当你的应用程序被卸载的时候,这个文件夹中的内容不会丢失。

通过Context.getExternalFilesDir()方法可以获取到 SDCard/Android/data/你的应用的包名/files/ 目录,一般放一些长时间保存的数据
通过Context.getExternalCacheDir()方法可以获取到 SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据
如果使用上面的方法,当你的应用在被用户卸载后,SDCard/Android/data/你的应用的包名/ 这个目录下的所有文件都会被删除,不会留下垃圾信息。
而且上面二个目录分别对应 设置->应用->应用详情里面的”清除数据“与”清除缓存“选项
如果要保存下载的内容,就不要放在以上目录下

Activity

public class DownloadManagerActivity extends ListActivity {
    public static final String URL_SMALL_FILE = "http://f2.market.xiaomi.com/download/AppStore/0b6c25446ea80095219649f646b8d67361b431127/com.wqk.wqk.apk";
    public static final String URL_BIG_FILE = "http://f3.market.xiaomi.com/download/AppChannel/099d2b4f6006a4c883059f459e0025a3e1f25454e/com.pokercity.bydrqp.mi.apk";
    private DownloadCompleteReceiver receiver;
    private TextView tv_info;
    private int status = 1;
    public static final int MSG_WHAT_DOWNLOAD_ID = 1;
    private boolean isQueryDownTaskById = false;
    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MSG_WHAT_DOWNLOAD_ID:
                if (isQueryDownTaskById) {
                    long id = (long) msg.obj;
                    tv_info.append("查询结果\n");
                    Map<String, String> map = queryDownTaskById(DownloadManagerActivity.this, id);
                    for (Map.Entry<String, String> k_v : map.entrySet()) {//增强for遍历键值对
                        tv_info.append(k_v + "\n");
                    }
                }
                break;
            }
        };
    };
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        String[] array = { "注册接收DownloadManager三个广播", "取消注册广播接收者", //
                "下载文件到SD卡下的Download目录", "下载文件到SD卡指定目录", "下载文件到/data/data/包名/files/目录", //
                "通过状态查询下载任务", "通过id查询下载任务", };
        for (int i = 0; i < array.length; i++) {
            array[i] = i + "、" + array[i];
        }
        tv_info = new TextView(this);// 将内容显示在TextView中
        tv_info.setTextColor(Color.BLUE);
        tv_info.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
        tv_info.setPadding(20, 10, 20, 10);
        getListView().addFooterView(tv_info);
        setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, new ArrayList<String>(Arrays.asList(array))));
        //加入到ThreadLocal中
        HandlerManager.setHandler(mHandler);
    }
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        switch (position) {
        case 0:
            if (receiver == null) receiver = new DownloadCompleteReceiver();
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);//下载完成的动作
            intentFilter.addAction(DownloadManager.ACTION_NOTIFICATION_CLICKED);//当用户单击notification中下载管理的某项时触发
            intentFilter.addAction(DownloadManager.ACTION_VIEW_DOWNLOADS);//查看下载项
            registerReceiver(receiver, intentFilter);
            break;
        case 1:
            if (receiver != null) {
                unregisterReceiver(receiver);
                receiver = null;
            }
            break;
        case 2:
            simpleDownLoadFileToSdNoUI(this, URL_SMALL_FILE);
            break;
        case 3:
            downLoadFile(this, URL_BIG_FILE, "包青天", new Random().nextInt(1000) + ".apk", DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED, //
                    DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE, true);
            break;
        case 4:
            simpleDownLoadFileToDataNoUI(this, URL_SMALL_FILE);
            break;
        case 5:
            tv_info.setText("\n" + getStatusString(status) + "    的任务有:");
            List<Map<String, String>> runningList = queryDownTaskByStatus(this, status);//共有五种状态
            // 遍历
            for (Map<String, String> hm : runningList) {
                tv_info.append("\n**********************************");
                Set<String> set = hm.keySet();
                for (String key : set) {
                    String value = hm.get(key);
                    tv_info.append("\n" + key + "-" + value);
                }
            }
            //下一个状态
            status = status << 1;
            if (status > (1 << 4)) status = 1;
            break;
        case 6:
            isQueryDownTaskById = true;
            break;
        }
    }
    public static String getStatusString(int status) {
        switch (status) {
        case DownloadManager.STATUS_FAILED:
            return "失败";
        case DownloadManager.STATUS_PAUSED:
            return "暂停";
        case DownloadManager.STATUS_PENDING:
            return "等待";
        case DownloadManager.STATUS_RUNNING:
            return "正在下载";
        case DownloadManager.STATUS_SUCCESSFUL:
            return "下载成功";
        default:
            return "没有这种状态";
        }
    }
    public static void simpleDownLoadFileToSdNoUI(Context mContext, String url) {
        downLoadFile(mContext, url, null, null, DownloadManager.Request.VISIBILITY_HIDDEN, DownloadManager.Request.NETWORK_WIFI, true);
    }
    public static void simpleDownLoadFileToDataNoUI(Context mContext, String url) {
        downLoadFile(mContext, url, null, null, DownloadManager.Request.VISIBILITY_HIDDEN, DownloadManager.Request.NETWORK_WIFI, false);
    }
    /**
     * 使用DownloadManager下载文件
     * @param mContext    上下文
     * @param url                文件路径,请自行确保路径正确
     * @param filePath        子目录名,设为null则不创建子目录
     * @param fileName    文件名,设为null则使用服务器路径中的文件名
     * @param visibility        通知显示的类型,请使用DownloadManager.Request中定义的常量,设置为不显示需要权限DOWNLOAD_WITHOUT_NOTIFICATION
     * @param networkType    只允许在指定的网络类型下下周,请使用DownloadManager.Request中定义的常量,可以使用"|"运算
     * @param isToSdCard    是否保存到SD卡上,设为false则保存到【/data/data/包名/files/】目录下
     */
    public static void downLoadFile(Context mContext, String url, String filePath, String fileName, int visibility, int networkType, boolean isToSdCard) {
        if (url == null || url == "") url = "http://www.sinaimg.cn/dy/slidenews/3_img/2016_22/77542_379697_224394.jpg";
        if (filePath == null || filePath == "") filePath = Environment.DIRECTORY_DOWNLOADS;
        if (fileName == null || fileName == "") fileName = url.substring(url.lastIndexOf("/") + 1);//截取文件名及后缀名
        if (fileName == null || fileName == "") fileName = new SimpleDateFormat("yyyy.MM.dd HH-mm-ss", Locale.CHINA).format(new Date());//截取失败时自动命名
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)).setNotificationVisibility(visibility).setAllowedNetworkTypes(networkType);
        if (isToSdCard) request.setDestinationInExternalPublicDir(filePath, fileName);//以SD卡路径为根路径
        else request.setDestinationInExternalFilesDir(mContext, filePath, fileName);//以【/data/data/包名/files/】为根路径
        ((DownloadManager) mContext.getSystemService(DOWNLOAD_SERVICE)).enqueue(request);//将下载请求放入队列
    }
    public static List<Map<String, String>> queryDownTaskByStatus(Context mContext, int status) {
        DownloadManager.Query query = new DownloadManager.Query();
        query.setFilterByStatus(status);
        Cursor cursor = ((DownloadManager) mContext.getSystemService(DOWNLOAD_SERVICE)).query(query);
        if (cursor != null) {
            List<Map<String, String>> data = new ArrayList<Map<String, String>>();
            while (cursor.moveToNext()) {
                String id = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_ID));
                String title = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TITLE));
                String uri = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                String name = cursor.getString(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_FILENAME));
                //String mStatu = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
                String sizeNow = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));//已下载
                String sizeTotal = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
                Map<String, String> map = new HashMap<String, String>();
                map.put("id", id);
                map.put("title", title);
                map.put("name", name);
                map.put("uri", uri);
                map.put("status", sizeTotal + ":" + sizeNow);
                data.add(map);
            }
            cursor.close();
            return data;
        }
        return null;
    }
    public static Map<String, String> queryDownTaskById(Context mContext, long id) {
        DownloadManager.Query query = new DownloadManager.Query();
        query.setFilterById(id);
        Cursor cursor = ((DownloadManager) mContext.getSystemService(DOWNLOAD_SERVICE)).query(query);
        if (cursor != null) {
            Map<String, String> data = new HashMap<String, String>();
            if (cursor.moveToNext()) {
                String sizeNow = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                String sizeTotal = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
                data.put("sizeNow", sizeNow);
                data.put("sizeTotal", sizeTotal);
            }
            cursor.close();
            return data;
        }
        return null;
    }
}

广播

/** 注册一个广播接收器,当下载完毕后会收到一个android.intent.action.DOWNLOAD_COMPLETE的广播,在这里取出队列里下载任务,进行安装*/
public class DownloadCompleteReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
        Handler mHandler = HandlerManager.getHandler();
        mHandler.sendMessage(Message.obtain(mHandler, DownloadManagerActivity.MSG_WHAT_DOWNLOAD_ID, id));
        if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
            Toast.makeText(context, "编号 " + id + " 的下载任务已经完成!", Toast.LENGTH_SHORT).show();
        } else if (intent.getAction().equals(DownloadManager.ACTION_NOTIFICATION_CLICKED)) {
            Toast.makeText(context, "别瞎点-" + id, Toast.LENGTH_SHORT).show();
        } else if (intent.getAction().equals(DownloadManager.ACTION_VIEW_DOWNLOADS)) {
            Toast.makeText(context, "查看下载项-" + id, Toast.LENGTH_SHORT).show();
        }
        //如果下载的是APK文件,则自动安装
        DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
        Query query = new DownloadManager.Query();
        query.setFilterById(id);
        Cursor cursor = downloadManager.query(query);
        if (cursor != null) {
            if (cursor.moveToFirst()) {
                int status = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS));
                String name = cursor.getString(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_FILENAME));
                String uri = cursor.getString(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_URI));
                String end = name.substring(name.lastIndexOf("."));
                if (end != null && end.equals(".apk") && status == DownloadManager.STATUS_SUCCESSFUL) {
                    Intent mIntent = new Intent(Intent.ACTION_VIEW);
                    mIntent.setDataAndType(Uri.parse(uri), "application/vnd.android.package-archive");
                    mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    context.startActivity(mIntent);
                }
            }
            cursor.close();
        }
    }
}

UI线程共享的Handler

/**在UI线程中均可以使用此Handler,如Activity、Service、BroadcastReceiver,他们用的都是同一个对象,可以方便在相互通讯
 * ThreadLocal会为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
 */
public class HandlerManager {
    private static ThreadLocal<Handler> threadLocal = new ThreadLocal<Handler>();
    public static Handler getHandler() {
        return threadLocal.get();//返回当前线程所对应的线程局部变量
    }
    public static void setHandler(Handler mHandler) {
        threadLocal.set(mHandler);//设置当前线程的线程局部变量的值
    }
}

DownloadManager 下载管理类的更多相关文章

  1. Android公共库(缓存 下拉ListView 下载管理Pro 静默安装 root运行 Java公共类)

    介绍总结的一些android公共库,包含缓存(图片缓存.预取缓存).公共View(下拉及底部加载更多ListView.底部加载更多ScrollView.滑动一页Gallery).及Android常用工 ...

  2. Android下载管理DownloadManager功能扩展和bug修改

    http://www.trinea.cn/android/android-downloadmanager-pro/ 本文主要介绍如何修改Android系统下载管理,以支持更多的功能及部分bug修改和如 ...

  3. 下载的管理类MyDownloadManager

    import android.content.Intent; import android.net.Uri; import java.io.File; import java.io.FileOutpu ...

  4. [转]3天搞定的小型B/S内部管理类软件定制开发项目【软件开发实战10步骤详解】

    本文转自:http://www.cnblogs.com/jirigala/archive/2010/10/07/1845275.html 2010-10-07 21:39 by 通用C#系统架构, 5 ...

  5. 【Cocos2d-X开发学习笔记】第19期:动作管理类(CCActionManager)的使用

    本系列学习教程使用的是cocos2d-x-2.1.4(最新版为3.0alpha0-pre) ,PC开发环境Windows7,C++开发环境VS2010 一.动作管理类 动作管理类CCActionMan ...

  6. nodejs+express-实现文件上传下载管理的网站

    Nodejs+Express-实现文件上传下载管理的网站 项目Github地址(对你有帮助记得给星哟):https://github.com/qcer/updo 后端:基于nodejs的express ...

  7. [Canvas]空战游戏进阶 增加己方子弹管理类

    点此下载源码,可用Chrome打开观看. 图例: 代码: <!DOCTYPE html> <html lang="utf-8"> <meta http ...

  8. [Canvas]空战游戏进阶 增加爆炸管理类

    点此下载源码,欲观看效果请用Chrome打开index.html 图例: 源码: <!DOCTYPE html> <html lang="utf-8"> & ...

  9. 线程池的管理类MyThreadPoolManager

    import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.Executor; import java.ut ...

随机推荐

  1. Xcode 7 warnings: object file was built for newer iOS version than being linked

    编译之后出现: ld: warning: object file xxxxx... was built for newer iOS version (8.1) than being linked (7 ...

  2. Mysql 5.7.9 cmake boost.cmake 处理

    环境Centos 6.7 x64 mininal 今天突然编译Mysql 5.7.9 按之前的cmake .的方式 发现报错了..提示 需要boost -- BOOST_INCLUDE_DIR /us ...

  3. 在线支付接口之PHP支付宝接口开发

    支付接口一般是第三方提供的代收款.付款的平台,可以通过支付接口帮助企业或个人利用一切可以使用的支付方式.常见支付平台:支付宝.快钱.云网支付.财付通. 支付宝页面:订单页面.状态页面.返回页面.--- ...

  4. table 自动换行

    <table border=" align="center" style="table-layout:fixed;word-wrap:break-word ...

  5. python os.walk()遍历

    os.walk()遍历 import os p='/bin' #设定一个路径 for i in os.walk(p): #返回一个元组 print (i) # i[0]是路径 i[1]是文件夹 i[2 ...

  6. UCOS 杂项 笔记

    1.  建立任务和建立数据队列  哪个先建立? 经过试验得知,数据队列和任务的建立先后没有顺序,都可以正常运行. 2.关于主函数的面试问题. 主函数写法有:   int  main()    和voi ...

  7. Windows 批处理文件

    窗口自动关闭:批处理文件执行完之后,窗口会自动关闭,若想执行完之后,窗口不自动关闭的话,在文件末尾添加1. 批处理文件执行完之后,窗口会自动关闭2. 若想执行完之后,窗口不自动关闭的话,在文件末尾添加 ...

  8. Android菜单详解(一)——理解android中的Menu

    前言 今天看了pro android 3中menu这一章,对Android的整个menu体系有了进一步的了解,故整理下笔记与大家分享. PS:强烈推荐<Pro Android 3>,是我至 ...

  9. PYTHONE的WHILE,BREAK,CONTINUE示例

    简短示例: while True: s = raw_input('Enter something : ') if s == 'quit': break if len(s) < 3: print ...

  10. dos命令弹出对话框---Msg命令详解

    标签: dos批处理对话框 2015-11-12 17:20 497人阅读 评论(0) 收藏 举报 脚本(30)  版权声明:本文为博主原创文章,未经博主允许不得转载. dos命令弹出对话框---Ms ...