2019 Nov. 02.
android端末でブラウザを起動する。https://www.icloud.com/ にアクセスしiPhoneのApple IDでログインする。
目的のファイルをダウンロードする。ダウンロード時に指定するアプリはブラウザにする。
android端末内部共有ストレージ/Download ディレクトリ内にファイルが保管される。
4567番ポートを使っているプロセスを調べる $ lsof -i :4567COMMAND PID USER    FD  TYPE  DEVICE SIZE/OFF NODE NAME
ruby    818 ryuichi 5u  IPv4  21246  0t0      TCP *:4567 (LISTEN)
4567番ポートを使っているプロセス(818)を終了させる$ kill -9 818
/etc/profile あるいは /etc/profile.d/FILE に export文を記述する。  export PATH=$PATH:/SYSTEM/WIDE/PATH/DIR
public class MyActivity extends AppCompatActivity {
    Button buttonOK;
    /*
     * MyAsyncTask内のListenerインターフェースを呼び出す
     */
    private MyAsyncTask.Listener createListener() {
        return new MyAsyncTask.Listener() {
            /*
             * Listenerインターフェースの抽象メソッドonSuccessにコードを実装
             */
            @Override
            public void onSuccess(String result) {
                CODES_TO_RUN_AFTER_MyAsyncTask;
            }
        };
    }
    /*
     * buttonOKがタップされたらMyAsyncTaskが呼び出される
     */
    buttonOK.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            myAsyncTask = new MyAsyncTask();
            /*
             * MyAsyncTask内のListenerインターフェース型変数listenerに
             * createListener()をセットする
             *     createListener()ではListenerインターフェースの
             *     抽象メソッドonSuccessの実装コードが記述されている。
             *     MyAsyncTask内で"listener.onSuccess()"によって実装コードを実行できる。
             */
            myAsyncTask.setListener(createListener());
            myAsyncTask.execute();
        }
    });
}
(MyAsyncTask.java)public class MyAsyncTask extends AsyncTask{ private Listener listener; /* * 抽象メソッドonSuccess()は、MyAsyncTask内で実行させたい処理。 * 抽象メソッドonSuccess()は、MyAsyncTaskを呼び出すMyActivity内の * createListener()内で実装されている。 */ interface Listener { void onSuccess(String str); } void setListener(Listener listener) { this.listener = listener; } @Override protected String doInBackground(Void... params) { } @Override protected void onPostExecute(String result) { super.onPostExecute(result); CODES_TO_EXECUTE_onPostExecute; /* * onSuccess()メソッド実行 */ listener.onSuccess(result); return; } } 
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 + "*");
    }
}
 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;
    }
}
  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); } } 
@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();
            }
        });
    }
  2019 Jun. 26.
$ cd AndroidStudio/PROJECT
$ ./gradlew assembleDebug
// BitmapクラスbitmapInstanceをバイト配列byteArrayImageに変換する
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
bitmapInstance.compress(Bitmap.CompressFormat.JPEG, 80, outStream);
byte[] byteArrayImage = outStream.toByteArray();
// byteArrayImageをメールに添付にする
final MimeBodyPart filePart = new MimeBodyPart();
filePart.setDataHandler(new DataHandler( new ByteArrayDataSource(byteArrayImage, "image/jpeg")));
String fileName = "FILE_NAME";
try {
    filePart.setFileName(MimeUtility.encodeWord(fileName));
} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
}
package YOUR.PACKAGE.alertdialogsample;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
    Button button_dialog1, button_dialog2, button_dialog3;
    private TextView text_view;
    private FragmentManager flagmentManager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text_view = findViewById(R.id.text_view);
        button_dialog1 = findViewById(R.id.button_dialog1);
        button_dialog2 = findViewById(R.id.button_dialog2);
        button_dialog3 = findViewById(R.id.button_dialog3);
        // button_dialog1ボタンタップでAlertを表示させる
        button_dialog1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                flagmentManager = getSupportFragmentManager();
                // DialogFragment を継承したAlertDialogFragment1のインスタンス
                AlertDialogFragment1 dialogFragment = AlertDialogFragment1.newInstance(100);
                // DialogFragmentの表示
                dialogFragment.show(flagmentManager, "test alert dialog1");
            }
        });
        // button_dialog2ボタンタップでダイアログのメッセージを変えたAlertを表示させる
        //   newInstance()への引数を変更してメッセージを変える
        button_dialog2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                flagmentManager = getSupportFragmentManager();
                // DialogFragmentを継承したAlertDialogFragment2のインスタンス
                AlertDialogFragment1 dialogFragment = AlertDialogFragment1.newInstance(200);
                // DialogFragmentの表示
                dialogFragment.show(flagmentManager, "test alert dialog2");
            }
        });
        // button_dialog3ボタンタップでItemを選択するAlertを表示させる
        button_dialog3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                flagmentManager = getSupportFragmentManager();
                // DialogFragment を継承したAlertDialogFragmentのインスタンス
                AlertDialogFragment2 dialogFragment = new AlertDialogFragment2();
                // DialogFragmentの表示
                dialogFragment.show(flagmentManager, "test alert dialog");
            }
        });
    }
    public void setTextView(String message){
        text_view.setText(message);
    }
    /*
     * DialogFragmentを継承したクラスAlertDialogFragment1
     */
    public static class AlertDialogFragment1 extends DialogFragment {
        /*
         * コンストラクタを記述してはならない。
         * newInstance()でのsetArguments、onCreateDialog()でのgetArgumentsを利用する。
         */
        public static AlertDialogFragment1 newInstance( int requestCode) {
            AlertDialogFragment1 fragment = new AlertDialogFragment1();
            Bundle arguments = new Bundle();
            arguments.putInt("reqCode", requestCode);
            fragment.setArguments(arguments);
            return fragment;
        }
        @Override
        @NonNull
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            int requestCode = getArguments().getInt("reqCode");
            AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
            switch (requestCode) {
                case 100:
                    alert.setTitle("Test AlertDialog1");
                    alert.setMessage("Message is 100");
                    break;
                case 200:
                    alert.setTitle("Test AlertDialog2");
                    alert.setMessage("Message is 200");
                    break;
            }
            alert.setPositiveButton(R.string.dialog_ok, null);
            return alert.create();
        }
    }
    /*
     * DialogFragmentを継承したクラスAlertDialogFragment2
     */
    public static class AlertDialogFragment2 extends DialogFragment {
        // 選択肢のリスト
        private String[] menulist = {"選択(1)","選択(2)","選択(3)"};
        @Override
        @NonNull
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
            alert.setTitle("Test AlertDialog3");
            alert.setItems(menulist, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int idx) {
                    // 選択1
                    if (idx == 0) {
                        setMassage(menulist[0]);
                    }
                    // 選択2
                    else if (idx == 1) {
                        setMassage(menulist[1]);
                    }
                    // 選択3, idx == 2
                    else{
                        setMassage(menulist[2]);
                    }
                }
            });
            return alert.create();
        }
        private void setMassage(String message) {
            MainActivity mainActivity = (MainActivity) getActivity();
            if (mainActivity != null) {
                mainActivity.setTextView(message);
            }
        }
    }
}
package YOUR.PACKAGE.APPLICATION;
/*
 * Re-use of https://akira-watson.com/android/file_search.html
 */
import android.os.Environment;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class SearchExternalStorageFile {
    // 外部ストレージ内のfileStrにマッチするファイルを検索
    public String[] searchFiles( String fileStr ){
        // マッチしたファイルの絶対パスを格納する
        List listMatchedFiles = new ArrayList<>();
        // String 型の ArrayList を生成
        List listDirectory = new ArrayList<>();
        // 外部ストレージのパスを取得する、パスは機種によって異なる
        File file = Environment.getExternalStorageDirectory();
        String storagePath = file.getPath();
        listDirectory.add(storagePath);
        int m = 0;
        int n = 0;
        String[] fileNames;
        String imgPath = null, fName;
        while(listDirectory.size() > m){
            File directory = new File(listDirectory.get(m));
            fileNames = directory.list();
            n = 0;
            while(fileNames.length > n){
                File subFile;
                subFile = new File(directory.getPath() + "/" + fileNames[n]);
                if (subFile.isDirectory()) {
                    listDirectory.add(directory.getPath() + "/" + fileNames[n]);
                } else {
                    if (fileNames[n].contains(fileStr)) {
                        listMatchedFiles.add(directory.getPath() + "/" + fileNames[n]);
                    }
                }
                n++;
            }
            m++;
        }
        int listSize = listMatchedFiles.size();
        return listMatchedFiles.toArray(new String[listSize]);
    }
}
  
例 DateFormat.format("yyyy-MM-dd_kk:mm:ss", dateTaken).toString()
package YOUR.PACKAGE.sampletakephotogetimagefile;
import android.Manifest;
import android.annotation.TargetApi;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
    Button button_take_photo;
    ImageView image_view;
    TextView text_view_uri_path, text_view_file_path, text_view_image_title;
    static final int REQUEST_CAPTURE_IMAGE = 100;
    private final int REQUEST_PERMISSION__EX_STORAGE = 1000;
    private final int REQUEST_PERMISSION_CAMERA = 1010;
    Uri pictureUri;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViews();
        // check & get permissions
        if(Build.VERSION.SDK_INT >= 23){
            checkPermission();
        }
        if (checkSelfPermission(Manifest.permission.CAMERA) !=
                PackageManager.PERMISSION_GRANTED){
            button_take_photo.setText(R.string.button_unable_phote );
            button_take_photo.setEnabled(false);
        }
        setListeners();
    }
    protected void findViews(){
        button_take_photo = findViewById(R.id.button_take_photo);
        image_view = findViewById(R.id.imageView);
        text_view_uri_path = findViewById(R.id.textViewUriPath);
        text_view_file_path = findViewById(R.id.textViewFilePath);
        text_view_image_title = findViewById(R.id.textViewImageTitle);
    }
    // Permissionの確認
    //   from https://akira-watson.com/android/mediastore.html
    @TargetApi(Build.VERSION_CODES.M)
    public void checkPermission() {
        if (checkSelfPermission(Manifest.permission.CAMERA) !=
                PackageManager.PERMISSION_GRANTED){
            requestCameraPermission();
        }
        if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
                PackageManager.PERMISSION_GRANTED){
            requestExStoragePermission();
        }
    }
    // CameraPermission許可を求める
    @TargetApi(Build.VERSION_CODES.M)
    private void requestCameraPermission() {
        if (shouldShowRequestPermissionRationale( Manifest.permission.CAMERA)) {
            requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_PERMISSION_CAMERA);
        } else {
            Toast toast = Toast.makeText(this, "許可されないとアプリが実行できません",
                    Toast.LENGTH_SHORT);
            toast.show();
            requestPermissions(new String[]{Manifest.permission.CAMERA }, REQUEST_PERMISSION_CAMERA);
        }
    }
    // ExternalStoragePermission許可を求める
    @TargetApi(Build.VERSION_CODES.M)
    private void requestExStoragePermission() {
        if (shouldShowRequestPermissionRationale( Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    REQUEST_PERMISSION__EX_STORAGE);
        } else {
            Toast toast = Toast.makeText(this, "許可されないとアプリが実行できません",
                    Toast.LENGTH_SHORT);
            toast.show();
            requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE },
                    REQUEST_PERMISSION__EX_STORAGE);
        }
    }
    // requestPermission結果に対する処理
    @Override
    public void onRequestPermissionsResult( int requestCode, @NonNull String[] permissions,
                                            @NonNull int[] grantResults) {
        if (requestCode == REQUEST_PERMISSION_CAMERA) {
            if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
                // 拒否された時の対応
                Toast toast = Toast.makeText(this, "これ以上なにもできません",
                        Toast.LENGTH_SHORT);
                toast.show();
            }
        } else if (requestCode == REQUEST_PERMISSION__EX_STORAGE) {
            if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
                // 拒否された時の対応
                Toast toast = Toast.makeText(this, "これ以上なにもできません",
                        Toast.LENGTH_SHORT);
                toast.show();
            }
        } else {
            Toast toast = Toast.makeText(this,
                    "Bad requestCode", Toast.LENGTH_SHORT);
            toast.show();
        }
    }
    protected void setListeners(){
        // カメラ起動ボタンが押された時
         button_take_photo.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                /*
                写真用情報を収集し、ContentResolverを使ってandroidに備わっている
                MediaStore.Images.Mediaデータベースに写真用情報を追加し、そのURI
                を取得する
                */
                long dateTaken = System.currentTimeMillis();
                String filename = DateFormat.format("yyyy-MM-dd_kk:mm:ss", dateTaken).toString() + ".jpg";
                ContentResolver contentResolver = getContentResolver();
                ContentValues values = new ContentValues(5);
                values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
                values.put(MediaStore.Images.Media.DATE_MODIFIED, System.currentTimeMillis()/1000);
                values.put(MediaStore.Images.Media.TITLE, filename);
                values.put(MediaStore.Images.Media.DISPLAY_NAME, filename);
                values.put(MediaStore.Images.Media.DATE_TAKEN,System.currentTimeMillis());
                pictureUri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
                // カメラを起動する
                Intent intent = new Intent();
                intent.setAction("android.media.action.IMAGE_CAPTURE");
                intent.putExtra(MediaStore.EXTRA_OUTPUT, pictureUri);
                  // MediaStore.EXTRA_OUTPUTで指定したpictureUriに、撮影後に画像データが書き込まれる
                startActivityForResult(intent, REQUEST_CAPTURE_IMAGE);
             }
         });
    }
    // このアクティビティから起動された他の機能から戻ってきた時の処理
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data ) {
        /*
          正しい結果が得られなかった場合の処理
          撮影キャンセルなどするとこっちに来る
        */
        if (resultCode != RESULT_OK) {
            // カメラ撮影からの復帰の時
            if (requestCode == REQUEST_CAPTURE_IMAGE) {
                Toast toast = Toast.makeText(this,"resultCode != RESULT_OK",
                        Toast.LENGTH_LONG);
                toast.show();
                return;
            }
        }
        /*
         * 写真撮影できた場合
         */
        if (requestCode == REQUEST_CAPTURE_IMAGE) {
            if (data == null ) {
                Toast.makeText(this, "data == null ",
                        Toast.LENGTH_SHORT).show();
            } else if ( data.getData() == null) {
                Toast.makeText(this, "data.getData() == null",Toast.LENGTH_SHORT).show();
            }
            // 撮影した写真を取り出す
            image_view.setImageURI(pictureUri);
            text_view_uri_path.setText("Uri path: " + pictureUri.getPath());
            // get filepath & title from uri
            ContentResolver contentResolver = this.getContentResolver();
            String[] columns =
                {
                    MediaStore.Images.Media.DATA,
                    MediaStore.Images.Media.TITLE
                };
            Cursor cursor = contentResolver.query(pictureUri, columns, null,
                    null, null);
            if(cursor == null) return;
            int pathIndex = cursor.getColumnIndex( MediaStore.Images.Media.DATA);
            int titleIndex = cursor.getColumnIndex( MediaStore.Images.Media.TITLE);
            cursor.moveToFirst();
            String filePath  = cursor.getString(pathIndex);
            String imageTitle = cursor.getString(titleIndex);
            text_view_file_path.setText(filePath);
            text_view_image_title.setText(imageTitle);
            return;
        }
    }
}
if(Build.VERSION.SDK_INT >= 23){
            checkPermission();
}
PROCESS_AFTER_GETTING_PERMISSIONS
// Permissionの確認
//   reuse of https://akira-watson.com/android/mediastore.html
@TargetApi(Build.VERSION_CODES.M)
public void checkPermission() {
    if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
        requestCameraPermission();
    }
    if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
        requestExStoragePermission();
    }
}
// CameraPermission許可を求める
@TargetApi(Build.VERSION_CODES.M)
private void requestCameraPermission() {
    if (shouldShowRequestPermissionRationale( Manifest.permission.CAMERA)) {
        requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_PERMISSION_CAMERA);
    } else {
        Toast toast = Toast.makeText(this, "許可されないとアプリが実行できません", Toast.LENGTH_SHORT);
        toast.show();
        requestPermissions(new String[]{Manifest.permission.CAMERA }, REQUEST_PERMISSION_CAMERA);
    }
}
// ExternalStoragePermission許可を求める
@TargetApi(Build.VERSION_CODES.M)
private void requestExStoragePermission() {
    if (shouldShowRequestPermissionRationale( Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
        requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_PERMISSION__EX_STORAGE);
    } else {
        Toast toast = Toast.makeText(this, "許可されないとアプリが実行できません", Toast.LENGTH_SHORT);
        toast.show();
        requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE }, REQUEST_PERMISSION__EX_STORAGE);
    }
}
// requestPermission結果に対する処理
@Override
public void onRequestPermissionsResult( int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (requestCode == REQUEST_PERMISSION_CAMERA) {
        if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
            // 拒否された時の対応
            Toast toast = Toast.makeText(this, "これ以上なにもできません", Toast.LENGTH_SHORT);
            toast.show();
        }
    } else if (requestCode == REQUEST_PERMISSION__EX_STORAGE) {
        if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
            // 拒否された時の対応
            Toast toast = Toast.makeText(this, "これ以上なにもできません", Toast.LENGTH_SHORT);
            toast.show();
        }
    } else {
        Toast toast = Toast.makeText(this, "Bad requestCode", Toast.LENGTH_SHORT);
        toast.show();
    }
}
package YOUR.PACKAGE;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
    boolean is1stRun = true;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if ( is1stRun ) {
            // get text by dialog
            InputTextDialogFragment cdf = new InputTextDialogFragment();
            cdf.show(getSupportFragmentManager(),"dialog");
            is1stRun = false;
        }
    }
    public void onReturnValue(String value) {
        TextView textViewPhrase = (TextView)findViewById(R.id.textViewPhrase);
        textViewPhrase.setText(value);
    }
}
package YOUR.PACKAGE;
import android.app.Dialog;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.EditText;
public class InputTextDialogFragment extends DialogFragment {
    EditText editTextPhrase;
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Dialog dialog = new Dialog(getActivity());
        dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
        dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
        dialog.setContentView(R.layout.input_text_dialog);
        editTextPhrase = (dialog.findViewById(R.id.editTextPhrase));
        dialog.findViewById(R.id.buttonOK).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String textPhrase = editTextPhrase.getText().toString();
                MainActivity callingActivity = (MainActivity) getActivity();
                callingActivity.onReturnValue(textPhrase);
                dismiss();
            }
        });
        return dialog;
    }
}
private final Context AppContext; private final String file; // android端末内の外部ストーリッジ確認 ListsdCardFilesDirPaths = SdCardDirPaths.getSdCardFilesDirPathListForLollipop( AppContext ); Collections.sort(sdCardFilesDirPaths, new CompStringLength()); for (String p : sdCardFilesDirPaths) { Log.d("My", "SDパスの1つ: " + p); } externalPath = sdCardFilesDirPaths.get(0); externalPath = externalPath.replaceAll("/Android.*$", ""); Log.d("My", "SDパス: " + externalPath); // get filePath final String sourcePath = externalPath + "/" + file; Log.d("My", "sourcePath " + sourcePath ); if ( new File(sourcePath).exists()) { Log.d("My", sourcePath + " exists."); } else { Log.d("My", sourcePath + " not exist."); } 
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
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();
                Log.d("My", "Externalパスの1つ: " + path);
                // isExternalStorageRemovableはAndroid5.0から利用できるAPI。
                // 取り外し可能かどうか(SDカードかどうか)を判定している。
                if (Environment.isExternalStorageRemovable(dir)) {
                    // 取り外し可能であればSDカード。
                    if (!sdCardFilesDirPathList.contains(path)) {
                        sdCardFilesDirPathList.add(path);
                    }
                } else {
                    // 取り外し不可能であれば内部ストレージ。
                }
            }
        }
        return sdCardFilesDirPathList;
    }
}
  import java.util.Comparator; public class CompStringLength implements Comparator{ @Override public int compare(String first, String second){ //null評価 //両方nullなら等価とする if(first == null && second == null){ return 0; } //片方nullなら、nullを小さいとする。 if(first == null){ return -1; }else if(second == null){ return 1; } //idの文字列長でソート。文字列数がが小さい順に並べる。 if(first.length() > second.length()){ return 1; }else if(first.length() < second.length()){ return -1; }else if(first.length() == second.length()){ return 0; } return 0; } } 
public class FirstActivity extends AppCompatActivity {
  Button button1 = (Button) findViewById(R.id.button1);
  button1.setEnabled(true);
  TextView textView1 = (TextView) findViewById(R.id.textView1);
  textView1.setText("start")
  new SecondTask(this).execute();
}
public class SecondTask extends AsyncTask {
  private WeakReference weakReference;
  /**
   * make WeakReference in constructor
   *   参照しているActivityを引数にしてWeakReferenceのインスタンスを生成する
  **/
  SecondTask(Context referenceContext) {
    private WeakReference weakReference;
    weakReference = new WeakReference<>(referenceContext);
  }
  /**
   * use of WeakReference in onPostExecute
   *   weakReference.get()で参照しているActivityのContextを取得し、それを通じてView を設定したりする
  **/
  @Override
  protected void onPostExecute(String result) {
    Activity activity = (Activity) weakReference.get();
    if (activity == null || activity.isFinishing()) return;
    activity.findViewById(R.id.button1).setEnabled(false);
    TextView tv = activity.findViewById(R.id.textView1);
    tv.setText("end");
  }
}
package YOUR.PACKAGE.NAME;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
    /** Channel接続タイプ */
    private static final String CHANNEL_TYPE = "sftp";
    private MyTask task;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /*
        final String ServerIP = "ServerIP";
        final int Port = PortNum;
        final String UserId = "USER";
        final String PassPhrase = "YOURPASSPHRASE";
        final String IdentityKeyPath = "YOUR/SECRET/FILE/PATH"; // Do not attach '/' at head of path
        final String SourcePath = "PATH/TO/SOURCE/FILE"; // Do not attach '/' at head of path
        final String DestPath = "PATH/TO/DEST/FILE";
        */
        final String ServerIP="";
        final int Port = ;
        final String UserId = "";
        final String PassPhrase = "";
        final String IdentityKeyPath = "";
        final String SourcePath = "";
        final String DestPath = "";
        Button button1= (Button) findViewById(R.id.button1);
        TextView textView1 = (TextView) findViewById(R.id.textView1);
        // タスクの生成
        task = new MyTask(ServerIP, Port, UserId, PassPhrase, IdentityKeyPath, SourcePath, DestPath,this);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                v.setEnabled(false);
                // 非同期処理を開始する
                task.execute();
            }
        });
    }
}
package YOUR.PACKAGE.NAME; import android.app.Activity; import android.content.Context; import android.os.AsyncTask; import android.widget.TextView; import com.jcraft.jsch.JSchException; import java.lang.ref.WeakReference; public class MyTask extends AsyncTask{ private final String ServerIp; private final int Port; private final String User; private final String IdentityKeyPath; private final String PassPhrase; private final String SrcPath; private final String DestPath; private WeakReference weakReference; // constructor MyTask(final String ServerIp, final int Port, final String User, final String PassPhrase, final String IdentityKeyPath, final String SrcPath, final String DestPath, Context referenceContext) { super(); // 呼び出し元へのweakReference weakReference = new WeakReference<>(referenceContext); this.ServerIp = ServerIp; this.Port = Port; this.User = User; this.PassPhrase = PassPhrase; this.IdentityKeyPath = IdentityKeyPath; this.SrcPath = SrcPath; this.DestPath = DestPath; } /** * バックグランドで行う処理 */ @Override protected String doInBackground(Void... value) { // startJsch MyJsch mJsch = new MyJsch( ServerIp, Port, User, PassPhrase, IdentityKeyPath, SrcPath, DestPath, weakReference.get()); try { mJsch.putFile(); } catch (JSchException e) { e.printStackTrace(); return e.toString(); } return "Success"; } /** * バックグランド処理が完了し、UIスレッドに反映する */ @Override protected void onPostExecute(String result) { // get a reference to the activity if it is still there Activity activity = (Activity) weakReference.get(); if (activity == null || activity.isFinishing()) return; activity.findViewById(R.id.button1).setEnabled(true); TextView tv = activity.findViewById(R.id.textView1); tv.setText(result); } } 
package YOUR.PACKAGE.NAME;
import android.content.Context;
import android.util.Log;
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.util.Collections;
import java.util.List;
public class MyJsch {
    private final String ServerIp;
    private final int Port;
    private final String User;
    private final String PassPhrase;
    private final String IdentityKeyPath;
    private final String SrcPath;
    private final String DestPath;
    private Context activityContext;
    private String externalPath;
    /** Channel接続タイプ */
    private static final String CHANNEL_TYPE = "sftp";
    /**
     * コンストラクタ
     */
    MyJsch(final String ServerIp, final int Port, final String User, final String PassPhrase,
           final String IdentityKeyPath, final String SrcPath, final String DestPath,
           Context activityContext) {
        this.ServerIp = ServerIp;
        this.Port = Port;
        this.User = User;
        this.IdentityKeyPath = IdentityKeyPath;
        this.PassPhrase = PassPhrase;
        this.SrcPath = SrcPath;
        this.DestPath = DestPath;
        this.activityContext = activityContext;
    }
    /**
     * ファイルアップロード
     *
     * @throws JSchException
     *             Session・Channelの設定/接続エラー時に発生
     */
    public void putFile()
            throws JSchException {
        Session session = null;
        ChannelSftp channel = null;
        // 外部ストーリッジ確認
        List sdCardFilesDirPaths =
                SdCardDirPaths.getSdCardFilesDirPathListForLollipop( activityContext );
        Collections.sort(sdCardFilesDirPaths, new CompStringLength());
        for (String p : sdCardFilesDirPaths) {
            Log.d("My", "SDパスの1つ: " + p);
        }
        externalPath = sdCardFilesDirPaths.get(0);
        externalPath = externalPath.replaceAll("/Android.*$", "");
        Log.d("My", "SDパス: " + externalPath);
        // get sourcePath
        final String sourcePath = externalPath + "/" + SrcPath;
        Log.d("My", "sourcePath " + sourcePath );
        if ( new File(sourcePath).exists()) {
            Log.d("My", sourcePath + " exists.");
        } else {
            Log.d("My", sourcePath + " not exist.");
        }
        /*
         * sftp通信を実行
        */
        try {
            session = connectSession();
            channel = connectChannelSftp(session);
            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 );
            Log.d("My", "absoluteDestPath is " + absoluteDestPath);
            Log.d("My", "destFile is " + destFile);
            Log.d("My", "destParentPath is " + destParentPath);
            Log.d("My", "current local directory is " + channel.lpwd());
            Log.d("My", "remote home directory is " + channel.getHome());
            channel.cd(destParentPath);
            channel.put(sourcePath, destFile);
            try {
                channel.lstat(destFile);
            } catch (SftpException e) {
                Log.d("My", DestPath + " does not exist.");
                Log.d("My", e.toString());
            }
        } catch (SftpException e) {
            Log.d("My",e.toString());
        } finally {
            disconnect(session, channel);
        }
    }
    /**
     * Sessionを開始
     */
    private Session connectSession()
            throws JSchException {
        final JSch jsch = new JSch();
        // 鍵追加
        String keyFilePath = externalPath + "/" + IdentityKeyPath;
        if ( new File(keyFilePath).exists()) {
            Log.d("My",  keyFilePath + " exists.");
        } else {
            Log.d("My",  keyFilePath + " not exist.");
        }
        jsch.addIdentity(keyFilePath, PassPhrase);
        // Session設定
        final Session session = jsch.getSession(User, ServerIp, Port);
        final UserInfo userInfo = new SftpUserInfo();
        // TODO 今回は使用しないがパスフレーズ等が必要な場合はUserInfoインスタンス経由で設定する
        session.setUserInfo(userInfo);
        session.connect();
        return session;
    }
    /**
     * SFTPのChannelを開始
     *
     * @param session
     *            開始されたSession情報
     */
    private ChannelSftp connectChannelSftp(final Session session)
            throws JSchException {
        final ChannelSftp channel = (ChannelSftp) session.openChannel(CHANNEL_TYPE);
        try {
            channel.connect();
        } catch (JSchException e) {
            Log.d("My",   e.toString());
        }
        return channel;
    }
    /**
     * Session・Channelの終了
     *
     * @param session
     *            開始されたSession情報
     * @param channels
     *            開始されたChannel情報.複数指定可能
     */
    private 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;
        }
    }
}
 # 第1月曜の深夜3時にコマンド実行0 3 1-7 * * root [ $(date "+\%w") -eq 1 ] && コマンド# 第2水曜の深夜3時に以下略0 3 8-14 * * root [ $(date "+\%w") -eq 3 ] && コマンド# 第3木曜の以下略0 3 15-21 * * root [ $(date "+\%w") -eq 4 ] && コマンド# 第4日曜の以下略0 3 22-28 * * root [ $(date "+\%w") -eq 0 ] && コマンド
| ChannelId | 30044 | 
| ChannelName | "radio TXT FM dramacity" | 
| ChannelDetail | "北海道札幌市厚別区にあるコミュニティFMラジオ局です。" | 
| ChannelImage | "http://listenradio.jp/img/rslogo/30044s.png" | 
| ChannelType | 2 | 
| ChannelRtmp | "rtmp://mtist.as.smartstream.ne.jp/30044/livestream" | 
| ChannelHls | "http://mtist.as.smartstream.ne.jp/30044/livestream/playlist.m3u8" | 
| ChannelHds | "http://mtist.as.smartstream.ne.jp/30044/livestream/manifest.f4m" | 
| AdFlg | true | 
| PublisherId | "a1502e22bc156c6" | 
| ChannelLogo | "http://listenradio.jp/img/rslogo/30044r.png" | 
2019 Apr. 13.
# テキストFILE内で hoge を含む行数を取得する
WORD = "hoge"
all_text = File.read(FILE)
count_match=all_text.scan(/^.*#{WORD}/).size