最近几天开学,所以没有更新博客。今天开始更新。最近我打算每天抽出一些事件看点Thinkin Java这本书,仔细研究下java,当然也会出这个博客关于Think in java系列的博客,大家可以一起研究下。

不多说,正式进入主题。这篇主要叙述的是关于保存图片的具体功能实现。

我们先来看看UC的

图10.2.13   UC保存图片对话框

图10.2.14   UC文件管理

我们可以看到UC在点击“保存图片”选项后,弹出了一个保存图片的对话框

既然有了参照物,那么我们就首先来进行界面的实现。

为了简单起见,对话框的编写仍旧采用AlertDialog的构建,只需要替换其中的布 局文件就可以了。我们可以简单的将内容的View采用LinearLayout,其中包含两个 LinearLayout,具体的看下面的xml布局配置文件:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_margin="5dp"

android:background="@android:color/white"

android:orientation="vertical">

<LinearLayout

android:id="@+id/dialog_fileName"

android:layout_width="match_parent"

android:layout_height="30dp"

android:orientation="horizontal"

android:layout_marginTop="30dp"

android:layout_marginLeft="10dp"

android:layout_marginRight="10dp"

android:background="@drawable/dialog_back"

>

<TextView

android:id="@+id/dialog_fileName_title"

android:layout_width="80dp"

android:layout_height="match_parent"

android:gravity="center"

android:textSize="15sp"

android:text="@string/fileName"

android:layout_marginLeft="5dp"

android:layout_marginTop="5dp"

android:layout_marginBottom="5dp"

/>

<EditText

android:id="@+id/dialog_fileName_input"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:hint="@string/blank"

android:layout_marginRight="5dp"

android:layout_marginTop="5dp"

android:layout_marginBottom="5dp"

android:background="@null"

/>

</LinearLayout>

<LinearLayout

android:id="@+id/dialog_savePath"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="horizontal"

android:layout_marginLeft="10dp"

android:layout_marginRight="10dp"

android:layout_marginTop="20dp"

android:layout_marginBottom="30dp"

android:background="@drawable/dialog_back"

>

<TextView

android:id="@+id/dialog_savePath_title"

android:layout_width="80dp"

android:layout_height="match_parent"

android:gravity="center"

android:textSize="15sp"

android:text="@string/savePath"

android:layout_marginLeft="5dp"

android:layout_marginTop="5dp"

android:layout_marginBottom="5dp"

/>

<TextView

android:id="@+id/dialog_savePath_enter"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:hint="@string/defaultPath"

android:text="@string/defaultPath"

android:layout_marginRight="5dp"

android:layout_marginTop="5dp"

android:layout_marginBottom="5dp"

android:background="@null"

/>

</LinearLayout>

</LinearLayout>

代码片段10.2.36 保存图片对话框的xml布局文件

具体的预览效果如下:

图10.2.15   对话框内容预览图

因为我们没有权限在手机内存中进行相关操作,所以为了方便起见,我们所有的路    径基础都是以sdcad的路径为基础的。

现在有了保存的界面,我们就可以编写关于文件管理的界面了。不过为了管理方便,  我们将所有的文件操作都放到file包下。现在我们只需要两种操作即可,分别为文件 列表展示与图片下载操作。图片下载先不管他,我们先进行文件展示方面的编写。

文件展示因为需要耗费一定的时间,Android建议我们将所有的耗时操作都放到子 线程中进行。所以,我通过继承了AsynTask类来进行文件展示的操作。

这里需要注意的是所有的耗时操作都是放在doInBackground这个方法当中的,  并且不能将UI线程中的操作放在这个类中,否则会报错。

现在我将这个文件展示类的具体代码放上来:

package com.example.file;

import java.io.File;

import java.text.SimpleDateFormat;

import java.util.ArrayList;

import java.util.Collections;

import java.util.HashMap;

import java.util.List;

import java.util.Locale;

import android.app.Activity;

import android.app.AlertDialog;

import android.app.Dialog;

import android.os.AsyncTask;

import android.os.Environment;

import android.util.Log;

import android.widget.ListView;

import android.widget.SimpleAdapter;

import com.example.androidstudy_web.R;

import com.example.util.SortComparator;

/**

* 文件管理类

* @version     1.0

* @author     本人dddd牛仔

* <hr/>

* */

public class FileShowManager extends AsyncTask<String, String,List<HashMap<String, Object>>>{

private static final String DEG_TAG ="webbrowser_FileManager";

public static final String SDCARD_HOME = Environment.getExternalStorageDirectory().toString();

public static final String DEFAULT_PATH =SDCARD_HOME + "/webbrowserX/download/";

public enum SORTTYPE {

LETTER, DATE,CHILDNUMS

}

private Activityactivity;

private ListViewfileList;

private DialogwaitDialog;

public FileShowManager(Activity activity, ListViewfileListView){

this.activity = activity;

this.fileList = fileListView;

}

@Override

protected void onPreExecute() {

//初始化控件

this.waitDialog =new AlertDialog.Builder(this.activity)

.setMessage("正在加载中...")

.create();

this.waitDialog.setCancelable(false);

this.waitDialog.setCanceledOnTouchOutside(false);

this.waitDialog.show();

super.onPreExecute();

}

@Override

protected List<HashMap<String, Object>>doInBackground(String... params) {

List<HashMap<String, Object>> fileLists =buildListForAdapter(params[0]);

//默认以首字母排序

this.sortByKey(fileLists, SORTTYPE.LETTER);

return fileLists;

}

@Override

protected void onPostExecute(List<HashMap<String, Object>>result) {

//初始化数据

this.initData(result);

fileList.invalidate();

this.waitDialog.dismiss();

super.onPostExecute(result);

}

/**

* 初始化数据

* */

public void initData(List<HashMap<String, Object>>fileLists){

SimpleAdapter adapter = new

SimpleAdapter(this.activity.getApplicationContext(),fileLists,

R.layout.filemanager_list_item,

new String[]{"name","path","childnums","date","img"},

new int[]{R.id.filemanager_item_info_name,R.id.filemanager_item_filePath,

R.id.filemanager_item_info_numsAndDate_nums,R.id.filemanager_item_info_numsAndDate_date,

R.id.filemanager_item_icon});

this.fileList.setAdapter(adapter);

}

/**

* 构建文件List的适配器

* @param path    文件路径

* */

public List<HashMap<String, Object>>buildListForAdapter(String path){

List<HashMap<String, Object>> list = newArrayList<HashMap<String,Object>>();

File rootFile = new File(path);

if(!rootFile.exists()){

//以默认位置打开

rootFile = new File(DEFAULT_PATH);

if(!rootFile.exists()){

//默认位置不存在,进行创建

rootFile.mkdirs();

}

}

File[] currentPathFiles = rootFile.listFiles();

Log.d(DEG_TAG,DEFAULT_PATH+":"+currentPathFiles);

if(!path.equals(SDCARD_HOME)){

HashMap<String, Object> root = new HashMap<String,Object>();

root.put("name", "/");

root.put("img", R.drawable.floder_home_back);

root.put("path", SDCARD_HOME);

root.put("childnums","返回根目录");

root.put("date", "");

list.add(root);

HashMap<String, Object> pmap = new HashMap<String,

Object>();

pmap.put("name", "..");

pmap.put("img", R.drawable.floder_up_back);

pmap.put("path", rootFile.getParent());

pmap.put("childnums","返回上一级");

pmap.put("date", "");

list.add(pmap);

}

if(currentPathFiles!=null){

//如果存在子文件则进行遍历

for (File file : currentPathFiles){

//根据是否为文件夹选择不同的图标

if(file.isDirectory()){

HashMap<String, Object> item = new HashMap<String,Object>();

item.put("img", R.drawable.floder_back);

item.put("name", file.getName());

item.put("path", file.getPath());

item.put("childnums","共有"+this.getDirectoryNums(file)+"项");

item.put("date",new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.CHINA).format(file.lastModified()));

list.add(item);

}

}

}

return list;

}

/**

* 统计文件夹中的文件夹数量

* @param directory文件夹

* */

public int getDirectoryNums(File directory){

if(directory.isDirectory()){

File[] files = directory.listFiles();

return this.getDirectoryNums(files);

}

return -1;

}

/**

* 统计文件夹中的文件夹数量

* @param files   文件夹下的所有文件

* */

public int getDirectoryNums(File[] files){

int nums = 0;

if(files!=null){

for(File file : files){

if(file.isDirectory()){

nums++;

}

}

}

return nums;

}

/**

* List排序

* @param lists   待排序的数组

* @param sortType排列种类

* */

public List<HashMap<String, Object>>sortByKey(List<HashMap<String, Object>> lists, SORTTYPE sortType){

Collections.sort(lists, new SortComparator(sortType));

Log.d(DEG_TAG,"list.sort:["+lists+"]");

return lists;

}

}

代码片段10.2.37 文件列表展示具体代码实现

这里最主要的一个函数就是buildListForAdapter。我通过传入当前的文件   路径来列出当前的所有文件夹以及通过getDirectoryNums这个函数得到每个  子文件夹的具体文件数量。至于为什么只选择显示文件夹,列出的子项数量也为子   文件夹的数量。这是因为UC的功能就是这么实现的,不过UC在删除文件夹的时 候会显示出其他文件,这个不知道是不是UC的一个BUG。

现在这样的文件显示效果是没有顺序可言的。我通过sortByKey的函数,将文 件列表以字母的数序来进行排列,为了以后的扩展性需要,我这里并没有将它写死,   而是传入了枚举变量,通过这个变量类分辨以何种顺序排列。

文件的排列我是通过Collections.sort来实现的,不过这个函数的实现需  要构建一个自定义的Comparator比较器。

具体的比较器实现方法如下:

package com.example.util;

import java.util.Comparator;

import java.util.HashMap;

import com.example.file.FileShowManager;

public class SortComparator implementsComparator<HashMap<String, Object>> {

private FileShowManager.SORTTYPEsortType;

public SortComparator(FileShowManager.SORTTYPE sortType){

this.sortType = sortType;

}

@Override

public int compare(HashMap<String, Object> lhs,HashMap<String, Object> rhs) {

switch(sortType){

case LETTER:

//字母排序

return String.valueOf(lhs.get("name")).compareTo(String.valueOf(rhs.get("name")));

case DATE:

//日期排序

return String.valueOf(lhs.get("date")).compareTo(String.valueOf(rhs.get("date")));

case CHILDNUMS:

//含文件夹数排序

return String.valueOf(lhs.get("childnums")).compareTo(String.valueOf(rhs.get("childnums")));

}

return 0;

}

}

代码片段10.2.38 比较器代码实现

我们根据传入的枚举值,来进行比较,如果为字母排序,则通过传入的单项为    HashMap的实现取得name值来比较,后面的日期与文件数排序也是相同的实现。至于   为什么日期也可以这样实现,那是因为日期的传入是一个字符串的形式。

现在我们可以看下文件列表展示的效果:

图10.2.16   文件列表的展示

如何实现这个界面呢?还是老样子,显示定义xml文件布局,再是根据布局编写相 应的Activity和其功能。

现在放上代码:

<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@android:color/white"

>

<FrameLayout

android:id="@+id/fileManager_title"

android:layout_width="fill_parent"

android:layout_height="46dp"

android:background="@android:color/holo_blue_light"

>

<TextView

android:id="@+id/fileManager_title_text"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/filemanagerTitle"

android:textSize="18sp"

android:textColor="@android:color/white"

android:textStyle="bold"

android:layout_gravity="center"

/>

<Button

android:id="@+id/fileManager_title_newDirectory"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/filemanagerNewDirectory"

android:layout_gravity="right|center_vertical"

android:layout_marginRight="3dp"

android:layout_marginTop="3dp"

android:layout_marginBottom="3dp"

/>

</FrameLayout>

<ListView

android:id="@+id/fileManager_list"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:layout_below="@id/fileManager_title"

android:layout_above="@+id/fileManager_toolbar"

>

</ListView>

<RelativeLayout

android:id="@+id/fileManager_toolbar"

android:layout_width="fill_parent"

android:layout_height="35dp"

android:layout_alignParentBottom="true"

android:background="@drawable/tools_back"

>

<TextView

android:id="@+id/fileManager_toolbar_sure"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/sure"

android:textSize="17sp"

android:textColor="@android:color/black"

android:layout_centerVertical="true"

android:layout_alignParentLeft="true"

android:layout_marginLeft="20dp"

/>

<TextView

android:id="@+id/fileManager_toolbar_cancel"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/cancel"

android:textSize="17sp"

android:textColor="@android:color/black"

android:layout_centerVertical="true"

android:layout_alignParentRight="true"

android:layout_marginRight="20dp"

/>

</RelativeLayout>

</RelativeLayout>

代码片段10.2.39 文件列表展示xml布局页面

我们可以来看看这个布局文件的预览效果:

图10.2.17   文件列表展示预览

文件列表的点击功能可以这样分析,我们在每个列表中加入一个向上的项和返回 根目录的项。这个功能已经在上述的文件展示类中实现了的。在我们点击确定按钮后,   返回当前的url,按取消则是不做任何处理。

因此,我们在activity中需要设置一个全局变量currentPath记录当前的相对路 径。

package com.example.androidstudy_web;

import java.io.File;

import android.app.Activity;

import android.app.AlertDialog;

import android.content.DialogInterface;

import android.content.Intent;

import android.os.Bundle;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.AdapterView;

import android.widget.AdapterView.OnItemClickListener;

import android.widget.AdapterView.OnItemLongClickListener;

import android.widget.Button;

import android.widget.EditText;

import android.widget.ListView;

import android.widget.TextView;

import android.widget.Toast;

import com.example.file.FileShowManager;

import com.example.other.ItemLongClickedPopWindow;

public class FileActivity extends Activity{

private static final String DEG_TAG ="webbrowser_FileManager";

public static final int RESULT_FILEMANAGER = 1;

//文件列表

private ListViewfileList;

//确定取消按钮

private TextViewsure;

private TextViewcancel;

//新建目录按钮

private ButtoncreateNewFloder;

//监听器

private FileManagerOnItemListenerfileManagerOnItemListener;

private FileManagerOnClickListenerfileManagerOnClickListener;

private FileManagerOnItemLongListenerfileManagerOnItemLongListener;

private FileListPopWindowMenufileListPopWindowMenu;

//长按文件列表单项弹出菜单

private ItemLongClickedPopWindowfileListItemLongClickedPopWindow;

//文件管理线程类

private FileShowManagerfileManager;

//当前的路径

private StringcurrentPath;

/**

* 文件管理Actvity

* @param savedInstanceState父Activity信息

* */

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_filemanager);

//初始化控件

this.fileList = (ListView)this.findViewById(R.id.fileManager_list);

this.sure = (TextView)this.findViewById(R.id.fileManager_toolbar_sure);

this.cancel = (TextView)this.findViewById(R.id.fileManager_toolbar_cancel);

this.createNewFloder = (Button)this.findViewById(R.id.fileManager_title_newDirectory);

this.fileManager =new FileShowManager(this,this.fileList);

this.fileManagerOnItemListener =new FileManagerOnItemListener();

this.fileManagerOnClickListener =new FileManagerOnClickListener();

this.fileManagerOnItemLongListener =new FileManagerOnItemLongListener();

//注册监听

this.fileList.setOnItemClickListener(this.fileManagerOnItemListener);

this.fileList.setOnItemLongClickListener(this.fileManagerOnItemLongListener);

this.sure.setOnClickListener(this.fileManagerOnClickListener);

this.cancel.setOnClickListener(this.fileManagerOnClickListener);

this.createNewFloder.setOnClickListener(this.fileManagerOnClickListener);

//启动文件查询线程

currentPath = getIntent().getStringExtra("savePath");

this.fileManager.execute(currentPath);

}

/**

* OnItemClickListener自定义继承类

* 覆盖如下方法:

* 1. onItemClick

* */

private class FileManagerOnItemListener implements OnItemClickListener{

@Override

public void onItemClick(AdapterView<?> parent, View view, int position,

long id) {

TextView path = (TextView) view.findViewById(R.id.filemanager_item_filePath);

currentPath = path.getText().toString();

Log.d(DEG_TAG,"path:"+currentPath);

fileManager = new FileShowManager(FileActivity.this,fileList);

fileManager.execute(currentPath);

}

}

/**

* OnItemLongClickListener自定义继承类

* 覆盖如下方法:

* 1. onItemLongClick

* */

private class FileManagerOnItemLongListener implementsOnItemLongClickListener{

@Override

public boolean onItemLongClick(AdapterView<?> parent, View view,

int position,long id) {

TextView date = (TextView) view.findViewById(R.id.filemanager_item_info_numsAndDate_date);

if(date.getText().toString().equals("")){

return false;

}

fileListItemLongClickedPopWindow =new ItemLongClickedPopWindow(FileActivity.this,ItemLongClickedPopWindow.FILEMANAGER_ITEM_POPUPWINDOW, 200, 200);

fileListItemLongClickedPopWindow.showAsDropDown(view, view.getWidth()/2,-view.getHeight()/2);

TextView deleteFloder = (TextView) fileListItemLongClickedPopWindow.getView(R.id.item_longclicked_deleteFloder);

TextViewnewNameForFloder = (TextView) fileListItemLongClickedPopWindow.getView(R.id.item_longclicked_newNameForFloder);

fileListPopWindowMenu =new FileListPopWindowMenu(view);

deleteFloder.setOnClickListener(fileListPopWindowMenu);

newNameForFloder.setOnClickListener(fileListPopWindowMenu);

return true;

}

}

/**

* OnClickListener自定义继承类

* */

private class FileListPopWindowMenu implements OnClickListener{

private ViewbeLongClickedView;

public FileListPopWindowMenu(View beLongClickedView){

this.beLongClickedView = beLongClickedView;

}

@Override

public void onClick(View v) {

fileListItemLongClickedPopWindow.dismiss();

TextView floderPath = (TextView) beLongClickedView.findViewById(R.id.filemanager_item_filePath);

TextView oldFloderName = (TextView) beLongClickedView.findViewById(R.id.filemanager_item_info_name);

final String floderPathStr = floderPath.getText().toString();

if(v.getId()==R.id.item_longclicked_deleteFloder){

//删除文件夹的实现

new AlertDialog.Builder(FileActivity.this)

.setTitle("删除目录")

.setMessage("是否删除\""+floderPathStr+"\"目录")

.setPositiveButton("删除",new DialogInterface.OnClickListener() {

@Override

publicvoid onClick(DialogInterface dialog, int which) {

File deleteDirectory = newFile(floderPathStr);

if(deleteDirectory.exists()){

deleteDirectory.delete();

fileManager =new FileShowManager(FileActivity.this,fileList);

fileManager.execute(currentPath);

}

}

})

.setNegativeButton("取消",null)

.create()

.show();

}else if(v.getId()==R.id.item_longclicked_newNameForFloder){

//重命名文件夹的实现

View newNameForFloderView = LayoutInflater.from(FileActivity.this).inflate(R.layout.dialog_newnameforfloder,null);

final TextView floderName = (TextView)  newNameForFloderView.findViewById(R.id.dialog_newNameForFloder

_floderName);

floderName.setText(oldFloderName.getText().toString());

new AlertDialog.Builder(FileActivity.this)

.setTitle("重命名")

.setView(newNameForFloderView)

.setPositiveButton("确定",new DialogInterface.OnClickListener() {

@Override

publicvoid onClick(DialogInterface dialog, int which) {

String newFloderName =floderName.getText().toString();

File newNameFloder = new File(floderPathStr);

newNameFloder.renameTo(new File(currentPath +"/" + newFloderName));

fileManager =new FileShowManager(FileActivity.this,fileList);

fileManager.execute(currentPath);

}

})

.setNegativeButton("取消",null)

.create()

.show();

}

}

}

/**

* OnClickListener自定义继承类

* 覆盖如下方法

* 1. onClick

* */

private class FileManagerOnClickListener implements OnClickListener{

@Override

public void onClick(View v) {

if(v.getId()==R.id.fileManager_toolbar_sure){

//确定操作,返回确定的url

Intent intentExtraUrl = new Intent();

intentExtraUrl.putExtra("savePath",currentPath);

setResult(RESULT_FILEMANAGER, intentExtraUrl);

finish();

}else if(v.getId()==R.id.fileManager_toolbar_cancel){

//取消操作,不更改url

setResult(MainActivity.REQUEST_DEFAULT);

finish();

}else if(v.getId()==R.id.fileManager_title_newDirectory){

//新建目录操作

View createNewFolderView = LayoutInflater.from(FileActivity.this).inflate(R.layout.dialog_createnewfloder,null);

final EditText newFloderName = (EditText)createNewFolderView.findViewById(R.id.dialog_createNewFloder_floderName);

new AlertDialog.Builder(FileActivity.this)

.setTitle("创建新目录")

.setView(createNewFolderView)

.setPositiveButton("确定",new DialogInterface.OnClickListener() {

@Override

publicvoid onClick(DialogInterface dialog, int which) {

StringcreateNewpath = currentPath + "/" + newFloderName.getText().toString();

Log.d(DEG_TAG,"createNewpath:"+createNewpath);

File file = new File(createNewpath);

if(!file.exists()){

file.mkdir();

fileManager =new FileShowManager(FileActivity.this,fileList);

fileManager.execute(currentPath);

}else{

//目录已存在,提示无法创建

Toast.makeText(FileActivity.this,"目录已存在", Toast.LENGTH_SHORT).show();

}

}

})

.setNegativeButton("取消",null)

.create()

.show();

}

}

}

@Override

public void onBackPressed() {

setResult(MainActivity.REQUEST_DEFAULT);

super.onBackPressed();

}

}

代码片段10.2.40  文件展示列表的具体实现

注意:这里在默认打开界面的时候就需要加载文件列表,而默认的位置就是保存图  片对话框所显示出来的保存路径。我们每次进行加载的时候都需要重新实例化一个文 件列表展示类,因为继承自AsynTask,只能执行一次execute方法。

因为我们要实现列表单项长按弹出菜单的实现,所以这就需要监听长按的事件。而    对于弹出菜单实现单击事件。上述代码中都有所提及。

至于在弹出保存对话框中的具体代码实现如下:

else if(v.getId()==R.id.item_longclicked_saveImage){

//图片菜单-保存图片

View dialogSaveImg = LayoutInflater.from(MainActivity.this).inflate(R.layout.dialog_saveimg,null);

choosePath = (TextView) dialogSaveImg.findViewById(R.id.dialog_savePath_enter);

imgSaveName = (TextView) dialogSaveImg.findViewById(R.id.dialog_fileName_input);

final String imgName =value.substring(value.lastIndexOf("/") + 1);

imgSaveName.setText(imgName);

choosePath.setOnClickListener(buttonClickedListener);

saveImageToChoosePath =new AlertDialog.Builder(MainActivity.this)

.setTitle("选择保存路径")

.setView(dialogSaveImg)

.setPositiveButton("确定",new

DialogInterface.OnClickListener(){

@Override

publicvoid onClick(DialogInterface dialog, int which) {

Log.d(DEG_TAG,"fileName:"+imgName+",filePath:"+choosePath.getText().toString());

new ImageDownloadManager(MainActivity.this).execute(imgName,value, choosePath.getText().toString());

}

})

.setNegativeButton("取消",null)

.create();

saveImageToChoosePath.show();

}

代码片段10.2.41 弹出保存对话框的具体实现

这里的ImageDownloadManager就是管理下载图片的类,因为耗时的缘故,我们这里仍旧使用AsynTask类。

package com.example.file;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.net.HttpURLConnection;

import java.net.URL;

import android.annotation.SuppressLint;

import android.content.Context;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.os.AsyncTask;

import android.os.Environment;

import android.util.Log;

import android.widget.Toast;

public class ImageDownloadManager extends AsyncTask<String, String,String>{

private static final String DEG_TAG ="webbrowser_FileDownloadManager";

private Filefile;

private Contextcontext;

public ImageDownloadManager(Context context){

this.context = context;

}

@SuppressLint("SdCardPath")

@Override

protected String doInBackground(String... params) {

Log.d(DEG_TAG,"fileName:"+params[0]+",filePath:"+params[2]);

if(params[2].startsWith("/sdcard/")){

//如果是以/sdcard/为开头的,则应保存为sdcard中

params[2] = Environment.getExternalStorageDirectory()+params[2].substring(8);

Log.d(DEG_TAG,"saveImagePath:"+params[2]);

}

try{

URL  url = new URL(params[1]);

HttpURLConnectionconn  =(HttpURLConnection)url.openConnection();

conn.setDoInput(true);

conn.connect();

InputStreaminputStream=conn.getInputStream();

Bitmap imgSave =BitmapFactory.decodeStream(inputStream);

this.writeFile(params[0],params[2], imgSave);

inputStream.close();

}catch(IOException e){

e.printStackTrace();

}

return null;

}

@Override

protected void onPostExecute(String result) {

Toast.makeText(context,"成功下载", Toast.LENGTH_SHORT).show();

super.onPostExecute(result);

}

/**

* 将图片写入

* @param fileName图片名

* @param dirPath    图片路径

* @param Bitmap  图片内容

* */

public void writeFile(String fileName, String dirPath, BitmapimgSave){

try{

File directory = new File(dirPath);

if((directory.exists())&&(directory.isFile())){

directory.delete();

}else{

directory.mkdirs();

}

this.file =new File(dirPath, fileName);

if(this.file.exists()){

this.file.delete();

}

this.file.createNewFile();

FileOutputStream fo = new FileOutputStream(this.file);

imgSave.compress(Bitmap.CompressFormat.PNG, 100, fo);

fo.flush();

fo.close();

}catch(FileNotFoundException e1){

Log.d(DEG_TAG,"文件未找到:"+e1.getMessage());

}catch(IOException e2){

Log.d(DEG_TAG,"文件创建错误:"+e2.getMessage());

e2.printStackTrace();

}

}

}

代码片段10.2.41  下载文件管理类

至此我们的保存图片功能已经完成。

案例:

AndroidStudy_web_v3.1_by 本人dddd牛仔

Android网络:开发浏览器(五)——功能完善之保存图片实现相关推荐

  1. 《Android 网络开发与应用实战详解》——2.3节Android系统架构

    本节书摘来自异步社区<Android 网络开发与应用实战详解>一书中的第2章,第2.3节Android系统架构,作者 王东华,更多章节内容可以访问云栖社区"异步社区"公 ...

  2. 《Android 网络开发与应用实战详解》——2.1节简析Android安装文件

    本节书摘来自异步社区<Android 网络开发与应用实战详解>一书中的第2章,第2.1节简析Android安装文件,作者 王东华,更多章节内容可以访问云栖社区"异步社区" ...

  3. 三、Android网络开发

    传送门 <一.Android Studio的安装和使用> <二.Android界面开发> <三.Android网络开发> <四.狗狗大全应用实战> 视频 ...

  4. Android网络开发技术实战详解

    <Android网络开发技术实战详解> 基本信息 作者: 朱桂英 丛书名: Android移动开发技术丛书 出版社:电子工业出版社 ISBN:9787121173493 上架时间:2012 ...

  5. android 仿微信demo————注册功能完善添加头像功能(移动端)

    android 仿微信demo----微信启动界面实现 android 仿微信demo----注册功能实现(移动端) android 仿微信demo----注册功能实现(服务端) android 仿微 ...

  6. 《Android 网络开发与应用实战详解》——1.3节搭建Android应用开发环境

    本节书摘来自异步社区<Android 网络开发与应用实战详解>一书中的第1章,第1.3节搭建Android应用开发环境,作者 王东华,更多章节内容可以访问云栖社区"异步社区&qu ...

  7. android 仿微信demo————注册功能完善添加头像功能(服务端)

    android 仿微信demo----微信启动界面实现 android 仿微信demo----注册功能实现(移动端) android 仿微信demo----注册功能实现(服务端) android 仿微 ...

  8. Android Studio开发——蓝牙聊天功能

    Android Studio开发--蓝牙聊天功能 蓝牙工作流程 功能要求 实现要点 声明蓝牙权限 添加程序运行的状态描述文本及配色代码 布局文件 蓝牙会话的服务组件ChatService Activi ...

  9. android 网络开发相关资料

    网络编程汇总: 1. http 基础知识和编程 http://www.jianshu.com/p/99dc1f8f62bf 2. socket  udp  tcp 区别与联系 http://jingy ...

最新文章

  1. OpenCV(项目)车牌识别3 -- 模板匹配
  2. SAP 不支持交货单中同一个物料多个行项目HU与序列号组合发货场景
  3. 服务器双系统设置默认,服务器双系统怎么选择
  4. C语言和C++语言在语法上面的部分区别
  5. python sql逐行读取数据库数据,使用python读取数据库中的内容 把爬虫爬到的内容,存储在mysql数据库中...
  6. 微课|玩转Python轻松过二级:第1章课后习题解答
  7. Android开发笔记(一百四十五)仿应用宝的垃圾清理动画
  8. 马斯克认怂和解,特斯拉股价大涨17%,市值回涨78亿美元
  9. 奇妙的证明 —— 0! = 1(a^0=1)
  10. 陈纪修老师《数学分析》 第06章:不定积分 笔记
  11. 世界三大统计分析软件sas splus spss
  12. 蓄电池充电c语言程序,蓄电池的充电方法和蓄电池工作原理
  13. 2018年大数据趋势 :人工智能… 数据分析将包含可视化模型…
  14. matlab 四面体体积
  15. 计算机怎么转换英语版本,电脑英文字母大小写怎么转换
  16. Ubuntu 16.04 使用校园网客户端上网
  17. 【树莓派】基于树莓派,实现无线路由功能
  18. Educational Codeforces Round 49 (Rated for Div. 2)切题报告
  19. PMP 考点 第三章 项目经理的角色
  20. Jmeter测试最大在线用户数

热门文章

  1. 【猿人学WEB题目专解】猿人学第5题
  2. 广州大喜事婚庆公司报价表
  3. 学习云计算怎么样?云服务和云计算有什么区别?
  4. 如何设置条码标签的打印数量
  5. 创造者的品味 转自apple4.us
  6. 怎样使用1M的内存排序100万个8位数
  7. 性能进阶:使用JMeter进行websocket测试【建议收藏】
  8. Python渗透测试之Scapy模块情报收集
  9. IDEA中Tomcat重新加载的几种方式
  10. 信捷PLC 批量传送位 MOV DMOV QMOV