最近几天开学,所以没有更新博客。今天开始更新。最近我打算每天抽出一些事件看点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网络开发》--HTTP数据通信

    No1: 例如:http://www.*****.com/china/index.htm 1)http:// 代表超文本传送协议,通知*****.com服务器显示web页,通常不用输入 2)www 代 ...

  2. android网络开发之测试机连接到服务器上面

    1:本人使用Tomcat作为服务器软件,首先打开Tomcat.(可以在浏览器中输入http://www.127.0.0.1:8080/查看) 2:服务器后台使用Servelt开发,这里不再讲解. 3: ...

  3. Android网络开发实例(基于抓包实现的网络模拟登录,登出和强制登出)

    学习Android有几个月了,最近喜欢上了网络编程,于是想通过Android写一些一个小程序用于连接外网.在这里非常感谢雪夜圣诞的支持,非常感谢,给我打开新的一扇门. 1.声明,本程序只能用于西南大学 ...

  4. Android网络开发

    1. WebView用法 ①布局文件新建一个WebView,特别注意线性布局和控件的宽高都要匹配父控件 <LinearLayout xmlns:android="http://sche ...

  5. Android网络开发之蓝牙

    蓝牙采用分散式网络结构以及快调频和短包技术,支持点对点及点对多点通信,工作在全球通用的2.4GHz ISM(I-工业.S-科学.M-医学)频段,其数据速率为1Mbps,采用时分双工传输方案.   蓝牙 ...

  6. Android网络开发之基本介绍

    Android平台浏览器采用WebKit引擎,名为ChormeLite,拥有强大扩展特性,每个开发者都可以编写自己的插件. 目前,Android平台有3种网络接口可以使用,分别是:java.net, ...

  7. Android网络开发之实时获取最新数据

    在实际开发中更多的是需要我们实时获取最新数据,比如道路流量.实时天气信息等,这时就需要通过一个线程来控制视图的更新. 示例:我们首先创建一个网页来显示系统当前的时间,然后在Android程序中每隔5秒 ...

  8. Android NDK开发(五)--C代码回调Java代码【转】

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/41862479 在上篇博客里了解了Java层是怎样传递数据到C层代码,并且熟悉了大部 ...

  9. Android NDK开发篇(五):Java与原生代码通信(数据操作)

    尽管说使用NDK能够提高Android程序的运行效率,可是调用起来还是略微有点麻烦.NDK能够直接使用Java的原生数据类型,而引用类型,由于Java的引用类型的实如今NDK被屏蔽了,所以在NDK使用 ...

随机推荐

  1. .NET Core & ASP.NET Core 1.0

    .NET Core & ASP.NET Core 1.0在Redhat峰会上正式发布 众所周知,Red Hat和微软正在努力使.NET Core成为Red Hat企业版Linux (RHEL) ...

  2. 测试css2.1选择器IE6/7/8支持情况,属性选择器/子元素/相邻

    环境 xp ie 8 , ietester <!doctype html> <html> <head> <meta charset="utf-8&q ...

  3. swift-数组array

    // Playground - noun: a place where people can play import UIKit //--------------------------------- ...

  4. javascript每日一练(十四)——弹性运动

    一.弹性运动 运动原理:加速运动+减速运动+摩擦运动: <!doctype html> <html> <head> <meta charset="u ...

  5. C++静态库中使用_declspec(dllexport) 不能导出函数的问题

    在某项目中,有一些静态库,这些静态库中有类型命名的函数GET_XXX.在一次项目结构调整的时候,我想将调用这静态库的代码编译成DLL,并且将这些Get函数导出,我就直接就这些函数前面添加了_decls ...

  6. Boost 库Program Options--第二篇

    程式執行參數處理函式庫:Boost Program Options(2/N) 前一篇已經大致解釋了 Boost Program Options 基本上的使用方法.而這一篇,則來細講一下選項描述(opt ...

  7. 理解js的prototype原型对象

    我们创建的每一个函数都有一个prototype(原型)属性.这个属性是一个指针,指向一个对象,而这个对象的用途是包括能够由特定类型的全部实例共享的属性和方法.假设依照字面意思来理解,那么prototy ...

  8. Java基础08 继承

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 继承(inheritance)是面向对象的重要概念.继承是除组合(composit ...

  9. 为进度条增加“伪进度条”?(使用QEventLoop和QTimer)

    在实际开发中,可能会遇到这样的场景:“一个操作非常耗时,但却无法获取其进度百分比”.造成这种情况的原因可能有: 1)该操作属于第三方库(泛指我们使用但无法修改的第三方代码,因此质量有高有底),可能由于 ...

  10. VDI转vmdk(VirtualBox与VMware硬盘格式转换)[转]

    VirtualBox用了一段时间,感觉没想像中那么的好.虽然设置里可以分配多CPU,但是分配多CPU后经常系统挂掉.整体感觉不够稳定,但它也有好处就是开源免费.但经常挂机总不能一直使用它,索性转到Vm ...