僕、国際ロボット展に出展します。12 月 18日(水)~21日(土)
サービスロボットゾーンです。
僕でなくて、フューチャアグリ株式会社です。(笑)
内容は、
低速度自律走行UNIT
低コスト自律走行AGV
不整地自律走行ロボット
その他、いろいろ
是非、お越しください。
Peace!!
ロボット使ってトマト作れば楽だなぁ...やってみっか!
農業ロボット開発記録
日本中で100台以上動かしちゃった(^^)/
I'm developing robots that do tomato harvesting, settled planting ,,,,and many tasks.
The goal of production cost of robot is $2,000 per unit.
Because it is necessary a lot of robots, in order to innovate the farming.
I use Raspberry Pi as robot controller to develop low cost robots.
TOMATO FARM website -> CLICK!
2019年10月5日土曜日
2019年9月9日月曜日
Build TensorFlow Lite on Raspberry Pi 4
TesorFlow Lite Raspberry Pi 用の libtensorflow-lite.a を作る
TensorFlowの当該のページ通りにすればよい。
他のページは見ない方が良い
About 40 minutes.
Build TensorFlow Lite for Raspberry Pi
cd ~/prj
git clone https://github.com/tensorflow/tensorflow.git
cd tensorflow
./tensorflow/lite/tools/make/download_dependencies.sh
./tensorflow/lite/tools/make/build_rpi_lib.sh
ls -al tensorflow/lite/tools/make/gen/rpi_armv7l/lib
drwxr-xr-x 2 root root 4096 Sep 9 02:32 .
drwxr-xr-x 5 root root 4096 Sep 9 02:32 ..
-rw-r--r-- 1 root root 12164884 Sep 9 02:32 benchmark-lib.a
-rw-r--r-- 1 root root 5796642 Sep 9 02:32 libtensorflow-lite.a
TensorFlowの当該のページ通りにすればよい。
他のページは見ない方が良い
About 40 minutes.
Build TensorFlow Lite for Raspberry Pi
cd ~/prj
git clone https://github.com/tensorflow/tensorflow.git
cd tensorflow
./tensorflow/lite/tools/make/download_dependencies.sh
./tensorflow/lite/tools/make/build_rpi_lib.sh
ls -al tensorflow/lite/tools/make/gen/rpi_armv7l/lib
drwxr-xr-x 2 root root 4096 Sep 9 02:32 .
drwxr-xr-x 5 root root 4096 Sep 9 02:32 ..
-rw-r--r-- 1 root root 12164884 Sep 9 02:32 benchmark-lib.a
-rw-r--r-- 1 root root 5796642 Sep 9 02:32 libtensorflow-lite.a
上記のページでは
tensorflow/lite/tools/make/gen/lib/rpi_armv7/libtensorflow-lite.a
ちょっと違う(笑)
tensorflow/lite/tools/make/gen/lib/rpi_armv7/libtensorflow-lite.a
ちょっと違う(笑)
Peace!!
Build Bazel(0.29.0) on Raspberry Pi 4
Bazel 0.26.0, 0.29.0のbuildです。
jdk は下記では8がサポート対象となっている
8にしないとエラーが発生する。このような対応不能なエラーが発生した。
#
# A fatal error has been detected by the Java Runtime Environment:
#
# Internal Error (g1ConcurrentMark.cpp:1666), pid=5210, tid=5234
# fatal error: Overflow during reference processing, can not continue. Please increase MarkStackSizeMax (current value: 2097152) and restart.
#
# JRE version: OpenJDK Runtime Environment (11.0.3+7) (build 11.0.3+7-post-Raspbian-5)
https://docs.bazel.build/versions/master/install-compile-source.html
もし違う場合には、確認して変更またはインストールする
下の例は0だったので、2に変更した後に、再度確認した画面
$ wget https://github.com/bazelbuild/bazel/releases/download/0.29.0/bazel-0.29.1-dist.zip
$ unzip bazel-0.29.0-dist.zip
$ EXTRA_BAZEL_ARGS="--host_javabase=@local_jdk//:jdk"
2つのファイルを変更
compile.sh
before
bazel_build "src:bazel_nojdk${EXE_EXT}" \
--action_env=PATH \
--host_platform=@bazel_tools//platforms:host_platform \
--platforms=@bazel_tools//platforms:target_platform \
|| fail "Could not build Bazel"
after
bazel_build "src:bazel_nojdk${EXE_EXT}" \
--host_javabase=@local_jdk//:jdk \
--action_env=PATH \
--host_platform=@bazel_tools//platforms:host_platform \
--platforms=@bazel_tools//platforms:target_platform \
|| fail "Could not build Bazel"
scripts/bootstrap/compile.sh
before
run "${JAVAC}" -classpath "${classpath}" -sourcepath "${sourcepath}" \
-d "${output}/classes" -source "$JAVA_VERSION" -target "$JAVA_VERSION" \
-encoding UTF-8 ${BAZEL_JAVAC_OPTS} "@${paramfile}"
after
run "${JAVAC}" -classpath "${classpath}" -sourcepath "${sourcepath}" \
-d "${output}/classes" -source "$JAVA_VERSION" -target "$JAVA_VERSION" \
-encoding UTF-8 ${BAZEL_JAVAC_OPTS} "@${paramfile}" -J-Xmx1024M
で、Go!!!
time comple.sh
この文字列が出ればOK
Build successful! Binary is here: /home/pi/tmp/output/bazel
次にコピーして完了
sudo cp output/bazel /usr/local/bin
tころで、こんなエラーがでた。
これは、上記の一番目の変更をしなかったから。。。
ERROR: /tmp/bazel_SwJ5aUhR/out/external/bazel_tools/tools/jdk/BUILD:492:14: Configurable attribute "actual" doesn't match this configuration: Could not find a JDK for host execution environment, please explicitly provide one using `--host_javabase.`
1.準備
sudo apt install openjdk-8-jdkjdk は下記では8がサポート対象となっている
8にしないとエラーが発生する。このような対応不能なエラーが発生した。
#
# A fatal error has been detected by the Java Runtime Environment:
#
# Internal Error (g1ConcurrentMark.cpp:1666), pid=5210, tid=5234
# fatal error: Overflow during reference processing, can not continue. Please increase MarkStackSizeMax (current value: 2097152) and restart.
#
# JRE version: OpenJDK Runtime Environment (11.0.3+7) (build 11.0.3+7-post-Raspbian-5)
https://docs.bazel.build/versions/master/install-compile-source.html
もし違う場合には、確認して変更またはインストールする
下の例は0だったので、2に変更した後に、再度確認した画面
sudo update-alternatives --config javac
There are 2 choices for the alternative javac (providing /usr/bin/javac).
Selection Path Priority Status
------------------------------------------------------------
0 /usr/lib/jvm/java-11-openjdk-armhf/bin/javac 1111 auto mode
1 /usr/lib/jvm/java-11-openjdk-armhf/bin/javac 1111 manual mode
* 2 /usr/lib/jvm/java-8-openjdk-armhf/bin/javac 1081 manual mode
Press <enter> to keep the current choice[*], or type selection number:
2. ソースのダウンロード
mkdir ~/prj/bazel;cd ~/prj/bazel$ wget https://github.com/bazelbuild/bazel/releases/download/0.29.0/bazel-0.29.1-dist.zip
$ unzip bazel-0.29.0-dist.zip
3. build前の設定と変更
環境変数追加$ EXTRA_BAZEL_ARGS="--host_javabase=@local_jdk//:jdk"
2つのファイルを変更
compile.sh
before
bazel_build "src:bazel_nojdk${EXE_EXT}" \
--action_env=PATH \
--host_platform=@bazel_tools//platforms:host_platform \
--platforms=@bazel_tools//platforms:target_platform \
|| fail "Could not build Bazel"
after
bazel_build "src:bazel_nojdk${EXE_EXT}" \
--host_javabase=@local_jdk//:jdk \
--action_env=PATH \
--host_platform=@bazel_tools//platforms:host_platform \
--platforms=@bazel_tools//platforms:target_platform \
|| fail "Could not build Bazel"
scripts/bootstrap/compile.sh
before
run "${JAVAC}" -classpath "${classpath}" -sourcepath "${sourcepath}" \
-d "${output}/classes" -source "$JAVA_VERSION" -target "$JAVA_VERSION" \
-encoding UTF-8 ${BAZEL_JAVAC_OPTS} "@${paramfile}"
after
run "${JAVAC}" -classpath "${classpath}" -sourcepath "${sourcepath}" \
-d "${output}/classes" -source "$JAVA_VERSION" -target "$JAVA_VERSION" \
-encoding UTF-8 ${BAZEL_JAVAC_OPTS} "@${paramfile}" -J-Xmx1024M
で、Go!!!
time comple.sh
この文字列が出ればOK
Build successful! Binary is here: /home/pi/tmp/output/bazel
次にコピーして完了
sudo cp output/bazel /usr/local/bin
tころで、こんなエラーがでた。
これは、上記の一番目の変更をしなかったから。。。
ERROR: /tmp/bazel_SwJ5aUhR/out/external/bazel_tools/tools/jdk/BUILD:492:14: Configurable attribute "actual" doesn't match this configuration: Could not find a JDK for host execution environment, please explicitly provide one using `--host_javabase.`
Peace!!
2019年8月31日土曜日
OpenCV4 Stereo matching
Stereo matchingは古くからある重要な手法。
僕も、いろいろな場面で使っている。
OpenCV4をセットアップしたあと、cpp ディレクトリーに移動
g++ `pkg-config opencv4 --cflags --libs` stereo_match.cpp -o stereo_match -std=c++11 -latomic
stereo_match ../data/aloeL.jpg ../data/aloeR.jpg --algorithm=sgbm --blocksize=3 --max-disparity=128
こんな感じでbuild とコンパイル
で、いろいろパラメータ変えるとこんな感じ
Peace!!
stm1 imgKittyl.bmp imgKitty.bmp --algorithm=sgbm --blocksize=1 --max-disparity=64
stm1 imgKittyl.bmp imgKitty.bmp --algorithm=sgbm --blocksize=1 --max-disparity=80
僕も、いろいろな場面で使っている。
OpenCV4をセットアップしたあと、cpp ディレクトリーに移動
g++ `pkg-config opencv4 --cflags --libs` stereo_match.cpp -o stereo_match -std=c++11 -latomic
stereo_match ../data/aloeL.jpg ../data/aloeR.jpg --algorithm=sgbm --blocksize=3 --max-disparity=128
こんな感じでbuild とコンパイル
で、いろいろパラメータ変えるとこんな感じ
更にフィルターをかけて、、
pip3 install scikit-learn
sudo apt install python3-sklearn
import numpy as np
from sklearn.preprocessing import normalize
import cv2
print('loading images...')
imgL = cv2.imread('../data/aloeLs.jpg') # downscale images for faster processing if you like
imgR = cv2.imread('../data/aloeRs.jpg')
# SGBM Parameters -----------------
window_size = 3
left_matcher = cv2.StereoSGBM_create(
minDisparity=0,
numDisparities=80,
blockSize=1,
P1=8 * 3 * window_size ** 2,
P2=32 * 3 * window_size ** 2,
disp12MaxDiff=1,
uniquenessRatio=15,
speckleWindowSize=0,
speckleRange=2,
preFilterCap=63,
mode=cv2.STEREO_SGBM_MODE_SGBM_3WAY
)
right_matcher = cv2.ximgproc.createRightMatcher(left_matcher)
# FILTER Parameters
lmbda = 80000
sigma = 1.2
visual_multiplier = 1.0
wls_filter = cv2.ximgproc.createDisparityWLSFilter(matcher_left=left_matcher)
wls_filter.setLambda(lmbda)
wls_filter.setSigmaColor(sigma)
print('computing disparity...')
displ = left_matcher.compute(imgL, imgR) # .astype(np.float32)/16
dispr = right_matcher.compute(imgR, imgL) # .astype(np.float32)/16
displ = np.int16(displ)
dispr = np.int16(dispr)
filteredImg = wls_filter.filter(displ, imgL, None, dispr) # important to put "imgL" here!!!
filteredImg = cv2.normalize(src=filteredImg, dst=filteredImg, beta=0, alpha=255, norm_type=cv2.NORM_MINMAX);
filteredImg = np.uint8(filteredImg)
cv2.imshow('Disparity Map', filteredImg)
cv2.waitKey()
cv2.destroyAllWindows()
Peace!!
stm1 imgKittyl.bmp imgKitty.bmp --algorithm=sgbm --blocksize=1 --max-disparity=64
stm1 imgKittyl.bmp imgKitty.bmp --algorithm=sgbm --blocksize=1 --max-disparity=80
stm1 imgKittyl.bmp imgKitty.bmp --algorithm=sgbm --blocksize=9 --max-disparity=64
2019年8月21日水曜日
Oracle SQL*Plus。MinGW32は癖がある (笑)
Oracle SQL*Plusを使うなんて20年ぶり
Windows環境で実行させて、結果をLinux環境に送り別の処理をする。
例えば、前日に新規登録されたデータだけを、翌日に抽出する場合。
Linux環境では、localtime_rで比較的簡単に日付指定の文字列を作れる。
ところが、Windows環境のMinGWは基本的にWindowsに依存しているので、
同じgccを使っても、localtime*は使用できない。
gccでも、違うんだぁ
Msys MinGWは、その環境で作った実行モジュールをWindowsのコマンドプロンプトで実行できない。
それをするなら、MinGWだけをインストールする必要がある。
MinGW | Minimalist GNU for Windows
Windows環境で実行させて、結果をLinux環境に送り別の処理をする。
例えば、前日に新規登録されたデータだけを、翌日に抽出する場合。
Linux環境では、localtime_rで比較的簡単に日付指定の文字列を作れる。
ところが、Windows環境のMinGWは基本的にWindowsに依存しているので、
同じgccを使っても、localtime*は使用できない。
gccでも、違うんだぁ
Msys MinGWは、その環境で作った実行モジュールをWindowsのコマンドプロンプトで実行できない。
それをするなら、MinGWだけをインストールする必要がある。
MinGW | Minimalist GNU for Windows
でも、MinGWはWindowsに依存しているのでLinuxとの違いが発生する。
多分、今回のlocaltime*だけだと思うけど、、、
まぁ、やるといろいろ起こります。勉強勉強
で、今回のソースをドーンと
Peace!!
SQL*Plusを起動するバッチ
@ECHO OFF
:START
ECHO ---------------------------------------------------
ECHO 前日新規に登録された品目情報を出力します。
ECHO ---------------------------------------------------
CD %~dp0
DEL hinsabun.csv
hinsabun.exe > hinsabun.sql
@ECHO SQLを実行中です。しばらくお待ち下さい..
@ECHO -------------------------------
sqlplus /nolog @"hinsabun.sql" USER PASSWORD 192.168.XXX.XXX/ORCL
@ECHO -------------------------------
@ECHO 完了しました。
EXIT
localtime_r を使わない処理
#include <stdio.h>
#include <string.h>
#include <time.h>
#define PRS(A) printf("%s\n", A)
char *mn[]= {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
int main(int argc, char* argv[]){
char szTime[15];
char szBuf[256], szBuf1[64];
char szMn[4], szDmy[10];
int n = 1, iDay, i, iMn, iYr;
struct tm tm;
time_t t;
time(&t);
t -= (86400 * n);
strcpy(szBuf1, ctime(&t));
strcpy(szDmy, strtok(szBuf1, " "));
strcpy(szMn, strtok(NULL, " "));
iDay = atoi(strtok(NULL, " "));
strcpy(szDmy, strtok(NULL, " "));
iYr = atoi(strtok(NULL, " "));
for (i = 0; i < 12; i++) {
if (strcmp(szMn, mn[i]) == 0){
iMn = i + 1;
break;
}
}
sprintf(szTime, "%04d%02d%02d", iYr, iMn, iDay);
//localtime_r(&t, &tm);
//sprintf(szTime, "%04d%02d%02d%02d%02d%02d",
// tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
// tm.tm_hour, tm.tm_min, tm.tm_sec);
//sprintf(szTime, "%04d%02d%02d",
// tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
PRS("connect &&1/&&2@&&3");
PRS("spool off");
PRS("set echo off");
PRS("set heading off");
PRS("set termout off");
PRS("set pause off");
PRS("set pagesize 0");
PRS("set linesize 10000");
PRS("--set trimout on");
PRS("set trimspool on");
PRS("set feedback off");
PRS("set verify off");
PRS("set colsep '|'");
PRS("spool hinsabun.csv");
sprintf(szBuf, "SELECT ITEM_CD, ITEM_DIV, ITEM_NAME1, ITEM_NAME2, STD_UNIT, STD_UNITPRICE, UNIT2, UNIT_CONV_RATE,ITEM_NAME4,REGIST_DATE, UPDATE_DATE from DFW_M040M where REGIST_DATE >= to_date('%s', 'yyyymmdd');", szTime);
PRS(szBuf);
PRS("spool off");
PRS("exit");
return 0;
}
Peace!!
2019年8月11日日曜日
AsyncTaskによるDB非同期処理をListenerを使ってクラス化
Android ActivityでDBを頻繁に使うプログラムを開発する場合に、
前項のようなコードをActivity内に組込むのはやめたい。
クラス化にあたっての課題は、処理の結果を呼び出したクラスに渡すか?
非同期処理処理を踏まえてどうするか。。。
で、先人の知恵を借りてListenerを使って呼び出し側で非同期処理の終了を
解るようにして、一件落着
ますます、便利になった。
Peace!!
ソースの先頭には、使い方を書いた。
サーバーサイドのDBプログラムは別途必要です。
ソースコード、どーんと(笑)
/***********************************************************
* AsyncTask<型1, 型2,型3>
* 型1 … Activityからスレッド処理へ渡したい変数の型
* ※ Activityから呼び出すexecute()の引数の型
* ※ doInBackground()の引数の型
* 型2 … 進捗度合を表示する時に利用したい型
* ※ onProgressUpdate()の引数の型
* 型3 … バックグラウンド処理完了時に受け取る型
* ※ doInBackground()の戻り値の型
* ※ onPostExecute()の引数の型
* ※ それぞれ不要な場合は、Voidを設定すれば良い
* --------------------------------------------------------------
* 呼び出す側に以下を追加する
********************************************************************************
* 汎用DBアクセスクラス SqlOpeAsyncTask を使う場合のListener設定
* クラスを使う側で設定する。
* onDestroyは、使うクラス側で重ならなければ使えるかも。未確認
* @return
* /
private SqlOpeAsyncTask.Listener createListener(){
return new SqlOpeAsyncTask.Listener(){
@Override
public void onSuccess(String ret){
// 以下は個々のプログラム毎に記述
etKata.setText(ret);
}
};
}
@Override
protected void onDestroy() {
SqlOpeAsyncTask.setListener(null);
super.onDestroy();
}
// 呼び出し例
String in1 = getResources().getString(R.string.url_srv_gets1);
String in2 = "?100:select kata,tana,hinc,kazu from zaiko where hinc = '15916-1' and tana <> 'REFER' order by tana DESC; ";
SqlOpeAsyncTask retAsyn = new SqlOpeAsyncTask();
retAsyn.setListener(createListener());
String inStr = in1 + in2;
Log.d(TAG, "before Async execute");
retAsyn.execute(inStr);
***********************************************************************/
package com.futureagri.app.thn.hd.java;
import android.nfc.Tag;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/******************************************************************
* 非同期でデータベース処理をするクラス。
******************************************************************/
public class SqlOpeAsyncTask extends AsyncTask<String, Void, String> {
private Listener listener;
private static final String TAG = "SqlOpeAsyncTask";
private String retString = "";
private TextView textView;
/********************************************************************
* メインスレッドとは別のスレッドで実行されます。
* 非同期で処理したい内容を記述します。
* このメソッドだけは必ず実装する必要があります
* @param data
* @return
*/
@Override
//protected String doInBackground(Object[] data) {
public String doInBackground(String... data) {
// target URL
String urlStr = (String)data[0];
Log.d(TAG, "doInBackground: " + "input sql=" + urlStr);
// Variable of set result texts
//StringBuilder result = new StringBuilder();
String result = "";
//http接続を行うHttpURLConnectionオブジェクトを宣言。finallyで確実に解放するためにtry外で宣言。
HttpURLConnection con = null;
//http接続のレスポンスデータとして取得するInputStreamオブジェクトを宣言。同じくtry外で宣言。
InputStream is = null;
int i = 10;
try {
//URLオブジェクトを生成。
URL url = new URL(urlStr);
//URLオブジェクトからHttpURLConnectionオブジェクトを取得。
con = (HttpURLConnection) url.openConnection();
//http接続メソッドを設定。
con.setRequestMethod("GET");
//接続。
con.connect();
final int status = con.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
// Success HTTP GET method
is = con.getInputStream();
result = is2String(is);
is.close();
}else {
Log.d(TAG, "doInBackground: HTTP response error");
}
} catch (MalformedURLException ex) {
ex.printStackTrace();
//} catch (ProtocolException ex) {
//ex.printStackTrace();
Log.d(TAG, "doInBackground: HTTP MalformedURLException");
} catch (IOException ex) {
ex.printStackTrace();
Log.d(TAG, "doInBackground: HTTP IOException");
} finally {
// HttpURLConnectionオブジェクトがnullでないなら解放。
if (con != null) {
con.disconnect();
}
// InputStreamオブジェクトがnullでないなら解放。
if (is != null) {
try {
is.close();
} catch (IOException ex) {
Log.d(TAG,"doInBackground: HTTP close is IOException");
}
}
}
// 非同期で取得したデータをセットする
if ( i == 0) {
Log.d(TAG, "doInBackground: HTTP return : error end");
return "-99999";
}else {
//return result.toString();
retString = result;
return result;
}
}
/*****************************************************************************
* doInBackgroundメソッドの実行後にメインスレッドで実行されます。
* doInBackgroundメソッドの戻り値をこのメソッドの引数として受け取り、
* その結果を画面に反映させることができます
* @param result
*/
@Override
public void onPostExecute(String result) {
//toastMake(result, 0, -200);
Log.d(TAG, "onPostExecute: result :" + result);
String[] ret = result.split("\\|"); // Mac \ -> (option + ¥)
int iMode = Integer.parseInt(ret[0]); // 呼び出した処理番号
int cnt = Integer.parseInt(ret[1]); // 検索数
int retu = Integer.parseInt(ret[2]); // 列数
Log.d(TAG, "onPostExecute: mode:cnt:retu=" + iMode + ":" + cnt + ":" + retu);
//-------------------------------------------------------------
// mode=100 kata,tana,hinc,kazu
//-------------------------------------------------------------
if (iMode == 100) {
retString = iMode + "|" + cnt + "|" + retu + "|";
for (int i = 0; i < cnt * retu; i++) {
retString = retString + ret[3 + i] + "|";
}
}
if (listener != null) {
listener.onSuccess(retString);
}
}
/*****************************************************************************
* InputStreamオブジェクトを文字列に変換するメソッド。変換文字コードはUTF-8。
*
* @param is 変換対象のInputStreamオブジェクト。
* @return 変換された文字列。
* @throws IOException 変換に失敗した時に発生。
*/
private String is2String(InputStream is) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
StringBuffer sb = new StringBuffer();
char[] b = new char[2048];
int line;
while(0 <= (line = reader.read(b))) {
sb.append(b, 0, line);
}
return sb.toString();
}
/************************************************************
* Listener 処理を定義する
*
* @param listener
*/
void setListener(Listener listener) {
this.listener = listener;
}
interface Listener {
void onSuccess(String count);
}
}
前項のようなコードをActivity内に組込むのはやめたい。
クラス化にあたっての課題は、処理の結果を呼び出したクラスに渡すか?
非同期処理処理を踏まえてどうするか。。。
で、先人の知恵を借りてListenerを使って呼び出し側で非同期処理の終了を
解るようにして、一件落着
ますます、便利になった。
Peace!!
ソースの先頭には、使い方を書いた。
サーバーサイドのDBプログラムは別途必要です。
ソースコード、どーんと(笑)
/***********************************************************
* AsyncTask<型1, 型2,型3>
* 型1 … Activityからスレッド処理へ渡したい変数の型
* ※ Activityから呼び出すexecute()の引数の型
* ※ doInBackground()の引数の型
* 型2 … 進捗度合を表示する時に利用したい型
* ※ onProgressUpdate()の引数の型
* 型3 … バックグラウンド処理完了時に受け取る型
* ※ doInBackground()の戻り値の型
* ※ onPostExecute()の引数の型
* ※ それぞれ不要な場合は、Voidを設定すれば良い
* --------------------------------------------------------------
* 呼び出す側に以下を追加する
********************************************************************************
* 汎用DBアクセスクラス SqlOpeAsyncTask を使う場合のListener設定
* クラスを使う側で設定する。
* onDestroyは、使うクラス側で重ならなければ使えるかも。未確認
* @return
* /
private SqlOpeAsyncTask.Listener createListener(){
return new SqlOpeAsyncTask.Listener(){
@Override
public void onSuccess(String ret){
// 以下は個々のプログラム毎に記述
etKata.setText(ret);
}
};
}
@Override
protected void onDestroy() {
SqlOpeAsyncTask.setListener(null);
super.onDestroy();
}
// 呼び出し例
String in1 = getResources().getString(R.string.url_srv_gets1);
String in2 = "?100:select kata,tana,hinc,kazu from zaiko where hinc = '15916-1' and tana <> 'REFER' order by tana DESC; ";
SqlOpeAsyncTask retAsyn = new SqlOpeAsyncTask();
retAsyn.setListener(createListener());
String inStr = in1 + in2;
Log.d(TAG, "before Async execute");
retAsyn.execute(inStr);
***********************************************************************/
package com.futureagri.app.thn.hd.java;
import android.nfc.Tag;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/******************************************************************
* 非同期でデータベース処理をするクラス。
******************************************************************/
public class SqlOpeAsyncTask extends AsyncTask<String, Void, String> {
private Listener listener;
private static final String TAG = "SqlOpeAsyncTask";
private String retString = "";
private TextView textView;
/********************************************************************
* メインスレッドとは別のスレッドで実行されます。
* 非同期で処理したい内容を記述します。
* このメソッドだけは必ず実装する必要があります
* @param data
* @return
*/
@Override
//protected String doInBackground(Object[] data) {
public String doInBackground(String... data) {
// target URL
String urlStr = (String)data[0];
Log.d(TAG, "doInBackground: " + "input sql=" + urlStr);
// Variable of set result texts
//StringBuilder result = new StringBuilder();
String result = "";
//http接続を行うHttpURLConnectionオブジェクトを宣言。finallyで確実に解放するためにtry外で宣言。
HttpURLConnection con = null;
//http接続のレスポンスデータとして取得するInputStreamオブジェクトを宣言。同じくtry外で宣言。
InputStream is = null;
int i = 10;
try {
//URLオブジェクトを生成。
URL url = new URL(urlStr);
//URLオブジェクトからHttpURLConnectionオブジェクトを取得。
con = (HttpURLConnection) url.openConnection();
//http接続メソッドを設定。
con.setRequestMethod("GET");
//接続。
con.connect();
final int status = con.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
// Success HTTP GET method
is = con.getInputStream();
result = is2String(is);
is.close();
}else {
Log.d(TAG, "doInBackground: HTTP response error");
}
} catch (MalformedURLException ex) {
ex.printStackTrace();
//} catch (ProtocolException ex) {
//ex.printStackTrace();
Log.d(TAG, "doInBackground: HTTP MalformedURLException");
} catch (IOException ex) {
ex.printStackTrace();
Log.d(TAG, "doInBackground: HTTP IOException");
} finally {
// HttpURLConnectionオブジェクトがnullでないなら解放。
if (con != null) {
con.disconnect();
}
// InputStreamオブジェクトがnullでないなら解放。
if (is != null) {
try {
is.close();
} catch (IOException ex) {
Log.d(TAG,"doInBackground: HTTP close is IOException");
}
}
}
// 非同期で取得したデータをセットする
if ( i == 0) {
Log.d(TAG, "doInBackground: HTTP return : error end");
return "-99999";
}else {
//return result.toString();
retString = result;
return result;
}
}
/*****************************************************************************
* doInBackgroundメソッドの実行後にメインスレッドで実行されます。
* doInBackgroundメソッドの戻り値をこのメソッドの引数として受け取り、
* その結果を画面に反映させることができます
* @param result
*/
@Override
public void onPostExecute(String result) {
//toastMake(result, 0, -200);
Log.d(TAG, "onPostExecute: result :" + result);
String[] ret = result.split("\\|"); // Mac \ -> (option + ¥)
int iMode = Integer.parseInt(ret[0]); // 呼び出した処理番号
int cnt = Integer.parseInt(ret[1]); // 検索数
int retu = Integer.parseInt(ret[2]); // 列数
Log.d(TAG, "onPostExecute: mode:cnt:retu=" + iMode + ":" + cnt + ":" + retu);
//-------------------------------------------------------------
// mode=100 kata,tana,hinc,kazu
//-------------------------------------------------------------
if (iMode == 100) {
retString = iMode + "|" + cnt + "|" + retu + "|";
for (int i = 0; i < cnt * retu; i++) {
retString = retString + ret[3 + i] + "|";
}
}
if (listener != null) {
listener.onSuccess(retString);
}
}
/*****************************************************************************
* InputStreamオブジェクトを文字列に変換するメソッド。変換文字コードはUTF-8。
*
* @param is 変換対象のInputStreamオブジェクト。
* @return 変換された文字列。
* @throws IOException 変換に失敗した時に発生。
*/
private String is2String(InputStream is) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
StringBuffer sb = new StringBuffer();
char[] b = new char[2048];
int line;
while(0 <= (line = reader.read(b))) {
sb.append(b, 0, line);
}
return sb.toString();
}
/************************************************************
* Listener 処理を定義する
*
* @param listener
*/
void setListener(Listener listener) {
this.listener = listener;
}
interface Listener {
void onSuccess(String count);
}
}
2019年8月2日金曜日
Android 非同期処理でサーバサービスを利用する
スマフォからデータベース処理する方法のメモ
至る所に掲載されているので、あくまでも自分のメモ
基本的にデータ量が少ないのでGETメソッドで説明
ちなみに、com.squareup.okhttp3:okhttp:3.12.1 を使っています。
非同期処理のHTTPサービスのオブジェクトを作成して実行
Object[] data = new Object[3];
data[0] = getResources().getString(R.string.url_srv_reg_payout);
// 引数を設定する
data[1] =
hdPartsActivity.SqlSelectReciever receiver =
new hdPartsActivity.SqlSelectReciever();
receiver.execute(qq);
public SqlSelectReciever() {
}
@Override
public String doInBackground(String... params) {
// target URL
String urlStr = (String)params[0];
Log.d(TAG, " SqlSelectReciever: " + "sql=" + urlStr);
// Variable of set result texts
//StringBuilder result = new StringBuilder();
String result = "";
//http接続を行うHttpURLConnectionオブジェクトを宣言。finallyで確実に解放するためにtry外で宣言。
HttpURLConnection con = null;
//http接続のレスポンスデータとして取得するInputStreamオブジェクトを宣言。同じくtry外で宣言。
InputStream is = null;
int i = 10;
try {
//URLオブジェクトを生成。
URL url = new URL(urlStr);
//URLオブジェクトからHttpURLConnectionオブジェクトを取得。
con = (HttpURLConnection) url.openConnection();
//http接続メソッドを設定。
con.setRequestMethod("GET");
//接続。
con.connect();
final int status = con.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
// Success HTTP GET method
is = con.getInputStream();
result = is2String(is);
Log.d(TAG, " HTTP connect result=" + result);
is.close();
}else {
Log.d(TAG, "HTTP response error");
}
} catch (MalformedURLException ex) {
ex.printStackTrace();
//} catch (ProtocolException ex) {
//ex.printStackTrace();
Log.d(TAG, "HTTP MalformedURLException");
} catch (IOException ex) {
ex.printStackTrace();
Log.d(TAG, "HTTP IOException");
} finally {
// HttpURLConnectionオブジェクトがnullでないなら解放。
if (con != null) {
Log.d(TAG, "HTTP not null");
con.disconnect();
}
// InputStreamオブジェクトがnullでないなら解放。
if (is != null) {
Log.d(TAG,"HTTP close InputStream");
try {
is.close();
} catch (IOException ex) {
Log.d(TAG,"HTTP close is IOException");
}
}
}
//JSON文字列を返す。
if ( i == 0) {
Log.d(TAG, "HTTP return : error");
return "error";
}else {
//Log.d("doInBackground:return:", result.toString());
//return result.toString();
//Log.d(TAG, "HTTP return : normal");
return result;
}
}
//=================================================
// サーバから戻ってきた戻り値に対する処理
// ここの部分が大事。
// Activityの中で複数の非同期処理をする時もここにを書く。
// 因みに僕は戻り値の最初の情報cntとretuを使って複数対応している。
//=================================================
@Override
public void onPostExecute(String result) {
String[] ret = result.split("\\|"); // Mac \ -> (option + ¥)
int cnt = Integer.parseInt(ret[0]); // 1行目:検索数
int retu = Integer.parseInt(ret[1]); // 1行目:列数
Log.d(TAG, "cnt:retu=" + cnt + ":" + retu);
・
・ ここにいろいろ処理を書く、
・
Intent intent = new Intent(hdPartsActivity.this, SqlGetList2.class);
// intentへ添え字付で値を保持させる
intent.putExtra( "hdkey", hks);
// 返却したい結果ステータスをセットする
setResult( SqlGetList2.RESULT_OK, intent );
//startActivity(new Intent(hdSeibanListActivity.this, SqlGetList2.class));
startActivity(intent);
//Log.d(TAG, " Intent after : startActivity(intent)");
return;
}
/**
* InputStream objectを文字列に変換するmethod。変換文字codeはUTF-8。
*
* @param is 変換対象のInputStreamオブジェクト。
* @return 変換された文字列。
* @throws IOException 変換に失敗した時に発生。
*/
private String is2String(InputStream is) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
StringBuffer sb = new StringBuffer();
char[] b = new char[1024];
int line;
while(0 <= (line = reader.read(b))) {
sb.append(b, 0, line);
}
return sb.toString();
}
}
至る所に掲載されているので、あくまでも自分のメモ
基本的にデータ量が少ないのでGETメソッドで説明
ちなみに、com.squareup.okhttp3:okhttp:3.12.1 を使っています。
1.基本的な流れ
・スマフォ側で、起動するサーバサイドのサービスの定義と渡す情報の設定
・非同期処理部分(AsyncTask)の記述。
基本部分は一度書けば使いまわし。
大事なのは、onPostExecuteの部分。
この部分にサーバから戻ってきたデータに対する処理を記述する。
この投稿では、データをチェックしたあと、Intentで別のActivity起動している
2. スマフォ側でサーバプログラム起動の準備
オブジェクト作成と、起動サービス、引数の設定非同期処理のHTTPサービスのオブジェクトを作成して実行
Object[] data = new Object[3];
data[0] = getResources().getString(R.string.url_srv_reg_payout);
// 引数を設定する
data[1] =
hdPartsActivity.SqlSelectReciever receiver =
new hdPartsActivity.SqlSelectReciever();
receiver.execute(qq);
3.非同期処理(AsyncTask)を担当する本体部分
private class SqlSelectReciever extends AsyncTask<String, String, String> {public SqlSelectReciever() {
}
@Override
public String doInBackground(String... params) {
// target URL
String urlStr = (String)params[0];
Log.d(TAG, " SqlSelectReciever: " + "sql=" + urlStr);
// Variable of set result texts
//StringBuilder result = new StringBuilder();
String result = "";
//http接続を行うHttpURLConnectionオブジェクトを宣言。finallyで確実に解放するためにtry外で宣言。
HttpURLConnection con = null;
//http接続のレスポンスデータとして取得するInputStreamオブジェクトを宣言。同じくtry外で宣言。
InputStream is = null;
int i = 10;
try {
//URLオブジェクトを生成。
URL url = new URL(urlStr);
//URLオブジェクトからHttpURLConnectionオブジェクトを取得。
con = (HttpURLConnection) url.openConnection();
//http接続メソッドを設定。
con.setRequestMethod("GET");
//接続。
con.connect();
final int status = con.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
// Success HTTP GET method
is = con.getInputStream();
result = is2String(is);
Log.d(TAG, " HTTP connect result=" + result);
is.close();
}else {
Log.d(TAG, "HTTP response error");
}
} catch (MalformedURLException ex) {
ex.printStackTrace();
//} catch (ProtocolException ex) {
//ex.printStackTrace();
Log.d(TAG, "HTTP MalformedURLException");
} catch (IOException ex) {
ex.printStackTrace();
Log.d(TAG, "HTTP IOException");
} finally {
// HttpURLConnectionオブジェクトがnullでないなら解放。
if (con != null) {
Log.d(TAG, "HTTP not null");
con.disconnect();
}
// InputStreamオブジェクトがnullでないなら解放。
if (is != null) {
Log.d(TAG,"HTTP close InputStream");
try {
is.close();
} catch (IOException ex) {
Log.d(TAG,"HTTP close is IOException");
}
}
}
//JSON文字列を返す。
if ( i == 0) {
Log.d(TAG, "HTTP return : error");
return "error";
}else {
//Log.d("doInBackground:return:", result.toString());
//return result.toString();
//Log.d(TAG, "HTTP return : normal");
return result;
}
}
//=================================================
// サーバから戻ってきた戻り値に対する処理
// ここの部分が大事。
// Activityの中で複数の非同期処理をする時もここにを書く。
// 因みに僕は戻り値の最初の情報cntとretuを使って複数対応している。
//=================================================
@Override
public void onPostExecute(String result) {
String[] ret = result.split("\\|"); // Mac \ -> (option + ¥)
int cnt = Integer.parseInt(ret[0]); // 1行目:検索数
int retu = Integer.parseInt(ret[1]); // 1行目:列数
Log.d(TAG, "cnt:retu=" + cnt + ":" + retu);
・
・ ここにいろいろ処理を書く、
・
Intent intent = new Intent(hdPartsActivity.this, SqlGetList2.class);
// intentへ添え字付で値を保持させる
intent.putExtra( "hdkey", hks);
// 返却したい結果ステータスをセットする
setResult( SqlGetList2.RESULT_OK, intent );
//startActivity(new Intent(hdSeibanListActivity.this, SqlGetList2.class));
startActivity(intent);
//Log.d(TAG, " Intent after : startActivity(intent)");
return;
}
/**
* InputStream objectを文字列に変換するmethod。変換文字codeはUTF-8。
*
* @param is 変換対象のInputStreamオブジェクト。
* @return 変換された文字列。
* @throws IOException 変換に失敗した時に発生。
*/
private String is2String(InputStream is) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
StringBuffer sb = new StringBuffer();
char[] b = new char[1024];
int line;
while(0 <= (line = reader.read(b))) {
sb.append(b, 0, line);
}
return sb.toString();
}
}
Peace!!
登録:
投稿 (Atom)






