在工作的时候,APP改造时,精选页面和生活页面上面都有广告轮廓图片进行滚动,已达到宣传作用。而这些广告图片需要在內管中进行维护,然后我在內管中写了一个维护的方法,将图片保存在了linux服务上的一个分区下,保存图片的路径是: /home/weblogic/pdsebank/ibs/uploadTemp/pmobile/

该路径下是在內管中上传的图片(格式为.png),并将这些图片的名字、描述、路径等信息保存在了数据库中的一张表中。然后我在手机银行的后台写了一个接口,去从数据库中获取到了这些广告图片的信息,返回的是一个json格式的数据,其中就有广告图片的路径,路为:/home/weblogic/pdsebank/ibs/uploadTemp/pmobile/chosen_bander1.png(这只是其中一个广告图片的路径)。

然后我在android客户端去访问这个接口,获取到图片的url后,使用sftp访问linux服务器,去该路径下拿到该图片,并保存到本地的sdcard中,然后将sdcard中的图片读取出来,显示到ImageVIew控件中。


大体思路是这样的。

这是我们在我电脑上写的一个小的demo,模拟了工作中的linux服务器(在我电脑上搭建的linux服务器)。如果有什么问题,或者更好的方法请各位大神指教:


这是打印出的参考日志:

android 通过sftp下载文件 安卓手机sftp_android 通过sftp下载文件

这是我在linux服务器上的存放的图片:

android 通过sftp下载文件 安卓手机sftp_android_02

这是运行app后,下载到手机sdcard中的图片

android 通过sftp下载文件 安卓手机sftp_ico_03

代码实现:

需要的工具类,FileUtils.java、SDCardUtils.java是自己做项目写的,直接拿来用。

FileUtils.java

package com.example.test;

import java.io.File;

import android.content.Context;
import android.os.Environment;

public class FileUtils {
	public static final String CACHE = "cache";//缓存目录(主要用于缓存一些文件)
	public static final String ROOT = "GooglePlay";//定义该APP的根目录
	public static final String ICON = "icon";//缓存APP中的图标
	public static Context context;
	public FileUtils(Context context){
		this.context = context;
	}
	/**
	 * 获取缓存图片路径
	 * @return	/mnt/sdcard/GooglePlay/icon
	 */
	public static File getIconDir() {
		return getDir(ICON);
	}
	/**
	 * 获取缓存路径(里面缓存了json文件)
	 * @return	/mnt/sdcard/GooglePlay/cache
	 */
	public static File getCacheDir() {
		return getDir(CACHE);
	}

	public static File getDir(String str) {
		StringBuilder path = new StringBuilder();
		if (isSDAvailable()) {
			path.append(Environment.getExternalStorageDirectory()
					.getAbsolutePath());// /mnt/sdcard
			path.append(File.separator);// '/'
			path.append(ROOT);// /mnt/sdcard/GooglePlay
			path.append(File.separator);
			path.append(str);// /mnt/sdcard/GooglePlay/cache  或者  /mnt/sdcard/GooglePlay/icon
		} else {
			// sd卡不可用
			
			File filesDir = context.getCacheDir();// cache
			path.append(filesDir.getAbsolutePath());// /data/data/com.xbmu.google/cache
			path.append(File.separator);
			path.append(str);
		}
		File file = new File(path.toString());
		if (!file.exists() || !file.isDirectory()) {
			file.mkdirs();// 创建文件夹
		}
		return file;
	}

	/**
	 * 判断sd卡是否可用
	 * 
	 * @return
	 */
	private static boolean isSDAvailable() {
		if (Environment.getExternalStorageState().equals(
				Environment.MEDIA_MOUNTED)) {
			return true;
		}
		return false;
	}

}


SDCardUtils.java

package com.example.test;

import java.io.File;

import android.os.Environment;
import android.os.StatFs;

/**
 * SD卡相关的辅助类
 * 
 * @author zhy
 * 
 */
public class SDCardUtils
{
	private SDCardUtils()
	{
		/* cannot be instantiated */
		throw new UnsupportedOperationException("cannot be instantiated");
	}

	/**
	 * 判断SDCard是否可用
	 * 
	 * @return
	 */
	public static boolean isSDCardEnable()
	{
		return Environment.getExternalStorageState().equals(
				Environment.MEDIA_MOUNTED);

	}

	/**
	 * 获取SD卡路径
	 * 
	 * @return /storage/emulated/0/
	 */
	public static String getSDCardPath()
	{
		return Environment.getExternalStorageDirectory().getAbsolutePath()
				+ File.separator;
	}

	/**
	 * 获取SD卡的剩余容量 单位byte
	 * 
	 * @return
	 */
	public static long getSDCardAllSize()
	{
		if (isSDCardEnable())
		{
			StatFs stat = new StatFs(getSDCardPath());
			// 获取空闲的数据块的数量
			long availableBlocks = (long) stat.getAvailableBlocks() - 4;
			// 获取单个数据块的大小(byte)
			long freeBlocks = stat.getAvailableBlocks();
			return freeBlocks * availableBlocks;
		}
		return 0;
	}

	/**
	 * 获取指定路径所在空间的剩余可用容量字节数,单位byte
	 * 
	 * @param filePath
	 * @return 容量字节 SDCard可用空间,内部存储可用空间
	 */
	public static long getFreeBytes(String filePath)
	{
		// 如果是sd卡的下的路径,则获取sd卡可用容量
		if (filePath.startsWith(getSDCardPath()))
		{
			filePath = getSDCardPath();
		} else
		{// 如果是内部存储的路径,则获取内存存储的可用容量
			filePath = Environment.getDataDirectory().getAbsolutePath();
		}
		StatFs stat = new StatFs(filePath);
		long availableBlocks = (long) stat.getAvailableBlocks() - 4;
		return stat.getBlockSize() * availableBlocks;
	}

	/**
	 * 获取系统存储路径
	 * 
	 * @return
	 */
	public static String getRootDirectoryPath()
	{
		return Environment.getRootDirectory().getAbsolutePath();
	}
}

SFtpUtil.java是自己参考网上的一些大神的例子,自己整合了一下,写出来的。有什么不足之处,请各位大神指教。

package com.example.test;
import java.io.File;
import java.util.Properties;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

public class SFtpUtil {
	private static Session session  = null;
	private static Channel channel = null;
	private static ChannelSftp chSftp = null;
	/**
	 * 链接sftp服务器
	 * @param ftpHost SFTP IP地址
	 * @param ftpUserName SFTP 用户名
	 * @param ftpPassword SFTP用户名密码
	 * @param ftpPort SFTP端口
	 */
	public static void connectFtpService(String ftpHost, String ftpUserName,
			String ftpPassword, int ftpPort){
		JSch jsch = new JSch();
		try {
			session = jsch.getSession(ftpUserName, ftpHost, ftpPort);
			session.setPassword(ftpPassword);
			session.setTimeout(100000);
			Properties config = new Properties();
			config.put("StrictHostKeyChecking", "no");
			session.setConfig(config);
			session.connect();
		} catch (JSchException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	/**
	 * 
	 * @param ftpPath SFTP服务器中文件所在路径 格式: ftptest/aa
	 * @param localPath 下载到本地的位置 格式:H:/download
	 * @param fileName 文件名称
	 * @throws JSchException
	 */
	public static void downloadSftpFile(String ftpPath, String localPath,
			String fileName) throws JSchException {
		

		channel = session.openChannel("sftp");
		channel.connect();
		chSftp  = (ChannelSftp) channel;

		String ftpFilePath = ftpPath + "/" + fileName;
		System.out.println("ftpFilePath:"+ftpFilePath);
		String localFilePath = localPath + File.separatorChar + fileName;
		System.out.println("localFilePath:"+localFilePath);
		try {
			chSftp .get(ftpFilePath, localPath);
		} catch (SftpException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 断开链接
	 */
	public static void disconnetFtpService(){
		try {
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			chSftp.quit();
			channel.disconnect();
			session.disconnect();
		}
	}
}

以上都是我的准备工作,主要实现的逻辑在MainActivity.java类中

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:id="@+id/id_icon"
        android:layout_width="match_parent"
        android:layout_height="160dp" />

</RelativeLayout>


MainActivity.java


package com.example.test;

import java.io.File;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ImageView;

import com.jcraft.jsch.JSchException;

public class MainActivity extends Activity {

	protected static final int LOADING_FAILED = -1;
	protected static final int LOADING_SUCCESS = 0;
	private SFtpUtil ftpUtil;
	private ImageView mImageView;
	private Bitmap bitmap;
	private Handler handler = new Handler(){
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case LOADING_SUCCESS:
				mImageView.setImageBitmap(bitmap);
				break;
			case LOADING_FAILED:
				//图片不存在,设置默认图片
				mImageView.setImageResource(R.drawable.ic_launcher);
				break;

			default:
				break;
			}
			
		};
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		mImageView = (ImageView) findViewById(R.id.id_icon);
		
		FileUtils fileUtils = new FileUtils(getApplicationContext());
		File cacheDir = fileUtils.getCacheDir();
		String cacheDirPath = cacheDir.getAbsolutePath()+File.separator;//	/mnt/sdcard/GooglePlay/cache/
		Log.e("缓存文件目录", cacheDirPath);
		
		File iconDir = fileUtils.getIconDir();//	/mnt/sdcard/GooglePlay/icon
		final String iconDirPath = iconDir.getAbsolutePath()+File.separator;
		Log.e("缓存图标目录", iconDirPath);
		
		final String path = SDCardUtils.getSDCardPath();
		Log.e("SD卡路径", path);//	/storage/emulated/0/
		String rootDirectoryPath = SDCardUtils.getRootDirectoryPath();//	/system
		Log.e("系统存储路径", rootDirectoryPath);
		ftpUtil = new SFtpUtil();
		//开启一个线程去linux服务器上下载东西
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				
				try {
					ftpUtil.connectFtpService("192.168.1.110", "root", "q1w2e3r4", 22);
					ftpUtil.downloadSftpFile("/home/btt",iconDirPath, "chosen_bander1.png");
					ftpUtil.disconnetFtpService();
					File file = new File(iconDirPath);
					Message message = Message.obtain();
					if(file.isDirectory()){//判断文件目录是否存在
						/*
						 * 这种方式存在缺陷,如果该目录(iconDirPath)下不存在我们所需要的图片,
						 * 但是里面又有图片,就不会达到预期的效果
						if(file.list().length>0){//为true,表示该目录(iconDirPath)下存在文件
							String filePath = iconDirPath+"chosen_bander1.png";
							bitmap = BitmapFactory.decodeFile(filePath);
							message.what = LOADING_SUCCESS;							
						}else{
							message.what = LOADING_FAILED;							
						}
						*/
						String[] names = file.list();//获取
						if(names.length>0){//该目录下存在图片
							for (String name : names) {//循环遍历是否是我们在服务器端下载的文件(根据名字去判断)
								if("chosen_bander1.png".equals(name)){
									Log.e(iconDirPath+"目录下的需要展示文件名",name);
									String filePath = iconDirPath+"chosen_bander1.png";
									bitmap = BitmapFactory.decodeFile(filePath);
									message.what = LOADING_SUCCESS;	
								}else{
									Log.e(iconDirPath+"目录下的不需要展示文件名",name);
									message.what = LOADING_FAILED;
								}
							}							
						}else{
							message.what = LOADING_FAILED;
						}
					}else{
						message.what = LOADING_FAILED;							
					}
					handler.sendMessage(message);
				} catch (JSchException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}).start();
		
		/*
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inSampleSize = 2;
		Log.e("图片路径:",iconDirPath+"chosen_bander1.png");
		Bitmap bitmap = BitmapFactory.decodeFile(iconDirPath+"chosen_bander1.png", options);
		mImageView.setImageBitmap(bitmap);
		*/
		
		/*
		Bitmap bmpDefaultPic = null;
		if(bmpDefaultPic==null){
			bmpDefaultPic = BitmapFactory.decodeFile(iconDirPath+"chosen_bander1.png");
		}
		Log.e("bmpDefaultPic", (bmpDefaultPic==null)+"");
		Log.e("图片路径:",iconDirPath+"chosen_bander1.png");
		mImageView.setImageBitmap(bmpDefaultPic);
		*/
		
		/*
		String filePath = iconDirPath+"chosen_bander1.png";
		File file = new File(filePath);
		if(file.exists()){
			 Bitmap bitmap = BitmapFactory.decodeFile(filePath);
			 mImageView.setImageBitmap(bitmap);
		}else{
			//图片不存在,设置默认图片
			mImageView.setImageResource(R.drawable.ic_launcher);
		}
		*/
	}
}

最后千万不要忘了在AndroidManifest.xml文件中配置访问网络的权限与读取sdcard卡的权限:


<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

运行app后,成功将linux服务器上的图片下载到本地的sdcard卡中,并将sdcard中的图片显示在了ImageView控件上。打出的日志如下:

10-23 17:18:04.336: E/缓存文件目录(5558): /storage/emulated/0/GooglePlay/cache/
10-23 17:18:04.346: E/缓存图标目录(5558): /storage/emulated/0/GooglePlay/icon/
10-23 17:18:04.346: E/SD卡路径(5558): /storage/emulated/0/
10-23 17:18:04.346: E/系统存储路径(5558): /system
10-23 17:18:05.826: E//storage/emulated/0/GooglePlay/icon/目录下的需要展示文件名(5558): chosen_bander1.png