2019 Jul. 15.
MyJsch.java
SdCardDirPaths.java
(利用例)
Send2ServerTask.java
MyActivity.java
MyJsch.java
package your.package;
import android.content.Context;
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;
import com.jcraft.jsch.UserInfo;
import java.io.File;
import java.io.InputStream;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
class MyJsch {
private final String ServerIp;
private final int Port;
private final String User;
private final String PassPhraseWord;
private final String IdentityKeyPath;
private final Context AppContext;
/** Channel接続タイプ */
private static final String CHANNEL_TYPE = "sftp";
/*
* コンストラクタ
*/
MyJsch( final String ServerIp, final int Port, final String User, final String PassPhraseWord,
final String IdentityKeyPath, final Context AppContext) {
this.ServerIp = ServerIp;
this.Port = Port;
this.User = User;
this.PassPhraseWord = PassPhraseWord;
this.IdentityKeyPath = IdentityKeyPath;
this.AppContext = AppContext;
}
/*
* Sessionを開始
*/
protected Session connectSession() throws JSchException {
Session session = null;
// android端末内の外部ストーリッジ確認
List sdCardFilesDirPaths =
SdCardDirPaths.getSdCardFilesDirPathListForLollipop( AppContext );
Collections.sort(sdCardFilesDirPaths, new CompStringLength());
String externalPath = sdCardFilesDirPaths.get(0);
externalPath = externalPath.replaceAll("/Android.*$", "");
final JSch jsch = new JSch();
// クライアント側のknownHostsチェックを行わない
Hashtable config = new Hashtable();
config.put("StrictHostKeyChecking", "no");
jsch.setConfig(config);
// パスフレーズ・秘密鍵方式
String privKeyFilePath = externalPath + "/" + IdentityKeyPath;
File privKeyFile = new File(privKeyFilePath);
if (privKeyFile.exists() ) {
jsch.addIdentity(privKeyFilePath, PassPhraseWord);
}
// Session取得
session = jsch.getSession(User, ServerIp, Port);
// パスワード方式でも可とする
session.setPassword(PassPhraseWord);
final UserInfo userInfo = new SftpUserInfo();
session.setUserInfo(userInfo);
session.connect();
return session;
}
/**
* SFTPのChannelを開始
*
* @param session
* 開始されたSession情報
*/
protected ChannelSftp connectChannelSftp(final Session session)
throws JSchException {
final ChannelSftp channel = (ChannelSftp) session.openChannel(CHANNEL_TYPE);
try {
channel.connect();
} catch (JSchException e) {
return null;
}
return channel;
}
/**
* Session・Channelの終了
*
* @param session
* 開始されたSession情報
* @param channels
* 開始されたChannel情報.複数指定可能
*/
protected void disconnect(final Session session, final Channel... channels) {
if (channels != null) {
for (Channel c: channels ) {
if (c != null) {
c.disconnect();
}
}
}
if (session != null) {
session.disconnect();
}
}
/**
* SFTPに接続するユーザ情報を保持するクラス
*/
private static class SftpUserInfo implements UserInfo {
@Override
public String getPassword() {
return null;
}
@Override
public boolean promptPassword(String arg0) {
return true;
}
@Override
public boolean promptPassphrase(String arg0) {
return true;
}
@Override
public boolean promptYesNo(String arg0) {
return true;
}
@Override
public void showMessage(String arg0) {
}
@Override
public String getPassphrase() {
return null;
}
}
/**
* ファイルアップロード
*
* @throws JSchException
* Session・Channelの設定/接続エラー時に発生
*/
public void putFile(ChannelSftp channel, InputStream inStream, String destPath)
throws SftpException {
/*
* sftp通信を実行
*/
String absoluteDestPath = channel.getHome() + "/" + destPath;
String destFile = new File(absoluteDestPath).getName();
int numDestPath = absoluteDestPath.length();
int numDestFile = destFile.length();
String destParentPath = absoluteDestPath.substring( 0, numDestPath - numDestFile );
channel.cd(destParentPath);
channel.put( inStream, destFile);
// confirm existance of destFile
channel.lstat(destFile);
}
/*
* サーバー上のファイルの削除
* destFileNameFront文字列から始まるファイルを全て削除する
*/
public void deleteFiles(ChannelSftp channel, String destFileNameFront) throws SftpException {
channel.rm(destFileNameFront + "*");
}
}
SdCardDirPaths.java
package your.package;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Environment;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class SdCardDirPaths {
/**
* SDカードのfilesディレクトリパスのリストを取得する。
* Android5.0以上対応。
*
* @param context
* @return SDカードのfilesディレクトリパスのリスト
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static List getSdCardFilesDirPathListForLollipop(Context context) {
List sdCardFilesDirPathList = new ArrayList<>();
// getExternalFilesDirsはAndroid4.4から利用できるAPI。
// filesディレクトリのリストを取得できる。
File[] dirArr = context.getExternalFilesDirs(null);
for (File dir : dirArr) {
if (dir != null) {
String path = dir.getAbsolutePath();
// isExternalStorageRemovableはAndroid5.0から利用できるAPI。
// 取り外し可能かどうか(SDカードかどうか)を判定している。
if (Environment.isExternalStorageRemovable(dir)) {
// 取り外し可能であればSDカード。
// このパスをパスリストに加える
if (!sdCardFilesDirPathList.contains(path)) {
sdCardFilesDirPathList.add(path);
}
}
}
}
return sdCardFilesDirPathList;
}
}
(利用例)
Send2ServerTask.java
package your.package; import android.app.Activity; import android.content.Context; import android.os.AsyncTask; import android.widget.Toast; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import com.jcraft.jsch.SftpException; import java.io.InputStream; import java.lang.ref.WeakReference; import java.util.HashMap; import java.util.Map; // 複数のファイルをSSH送信する public class Send2ServerTask extends AsyncTask{ final String ServerIp = "SSH.SERVER.IP.ADDRESS"; final int Port = 22; final String User = "SshLogInUser"; final String IdentityKeyPath = "PRIVATE/KEY/FILE/PATH/IN/CLIENT/DEVICE"; // if IdentityKeyPath is illegal, password authentication is used. final String DestParentPath = "SERVER/DIR/TO/BE/STORED"; private WeakReference weakRef; private HashMap inStreamMap; final private String passPhrase; final private String fileNameFront; // SSH失敗時のファイル削除のためにファイル名共通文字列を保持 // 複数の送信ファイルはいずれもfileNameFront文字列で始まるファイル名とすること private Listener listener; /* * constructor * inStreamMap 送信する複数ファイルのファイル名とインプットストリームをHashMapで渡す */ Send2ServerTask(Activity parentActivity, HashMap inStreamMap, String passPhrase, String fileNameFront) { weakRef = new WeakReference<>(parentActivity); this.inStreamMap = new HashMap<>(inStreamMap); this.passPhrase = passPhrase; this.fileNameFront = fileNameFront; } @Override protected String doInBackground(Void... params) { MyJsch mJsch; Session sftpSession = null; ChannelSftp sftpChannel = null; Activity refActivity = weakRef.get(); if (refActivity == null || refActivity.isFinishing()) { return null; } Context appContext = weakRef.get().getApplicationContext(); // initialise Jsch mJsch = new MyJsch(ServerIp, Port, User, passPhrase, IdentityKeyPath, appContext); // connect session, channel try { sftpSession = mJsch.connectSession(); sftpChannel = mJsch.connectChannelSftp( sftpSession ); // upload int count = 0; for ( Map.Entry entry : inStreamMap.entrySet()) { // entry.getKey() entry.getValue() String destPath = DestParentPath + "/" + entry.getKey(); try { mJsch.putFile(sftpChannel, entry.getValue(), destPath); } catch (SftpException e) { try { // このセッションでアップロードされたファイルをすべて削除する mJsch.deleteFiles(sftpChannel, fileNameFront); mJsch.disconnect( sftpSession, sftpChannel); return "Failed to upload files. count: " + count + ". " + destPath + " " + e.toString(); } catch (SftpException e1) { mJsch.disconnect( sftpSession, sftpChannel); return "Failed to delete remote files. " + e1.toString(); } } try { // take sleep between SFTP#puts Thread.sleep(500); } catch (InterruptedException e) { // このセッションでアップロードされたファイルをすべて削除する mJsch.deleteFiles(sftpChannel, fileNameFront); mJsch.disconnect( sftpSession, sftpChannel); return "Failed! sleep" + e.toString(); } count++; } if ( count != inStreamMap.size()) { // このセッションでアップロードされたファイルをすべて削除する mJsch.deleteFiles(sftpChannel, fileNameFront); mJsch.disconnect( sftpSession, sftpChannel); return "Could not upload " + inStreamMap.size() + " files"; } } catch (JSchException | SftpException e) { mJsch.disconnect( sftpSession, sftpChannel); return "connection failed. " + e.toString(); } finally { // disconnect channel, session mJsch.disconnect( sftpSession, sftpChannel); } return "Succeeded. " + inStreamMap.size() + " files upload"; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); Activity refActivity = weakRef.get(); if (refActivity == null || listener == null) { Toast.makeText(refActivity, "failed sending to server.", Toast.LENGTH_LONG).show(); } else { if ( result.contains("Succeeded") ) { Toast.makeText(refActivity, result, Toast.LENGTH_SHORT).show(); } else { Toast.makeText(refActivity, result, Toast.LENGTH_LONG).show(); } listener.onSuccess(result); } return; } void setListener(Listener listener) { this.listener = listener; } interface Listener { void onSuccess(String str); } }
MyActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_confirm_before_send);
buttonOK = findViewById(R.id.buttonOK);
setListeners();
}
/*
* Send2ServerTaskへのリスナ
* サーバーへのアップロード終了後に行う処理を記述
*/
private Send2ServerTask.Listener createListener() {
return new Send2ServerTask.Listener() {
@Override
public void onSuccess(String result) {
deleteFiles();
}
};
}
protected void setListeners(){
buttonOK.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/*
* HashMap SSHサーバーに送るデータ
* String 送信先ファイルパス
* InputStream 送信ファイルのインプットストリーム
*/
HashMap dataMap = new HashMap<>();
setData2dataMap(); // dataMapにSSH通信データをセットする
setPassPhraseWord();
setFileNameFront();
/*
* dataMapを保管サーバーに送る
*/
send2serverTask = new Send2ServerTask(thisActivity, dataMap, passPhraseWord, fileNameFront);
// Listenerを設定し、send2serverTaskを実行してdataMapを保管サーバーに送る
send2serverTask.setListener(createListener());
send2serverTask.execute();
}
});
}
0 件のコメント:
コメントを投稿