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端末内の外部ストーリッジ確認 ListsdCardFilesDirPaths = 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 ListgetSdCardFilesDirPathListForLollipop(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) { /* * HashMapSSHサーバーに送るデータ * 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 件のコメント:
コメントを投稿