2012年6月30日土曜日

Android端末の音楽ファイルをパソコンで聞く:Bluetooth

使用Bluetoothアダプタ:BUFFALO BSHSBD04BK

ペアリング済のディバイスを接続して、
Media にチェックを入れる。

オーディオの音楽再生の部分が自動的に接続状態になる。

アンドロイド端末で普通再生すればパソコンでも再生される。


プログラムで再生
SDカードの中のファイルをメディアプレイヤーで再生させて、
パソコンにBluetoothで接続して、パソコンでも再生させる。

import android.content.*;
import android.app.Activity;
import android.os.Bundle;
import android.media.*;
import java.io.*;
import android.util.Log;

public class AnTemptestActivity extends Activity
{
    private static final String TAG = "BTAudioActivity";

    private MediaPlayer mPlayer = null;
    private AudioManager amanager = null;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        amanager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        amanager.setBluetoothScoOn(true);
        amanager.setMode(AudioManager.MODE_IN_CALL);

        mPlayer = new MediaPlayer();

        try {
            mPlayer.setDataSource(new FileInputStream("/sdcard/Voice/rec.3gpp").getFD());

            mPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);

            mPlayer.prepare();

            mPlayer.start();
        } catch(Exception e) {
            Log.e(TAG, e.toString());
        }
    }

    @Override
    public void onDestroy()
    {
        mPlayer.stop();
        amanager.setMode(AudioManager.MODE_NORMAL);
        amanager.setBluetoothScoOn(false);
        super.onDestroy();
    }
}


2012年6月24日日曜日

中華タブレットの日本語化

1.表示を日本語化して、
2.日本語入力を可能にする。

1.Google Play から
More Locale 2をインストールする。

インストールしたアプリのアイコンを選択

Japanese(Japan) を選択する。


日本語された


2.日本語入力を可能にする。
Google Play で japanese keyboard と検索して、
Google 日本語入力を選択して、ダウンロードする。



Settings -> Language & keyboard settings を選択して、
Google日本語入力Bata にチェックを入れる。



日本語入力が可能になった。


2012年6月19日火曜日

AndroidでGoogle クラウド プリントを使ってみる:準備編

1、Chromeをインストールする。
Google Chrome - ブラウザのダウンロード

2、Google アカウントを取得しておく。

3、Chromeでの設定





プリンタの管理をクリック。


今度は、SDカードに保存されているHTMLファイルをGoogle クラウドプリントで出力するプログラムを書いてみた。
AndroidでGoogle クラウド プリントを使ってみる

Google クラウド プリントでSDカードのデータ印刷

Google クラウド プリントがAndroid からも利用出来るみたいなのでやってみた。
googleのブラウザChromでの設定が必要ですが、普段使っているプリンタが利用できるのでいい。
Chromeでの設定を書いてみる。

SDカードに保存されているHTMLファイルを出力してみる。

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;

public class Anprint2Activity extends Activity {
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  // setContentView(R.layout.main);

  Intent printIntent = new Intent(this, PrintDialogActivity.class);

  printIntent.setDataAndType(Uri.parse("file:///mnt/sdcard/index.html"),
    "text/plain");

  printIntent.putExtra("title", "docTitle");
  startActivity(printIntent);
 }
}

PrintDialogActivity は下記アドレスの丸写しです。
https://developers.google.com/cloud-print/docs/android
マニフェストファイルにもアクティビティーを設定する
ついでに下記の許可も与えておく
<uses-permission android:name="android.permission.INTERNET"/>

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.Intent;
import android.os.Bundle;
import android.util.Base64;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class PrintDialogActivity extends Activity {
  private static final String PRINT_DIALOG_URL = "https://www.google.com/cloudprint/dialog.html";
  private static final String JS_INTERFACE = "AndroidPrintDialog";
  private static final String CONTENT_TRANSFER_ENCODING = "base64";

  private static final String ZXING_URL = "http://zxing.appspot.com";
  private static final int ZXING_SCAN_REQUEST = 65743;

  /**
   * Post message that is sent by Print Dialog web page when the printing dialog
   * needs to be closed.
   */
  private static final String CLOSE_POST_MESSAGE_NAME = "cp-dialog-on-close";

  /**
   * Web view element to show the printing dialog in.
   */
  private WebView dialogWebView;

  /**
   * Intent that started the action.
   */
  Intent cloudPrintIntent;

  @Override
  public void onCreate(Bundle icicle) {
    super.onCreate(icicle);

    setContentView(R.layout.print_dialog);
    dialogWebView = (WebView) findViewById(R.id.webview);
    cloudPrintIntent = this.getIntent();

    WebSettings settings = dialogWebView.getSettings();
    settings.setJavaScriptEnabled(true);

    dialogWebView.setWebViewClient(new PrintDialogWebClient());
    dialogWebView.addJavascriptInterface(
      new PrintDialogJavaScriptInterface(), JS_INTERFACE);

    dialogWebView.loadUrl(PRINT_DIALOG_URL);
  }

  @Override
  public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    if (requestCode == ZXING_SCAN_REQUEST && resultCode == RESULT_OK) {
      dialogWebView.loadUrl(intent.getStringExtra("SCAN_RESULT"));
    }
  }

  final class PrintDialogJavaScriptInterface {
    public String getType() {
      return cloudPrintIntent.getType();
    }

    public String getTitle() {
      return cloudPrintIntent.getExtras().getString("title");
    }

    public String getContent() {
      try {
        ContentResolver contentResolver = getContentResolver();
        InputStream is = contentResolver.openInputStream(cloudPrintIntent.getData());
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        byte[] buffer = new byte[4096];
        int n = is.read(buffer);
        while (n >= 0) {
          baos.write(buffer, 0, n);
          n = is.read(buffer);
        }
        is.close();
        baos.flush();

        return Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);
      } catch (FileNotFoundException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }
      return "";
    }

    public String getEncoding() {
      return CONTENT_TRANSFER_ENCODING;
    }

    public void onPostMessage(String message) {
      if (message.startsWith(CLOSE_POST_MESSAGE_NAME)) {
        finish();
      }
    }
  }

  private final class PrintDialogWebClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
      if (url.startsWith(ZXING_URL)) {
        Intent intentScan = new Intent("com.google.zxing.client.android.SCAN");
        intentScan.putExtra("SCAN_MODE", "QR_CODE_MODE");
        try {
          startActivityForResult(intentScan, ZXING_SCAN_REQUEST);
        } catch (ActivityNotFoundException error) {
          view.loadUrl(url);
        }
      } else {
        view.loadUrl(url);
      }
      return false;
    }

    @Override
    public void onPageFinished(WebView view, String url) {
      if (PRINT_DIALOG_URL.equals(url)) {
        // Submit print document.
        view.loadUrl("javascript:printDialog.setPrintDocument(printDialog.createPrintDocument("
          + "window." + JS_INTERFACE + ".getType(),window." + JS_INTERFACE + ".getTitle(),"
          + "window." + JS_INTERFACE + ".getContent(),window." + JS_INTERFACE + ".getEncoding()))");

        // Add post messages listener.
        view.loadUrl("javascript:window.addEventListener('message',"
            + "function(evt){window." + JS_INTERFACE + ".onPostMessage(evt.data)}, false)");
      }
    }
  }
}

プログラムを実行すると、
サインアップ画面が表示される。

プリンタを選択する。

Print を選択する


うまく送られているようですが、何が悪いのか、このタイミングで5010エラーが出て、
プリンタが壊れた模様。

2012年6月18日月曜日

AndroidとJavaScriptの連携:WebView addJavascriptInterface





①、Android側:WebView で assets フォルダの HTMLファイルを表示。
②、HTMLファイル読み込み後、データ送信(実行するJavaScript)。
③、HTML側:Adnroid から送られてきたデータを表示。その後、
④、Androidにデータを送り返す。
⑤、Android側:HTMから受け取ったデータをTextViewに表示

 
<html>
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <script src="jquery.min.js"></script>
  <script type="text/javascript">
   function anFunc(arg) {
    // Javaからのデータを処理
    //$("div#test").append("jQueryで表示");//jQueryは今回使わない
    var element=document.getElementById("test").innerText="Android から送られた文字:" + arg;//③
    
    //Javaのメソッドを呼び出す Androidにデータを送信④
    //window.interfaceName.makeToast();//Tostを表示する場合
    window.interfaceName.logOutput("HTMLからのデータ");//LogCatに出力する場合
    window.interfaceName.viewOut(",HTMLからのデータ");//TextViewに表示する場合
   }
  </script>

 </head>
 <body>
  <div>
   ここはHTMLで表示
  </div>
  <div id="test"></div>
 </body>
</html>
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
import android.widget.Toast;

public class HtmlViewActivity extends Activity {
 private WebView webview;
 private Handler mHandler = new Handler();
 /** Called when the activity is first created. */
    @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  
  //webview = new WebView(this);
        webview = (WebView) findViewById(R.id.webView1);
 
  webview.setWebViewClient(new WebViewClient() {});

  // JavaScriptを有効にする
  webview.getSettings().setJavaScriptEnabled(true);
  
  // JavaScriptにJavaオブジェクトを登録する
     // 第2引数で指定した名前で、Javascriptからオブジェクトにアクセスできます。
  webview.addJavascriptInterface(new className(this), "interfaceName");

  //ページ読み込み完了時の処理
  webview.setWebViewClient(new WebViewClient() {
        @Override
        public void onPageFinished(WebView view, String url)
        {
        //ページ読み込み後データ送信
         String script = "javascript:anFunc('5');";
            webview.loadUrl( script );//②
        }
    });

  //ページを読み込み
  webview.loadUrl("file:///android_asset/test3.html");//①


  //setContentView(webview);
    }
 
/*
⑤ HTMLからのデータ処理
*/
 public class className {
  private Context con;
  
  public className(HtmlViewActivity htmlViewActivity) {
   // TODO 自動生成されたコンストラクター・スタブ
    this.con = htmlViewActivity;
  }
  //Tostを表示する場合
  public void makeToast() {
      Toast.makeText(con, "Tost表示", Toast.LENGTH_LONG).show();
  }
  //LogCatに出力する場合
  public void logOutput(String text) {
    Log.d("LOG", text);//
  }
  //TextViewに表示する場合
  public void viewOut(final String text) {
   final TextView textView = (TextView) findViewById(R.id.textView1);
   //textView.append(text);//error
   mHandler.post(new Runnable() {
    public void run() {
     // TODO 自動生成されたメソッド・スタブ
     textView.append(text);//OK
    }
   });
  }

 }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >



    <WebView
        android:id="@+id/webView1"
        android:layout_width="match_parent"
        android:layout_height="132dp" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="false"
        android:text="ここはTextView" />

</LinearLayout>

WebView でjQueryを使ってみる。:Android


<html>
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <script src="jquery.min.js"></script>
  <script>
   $(function() {
    $("div#test").append("jQueryで表示");
   });
  </script>
 </head>
 <body>
  <div>ここはHTMLで表示</div>
  <div id="test"></div>

 </body>
</html>

import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class HtmlViewActivity extends Activity {
 /** Called when the activity is first created. */
    @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  WebView webview = new WebView(this);
  webview.setWebViewClient(new WebViewClient() {});  

  // JavaScriptを有効にする
  webview.getSettings().setJavaScriptEnabled(true);

  //ページを読み込み
  webview.loadUrl("file:///android_asset/test3.html");

  setContentView(webview);
    }
}

assetsフォルダの中のHTMLファイルでjQuery を使ってみる。
1.assetsフォルダにjQueryを入れて使う方法
上記のソース

2.GoogleでホストされているjQueryを使う方法
Google Libraries API - Developer's Guide

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript">

2012年6月17日日曜日

Android から JavaScript を実行:Android WebView


Android から JavaScript で HTML のテキストを文字を赤くしている。


<html>
 <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>addJavascriptInterfaceサンプル</title>
</head>
 <body>
  <h1>Android と JavaScriptの連携</h1>
  <div id="text">123</div>
 </body>
</html>

import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class HtmlViewActivity extends Activity {

 private WebView webview;
 private String script;

 /** Called when the activity is first created. */
    @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  webview = new WebView(this);
  script = "javascript:document.getElementById('text').style.color = 'red';";
  // JavaScriptを有効にする
  webview.getSettings().setJavaScriptEnabled(true);
  //ページ読み込み後JavaScriptを実行
  webview.setWebViewClient(new WebViewClient() {  
      @Override  
      public void onPageFinished(WebView view, String url)  
      {  
          webview.loadUrl( script );  
      }  
  });  
  
  //ページを読み込み
  webview.loadUrl("file:///android_asset/test4.html");

  setContentView(webview);
    }
}


HTML から Android に情報を送る


Html のボタンをタップすると、Android で Tost を表示する。

<html>
 <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>addJavascriptInterfaceサンプル</title>
</head>
 <body>
  <h1>Android と JavaScriptの連携</h1>
  <button onClick="andjs.makeToast()">Toastを表示</button>
 </body>
</html>

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.webkit.WebView;
import android.widget.Toast;

public class HtmlViewActivity extends Activity {
 public class JsObject {

  private Context con;

  public JsObject(Context con) {
   this.con = con;
  }
  public void makeToast() {
   Toast.makeText(con, "Tost表示", Toast.LENGTH_LONG).show();
  }
 }

 /** Called when the activity is first created. */
    @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  WebView webview = new WebView(this);
  // JavaScriptを有効にする
  webview.getSettings().setJavaScriptEnabled(true);

  webview.loadUrl("file:///android_asset/test4.html");
  JsObject jsObj = new JsObject(this);

  webview.addJavascriptInterface(jsObj, "andjs");

  setContentView(webview);
    }
}

html データを作って表示:Android WebView loadData



import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;

public class HtmlViewActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        WebView webview = (WebView) findViewById(R.id.webView1);
        String data = "<html><head><meta http-equiv=\"content-type\" content=\"text/html;charset=UTF-8\"></head>";
        data +=  "<body>HTML データを作って表示</body></html>";
        webview.loadData(data, "text/html", "UTF-8");
        
    }
}

JavaScript を含める場合

import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;

public class HtmlViewActivity extends Activity {

 private WebView webview;
 private String html;

 /** Called when the activity is first created. */
    @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  webview = new WebView(this);
  html = "<html><head><meta http-equiv=\"content-type\" content=\"text/html;charset=UTF-8\">";
  html +=  "<script type=\"text/javascript\"> document.write('JavaScriptで表示<br />');</script>";
  html +=  "</head>";
  html +=  "<body>HTML データを作って表示</body></html>";
        
  // JavaScriptを有効にする
  webview.getSettings().setJavaScriptEnabled(true);
  
  
  //ページを読み込み
   webview.loadData(html, "text/html", "UTF-8");

  setContentView(webview);
    }
}

WebViewの使い方:Android


URLを指定してホームページ表示

import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;

public class HtmlViewActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        WebView webview = (WebView) findViewById(R.id.webView1);
        webview.loadUrl("http://www.google.com");
        
    }
}

assets フォルダに保存されているファイルを表示する場合
webview.loadUrl( "file:///android_asset/test.html" );

JavaScripr を有効にする
webview.getSettings().setJavaScriptEnabled(true);

文字の大きさの指定:Android setTextSize

Android で文字の大きさについて調べてみる。

setTextSize() の単位は SPが使われているらしい。
例:
setTextSize (20);

sp(scaled pixel):解像度に応じて伸縮する

dp (dip:Density-independent Pixels ):端末のdpiによってサイズが切り替わる。
160 dpi の画面で 1 dp = 1 px

レイアウトにはdpを使ってテキストはspで記述すると同じ表示になるそうです。

sp,dp から px の変更
20sp x 1.5(scaledDensity) = 30px //未確認

scaledDensityの調べ方

// ディスプレイ情報の取得
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
         
Log.d("test", "density=" + metrics.density);  
Log.d("test", "densityDpi=" + metrics.densityDpi);  
Log.d("test", "scaledDensity=" + metrics.scaledDensity);  
Log.d("test", "widthPixels=" + metrics.widthPixels);  
Log.d("test", "heightPixels=" + metrics.heightPixels);  
Log.d("test", "xDpi=" + metrics.xdpi);  
Log.d("test", "yDpi=" + metrics.ydpi);  



2012年6月15日金曜日

Androidで縦書き5:禁則処理を考える

。だけを考えてみる。

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

public class TategakiActivity extends Activity {

 public class CustomView extends View {
  private int width;
  private int w;
  private Paint paint;

  public CustomView(Context context) {
   super(context);
   setFocusable(true);
  }

  protected void onDraw(Canvas canvas) {
   super.onDraw(canvas);
   int textCount = 40;//一行の文字数
   
   //キャンバスサイズの取得
   int height = canvas.getHeight();// 800ピクセル
   width = canvas.getWidth();// 480ピクセル

   paint = new Paint();
   paint.setAntiAlias(true);

   paint.setColor(Color.WHITE);
   paint.setTextSize(20);
   
   String text = " 親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。";
   int textLength = text.length();
   System.out.println( text.length() );
   
   //必要な行数
   int line = textLength / textCount ;//1
   int linePlus = textLength % textCount;
   System.out.println( line + "::" + linePlus );
   
   int low = height / textCount;//固定値 20 文字の高さ
   w = low ;//上からの位置 変化する 20
   int moveText = 0;
   for ( int j = 1 ; j < 3 ; j++ ){
    for (int i = 0 ; i < 40 ; i++ ) {
     String moji = String.valueOf(text.charAt( moveText ));
     //描画と禁則処理
     drawCanvas(canvas,moji,j);
     moveText += 1;
     w = w + low;
    }
     w = low ;
   }
  }
/*
 * 描画と禁則処理
 */
  private void drawCanvas(Canvas canvas, String moji, int j) {
   // TODO 自動生成されたメソッド・スタブ   
   if ( !moji.equals("。")  ){
    canvas.drawText( moji , width-20*j, w, paint);
   }else{
    canvas.save();
    canvas.rotate(180, width-20*j+10, w-7);//角度 中心x 中心y
    canvas.drawText( "。" ,  width-20*j, w, paint);
    canvas.restore();
   }

  }
 }
 
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  // ステータスバー削除    
  getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 
  
  // タイトルバーの削除    
  requestWindowFeature(Window.FEATURE_NO_TITLE);
  
  View drawView = new CustomView(this);
  setContentView(drawView);
 }
}

今度は WebView で縦書きにしてみる。

Androidで縦書き4:複数行を表示する。


1列40文字を2行表示する。

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

public class TategakiActivity extends Activity {

 public class CustomView extends View {
  public CustomView(Context context) {
   super(context);
   setFocusable(true);
  }

  protected void onDraw(Canvas canvas) {
   super.onDraw(canvas);
   int textCount = 40;//一行の文字数
   
   //キャンバスサイズの取得
   int height = canvas.getHeight();// 800ピクセル
   int width = canvas.getWidth();// 480ピクセル

   Paint paint = new Paint();
   paint.setAntiAlias(true);

   paint.setColor(Color.WHITE);
   paint.setTextSize(20);
   
   String text = " 親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。";
   int textLength = text.length();
   System.out.println( text.length() );
   
   //必要な行数
   int line = textLength / textCount ;//1
   int linePlus = textLength % textCount;
   System.out.println( line + "::" + linePlus );
   
   int low = height / textCount;//固定値 20 文字の高さ
   int w = low ;//上からの位置
   int moveText = 0;
   for ( int j = 1 ; j < 3 ; j++ ){
    for (int i = 0 ; i < 40 ; i++ ) {
     String moji = String.valueOf(text.charAt( moveText ));
     canvas.drawText( moji , width-20*j, w, paint);
     moveText += 1;
     w = w + low;
    }
     w = low ;
   }

  }
 }
 
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  // ステータスバー削除    
  getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 
  
  // タイトルバーの削除    
  requestWindowFeature(Window.FEATURE_NO_TITLE);
  
  View drawView = new CustomView(this);
  setContentView(drawView);
 }
}


Androidで縦書き3:文字列を使う



import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

public class TategakiActivity extends Activity {

 public class CustomView extends View {
  public CustomView(Context context) {
   super(context);
   setFocusable(true);
  }

  protected void onDraw(Canvas canvas) {
   super.onDraw(canvas);
   //キャンバスサイズの取得
   int height = canvas.getHeight();// 800ピクセル
   int width = canvas.getWidth();// 480ピクセル

   Paint paint = new Paint();
   paint.setAntiAlias(true);

   paint.setColor(Color.WHITE);
   paint.setTextSize(20);
   
   String text = "おはよう";
   
   int low = height / 40;//固定値 20
   int w = low ;
   for (int i = 0; i < text.length() ; i++ ) {
    String moji = String.valueOf(text.charAt( i ));
    canvas.drawText( moji , width-20, w, paint);
    w = w + low;
   }
  }
 }
 
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  // ステータスバー削除    
  getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 
  
  // タイトルバーの削除    
  requestWindowFeature(Window.FEATURE_NO_TITLE);
  
  View drawView = new CustomView(this);
  setContentView(drawView);
 }
}

Androidで縦書き2:縦に40字表示する。


Canvasの幅と高さを取得して、縦位置で表示

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

public class TategakiActivity extends Activity {

 public class CustomView extends View {
  public CustomView(Context context) {
   super(context);
   setFocusable(true);
  }

  protected void onDraw(Canvas canvas) {
   super.onDraw(canvas);
   //キャンバスサイズの取得
   int height = canvas.getHeight();// 800ピクセル
   int width = canvas.getWidth();// 480ピクセル

   Paint paint = new Paint();
   paint.setAntiAlias(true);

   paint.setColor(Color.WHITE);
   paint.setTextSize(20);

   int low = height / 40;//20
   for (int i = low; i <= height; i += low) {
    canvas.drawText("お", width-20, i, paint);
   }
  }
 }
 
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  // ステータスバー削除    
  getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 
  
  // タイトルバーの削除    
  requestWindowFeature(Window.FEATURE_NO_TITLE);
  
  View drawView = new CustomView(this);
  setContentView(drawView);
 }
}


Androidで縦書き1:onDrawでCanvasに1文字表示


とりあえず一文字表示
drawTextで指定している座標は文字の左下。

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

public class TategakiActivity extends Activity {

 public class CustomView extends View {
  public CustomView(Context context) {
   super(context);
   setFocusable(true);
  }

  protected void onDraw(Canvas canvas) {
   super.onDraw(canvas);

   Paint paint = new Paint();
   paint.setAntiAlias(true);

   paint.setColor(Color.WHITE);
   paint.setTextSize(40);

   canvas.drawText("お", 40, 40, paint);
  }
 }
 
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  // ステータスバー削除    
  getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 
  
  // タイトルバーの削除    
  requestWindowFeature(Window.FEATURE_NO_TITLE);
  
  View drawView = new CustomView(this);
  setContentView(drawView);
 }
}

2012年6月12日火曜日

AndroidでDTMF信号:ToneGenerator


import android.app.Activity;
import android.media.ToneGenerator;
import android.os.Bundle;
import android.view.View;

public class ToneGeneratorTestActivity extends Activity {
 private ToneGenerator toneGenerator;

 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  // ToneGenerator初期化
  toneGenerator = new ToneGenerator(android.media.AudioManager.STREAM_DTMF,ToneGenerator.MAX_VOLUME);

 }

 protected void onStop() {
  super.onStop();
  toneGenerator.release();
 }

//ボタンが押されたときの処理
 public void ButtonClick(View v) {
  switch (v.getId()) {
  case R.id.Button01:
   toneGenerator.startTone(ToneGenerator.TONE_DTMF_1, 200);// 再生時間200ミリ秒(35-1500)
   break;
  case R.id.Button02:
   toneGenerator.startTone(ToneGenerator.TONE_DTMF_2, 200);
   break;
  case R.id.Button03:
   toneGenerator.startTone(ToneGenerator.TONE_DTMF_3, 200);
   break;
  case R.id.Button04:
   toneGenerator.startTone(ToneGenerator.TONE_DTMF_4, 200);
   break;
  case R.id.Button05:
   toneGenerator.startTone(ToneGenerator.TONE_DTMF_5, 200);
   break;
  case R.id.Button06:
   toneGenerator.startTone(ToneGenerator.TONE_DTMF_6, 200);
   break;
  case R.id.Button07:
   toneGenerator.startTone(ToneGenerator.TONE_DTMF_7, 200);
   break;
  case R.id.Button08:
   toneGenerator.startTone(ToneGenerator.TONE_DTMF_8, 200);
   break;
  case R.id.Button09:
   toneGenerator.startTone(ToneGenerator.TONE_DTMF_9, 200);
   break;
  case R.id.Button00:
   toneGenerator.startTone(ToneGenerator.TONE_DTMF_0, 200);
   break;
  case R.id.Button0A:
   toneGenerator.startTone(ToneGenerator.TONE_DTMF_A, 200);
   break;
  case R.id.Button0S:
   toneGenerator.startTone(ToneGenerator.TONE_DTMF_S, 200);
   break;
  case R.id.ButtonFinish:
   finish();
  }

 }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >


    <TableLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >


        <TableRow
            android:id="@+id/TableRow03"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1" >

            <Button
                android:id="@+id/Button01"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="1" android:onClick="ButtonClick"/>

            <Button
                android:id="@+id/Button02"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="2" android:onClick="ButtonClick"/>

            <Button
                android:id="@+id/Button03"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="3" android:onClick="ButtonClick"/>
        </TableRow>


        <TableRow
            android:id="@+id/TableRow02"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1" >

            <Button
                android:id="@+id/Button04"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="4" android:onClick="ButtonClick"/>

            <Button
                android:id="@+id/Button05"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="5" android:onClick="ButtonClick"/>

            <Button
                android:id="@+id/Button06"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="6" android:onClick="ButtonClick"/>
        </TableRow>


        <TableRow
            android:id="@+id/TableRow01"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1" >

            <Button
                android:id="@+id/Button07"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="7" android:onClick="ButtonClick"/>

            <Button
                android:id="@+id/Button08"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="8" android:onClick="ButtonClick"/>

            <Button
                android:id="@+id/Button09"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="9" android:onClick="ButtonClick"/>
        </TableRow>


        <TableRow
            android:id="@+id/tableRow1"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1" >

            <Button
                android:id="@+id/Button0A"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="*" android:onClick="ButtonClick"/>

            <Button
                android:id="@+id/Button00"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="0" android:onClick="ButtonClick"/>

            <Button
                android:id="@+id/Button0S"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="#" android:onClick="ButtonClick"/>
        </TableRow>

    </TableLayout>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="終了" android:id="@+id/ButtonFinish" android:onClick="ButtonClick"/>

</LinearLayout>

2012年6月10日日曜日

ListView の使い方-SimpleAdapter


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.SimpleAdapter;

public class AndroidListTestActivity extends Activity {
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  // ListView を取得
  ListView listView = (ListView) findViewById(R.id.listView1);

  List<Map<String, String>> dataList = createData();

  // リストビューに渡すアダプタを生成します。
  SimpleAdapter adapter2 = new SimpleAdapter(
    this, 
    dataList,
    android.R.layout.simple_list_item_2, 
    new String[] { "title","comment" }, 
    new int[] { android.R.id.text1,android.R.id.text2 });

  // アダプタを設定します。
  listView.setAdapter(adapter2);
 }

 private List<Map<String, String>> createData() {
  List<Map<String, String>> retDataList = new ArrayList<Map<String, String>>();

  for (int n = 0; n < 3; n++) {
   Map<String, String> data = new HashMap<String, String>();
   data.put("title", "Item" + n);
   data.put("comment", "subItem" + n);
   retDataList.add(data);
  }

  return retDataList;
 }
}

ListView の使い方-List<> ArrayAdapter

import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class AndroidListTestActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        //ListView を取得
        ListView listView = (ListView) findViewById(R.id.listView1);
        
        List<String> mStrings = new ArrayList<String>();
        // アイテムを追加します
  mStrings.add("Item1");
  mStrings.add("Item2");
  mStrings.add("Item3");
  mStrings.add("Item4");
  

        
        //ListView に表示する項目設定
  ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mStrings);     

        // アダプターを設定します
        listView.setAdapter(adapter);
    }
}

ListView の使い方


import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class AndroidListTestActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        //ListView を取得
        ListView listView = (ListView) findViewById(R.id.listView1);
        
        //ListView に表示する項目設定
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
        // アイテムを追加します
        adapter.add("Item1");
        adapter.add("Item2");
        adapter.add("Item3");
        
        // アダプターを設定します
        listView.setAdapter(adapter);
    }
}

2012年6月9日土曜日

Bluetoothディバイスの調査:MAC Address RSI:Android



import java.util.Set;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.widget.TextView;

public class BluetoothTestActivity extends Activity {
 private BluetoothAdapter myBluetoothAdapter;
 private TextView textView;

 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  textView = (TextView) findViewById(R.id.textView1);

  // Bluetooth
  myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  if (myBluetoothAdapter == null) {
   textView.append("Bluetoothをサポートしていません。\n");
  } else {
   textView.append("Bluetoothをサポートしています。\n");
   //Bluetoothが利用できるか確認する
   if (myBluetoothAdapter.isEnabled()) {
    textView.append("Bluetoothを利用できます。\n");
    //自機ディバイスの調査
    getLocalInformation();
    //ペアリング済みのディバイスの調査
    findPairedDevices();
    //ディバイスを見つけて調査
    discoverDevices();
   }else{
    textView.append("Bluetoothを利用できません。\n");
    //Bluetoothを使えるようにする処理を書いたりする。
   }
  }
 }

// 自機ディバイスの調査メソッド

 private void getLocalInformation() {
  // TODO 自動生成されたメソッド・スタブ
  textView.append("自機Bluetoothディバイスの調査\n");
  textView.append("ディバイス名:" + myBluetoothAdapter.getName() + "\n");
  textView.append("アドレス:" + myBluetoothAdapter.getAddress() + "\n");
  
  textView.append("SCAN_MODE:");
  switch (myBluetoothAdapter.getScanMode()) {
  case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
   textView.append("SCAN_MODE_CONNECTABLE" + "\n");
   break;
  case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
   textView.append("SCAN_MODE_CONNECTABLE_DISCOVERABLE" + "\n");
   break;
  case BluetoothAdapter.SCAN_MODE_NONE:
   textView.append("SCAN_MODE_NONE" + "\n");
   break;
  }
  
  textView.append("STATE:");
  switch (myBluetoothAdapter.getState()) {
  case BluetoothAdapter.STATE_OFF:
   textView.append("STATE_OFF\n");
   break;
  case BluetoothAdapter.STATE_ON:
   textView.append("STATE_ON\n");
   break;
  case BluetoothAdapter.STATE_TURNING_OFF:
   textView.append("STATE_TURNING_OFF\n");
   break;
  case BluetoothAdapter.STATE_TURNING_ON:
   textView.append("STATE_TURNING_ON\n");
   break;
  }
 }

// ペアリング済みの調査
 private void findPairedDevices() {
  textView.append("\n登録済みディバイス\n");

 Set<BluetoothDevice> pairedDevices = myBluetoothAdapter.getBondedDevices();
  if (pairedDevices.size() > 0) {
   for (BluetoothDevice device : pairedDevices) {
    textView.append("ディバイス名:" + device.getName() + "\n");
    textView.append("アドレス:" + device.getAddress() + "\n");
    textView.append("クラス:" + device.getBluetoothClass() + "\n");
   }
  } else {
   textView.append("登録されているBluetoothデバイスはありません。\n");
  }
 }
 
// 他のBluetoothディバイスを見つけるレシーバーを登録

 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
     public void onReceive(Context context, Intent intent) {
         String action = intent.getAction();
         // When discovery finds a device
         if (BluetoothDevice.ACTION_FOUND.equals(action)) {
             // Get the BluetoothDevice object from the Intent
             BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
             textView.append("ディバイス名: " + device.getName() + "\n");
             textView.append("アドレス: " + device.getAddress() + "\n");
             short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,Short.MIN_VALUE);
             textView.append("RSSI: " + rssi + "dBm" + "\n");
         }
     }
 };
 

// ディバイスを見つける
 private void discoverDevices() {
  // TODO 自動生成されたメソッド・スタブ

  IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
  registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
  
  myBluetoothAdapter.startDiscovery();
  textView.append("\nディバイスを検索中\n");
 }
}

マニフェストファイルに追加
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

ディバイスを見つけるのに意外と時間が掛かる時がある
下記のような解説があった。
発見の処理は通常約 12 秒間の問い合わせスキャンを呼び出し、その後に見つかった各デバイスの Bluetooth 名を取得するためのページスキャンが続きます。

検索対象のBlutooth ディバイスは、他のディバイスに情報を表示するように設定しておく必要があるかも。

ディバイスの検索では、ペアリング済みのディバイスだけでなく、検索可能なディバイスが検索される。全然知らない他人のディバイスも表示される。

2012年6月8日金曜日

Wifi情報取得:SSID,IP Adrress,MAC Address,RSSI


package com.xxx;

import android.app.Activity;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class WifiTestActivity extends Activity {
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  WifiManager manager = (WifiManager) getSystemService(WIFI_SERVICE);
  WifiInfo info = manager.getConnectionInfo();
  String[] apInfo = new String[4];
  // SSIDを取得
  apInfo[0] = String.format("SSID : %s", info.getSSID());
  // IPアドレスを取得
  int ipAdr = info.getIpAddress();
  apInfo[1] = String.format("IP Adrress : %02d.%02d.%02d.%02d",
    (ipAdr >> 0) & 0xff, (ipAdr >> 8) & 0xff, (ipAdr >> 16) & 0xff,
    (ipAdr >> 24) & 0xff);
  // MACアドレスを取得
  apInfo[2] = String.format("MAC Address : %s", info.getMacAddress());
  // 受信信号強度&信号レベルを取得
  int rssi = info.getRssi();
  int level = WifiManager.calculateSignalLevel(rssi, 5);
  apInfo[3] = String.format("RSSI : %d / Level : %d/4", rssi, level);

  ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, apInfo);

  ListView listView = (ListView) findViewById(R.id.listView1);

  listView.setAdapter(adapter);

 }
}

マニフェストファイルに追加
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

2012年6月4日月曜日

サーバソケット

サーバ側プログラム

import java.io.*;
import java.net.*;

public class echoServer {
    public static void main(String args[]) {
        // ソケットや入出力用のストリームの宣言
        ServerSocket echoServer = null;
        Socket clientSocket = null;
        
        String line;
        BufferedReader is;
        PrintStream os;
        
        // ポート9999番を開く
        try {
         //待ち受けポートを指定して新しいサーバソケットを生成しています。
            echoServer = new ServerSocket(9999);
            System.out.println("EchoServerが起動しました(port=" + echoServer.getLocalPort() + ")");
            
            //acceptメソッドを呼び出し、クライアントからの接続待機状態に入ります。クライアントからの接続要求があると、socketにはクライアントとの通信に利用できるSocketのインスタンスが代入されます。
            clientSocket = echoServer.accept();
            System.out.println("接続されました "+ clientSocket.getRemoteSocketAddress() );
            
            is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
            os = new PrintStream(clientSocket.getOutputStream());

            // クライアントからのメッセージを待ち、受け取ったメッセージをそのまま返す
            while ( (line = is.readLine()) != null ) {
                System.out.println("受信: " + line);
                os.println(line);
                System.out.println("送信: " + line);
              }
        }
        catch (IOException e) {
            System.out.println(e);
        }
        
    }
}

クライアント側プログラム

import java.io.*;
import java.net.*;

public class echoClient {
    public static void main(String[] args) {
        // ソケットや入出力用のストリームの宣言
        Socket echoSocket = null;
        DataOutputStream os = null;
        BufferedReader is = null;

        // ポート9999番を開く
        try {
            echoSocket = new Socket("localhost", 9999);
            os = new DataOutputStream(echoSocket.getOutputStream());
            is = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
        } catch (UnknownHostException e) {
            System.err.println("Don't know about host: localhost");
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for the connection to: localhost");
        }

        // サーバーにメッセージを送る
        if (echoSocket != null && os != null && is != null) {
            try {
                // メッセージを送ります
                os.writeBytes("HELLO\n");

                // サーバーからのメッセージを受け取り画面に表示します
                String responseLine;
                if ((responseLine = is.readLine()) != null) {
                    System.out.println("Server: " + responseLine);
                }

                // 開いたソケットなどをクローズ
                os.close();
                is.close();
                echoSocket.close();
            } catch (UnknownHostException e) {
                System.err.println("Trying to connect to unknown host: " + e);
            } catch (IOException e) {
                System.err.println("IOException: " + e);
            }
        }
    }
}

Bluetooth:参考サイト

RXTX:送受信プログラムサンプル

パソコン側のプログラム作成:受信

パソコンにシリアル通信で文字を送るプログラムの作成

アプリのBlutooyhSPPを起動させて、Command Line を選択して、文字を送る。


おはよう、と入力して送信

うまく送られているようだ。

import java.io.*;
import java.util.TooManyListenersException;

import gnu.io.*;

public class SerialTestClass {

 public static void main(String arg[]) {

  try {

   // 使用するCOMポートを取得
   CommPortIdentifier comID = CommPortIdentifier.getPortIdentifier("COM3");

   // COMポートを開きます
   CommPort commPort = comID.open("SerialTest", 2000);

   if (commPort instanceof SerialPort ) {
    
   }
   // シリアルポートのインスタンスを生成…
   SerialPort port = (SerialPort) commPort;

   // シリアルポートの設定
   // ボーレート、データビット数、ストップビット数、パリティを設定
   port.setSerialPortParams(9600, SerialPort.DATABITS_8,SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

   // フロー制御はしない
   port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);

   // ストリームを生成して、1文字ずつ送信していきます
   //OutputStream out = port.getOutputStream();
   InputStream in = port.getInputStream();
   
   try {
    //port.addEventListener(new SerialReader(in));
    //port.notifyOnDataAvailable(true);
    
    // イベントリスナー登録
    port.addEventListener( new SerialReader(in) );
    port.notifyOnDataAvailable(true);
    
   } catch (TooManyListenersException e) {
    // TODO 自動生成された catch ブロック
    e.printStackTrace();
   }
   
            
   // ストリームとCOMポートを閉じる処理
   //閉じたら待受状態にならないで終了する
   //in.close();
   //port.close();

  } catch (NoSuchPortException e) {
   // TODO 自動生成された catch ブロック
   e.printStackTrace();
  } catch (PortInUseException e) {
   // TODO 自動生成された catch ブロック
   e.printStackTrace();
  } catch (UnsupportedCommOperationException e) {
   // TODO 自動生成された catch ブロック
   e.printStackTrace();
  } catch (IOException e) {
   // TODO 自動生成された catch ブロック
   e.printStackTrace();
  }
 }
 
 public static class SerialReader implements SerialPortEventListener {

  private InputStream in;
  private byte[] buffer = new byte[1024];

  public SerialReader(InputStream in) {
   // TODO 自動生成されたコンストラクター・スタブ
   this.in = in;
  }

  @Override
  public void serialEvent(SerialPortEvent arg0) {
   int data;

   try {
    int len = 0;
    while ((data = in.read()) > -1) {
     if (data == '\n') {
      break;
     }
     buffer[len++] = (byte) data;
    }
    System.out.print(new String(buffer, 0, len));
   } catch (IOException e) {
    e.printStackTrace();
    System.exit(-1);
   }
  }
 }
}

2012年6月3日日曜日

パソコン側のプログラム作成:送信:Bluetooth SPP

Bluetooth でシリアル通信するためのでパソコン側のプログラムを作成しようと思う。
Javaで作るかVC++で作るか迷うところです。
Android アプリもjava で作るので今回はJavaを選択した。

java でシリアル通信プログラムを作るには、RXTX というライブラリが必要。
RXTX のダウンルードサイト
JavaDocs

ダウンロードしたファイル名:rxtx-2.1-7-bins-r2.zip
ダウンロードしたファイルを解凍する。
eclipseの設定
RXTXcomm.jar はライブラリに追加する。
解答したフォルダの中のWindowsフォルダの中のi368-mingw32フォルダの
rxtxParallel.dll rxtxSerial.dll の2つのファイルをプロジェクトのルートにフォルダにコピーしておく。

Tera Taram で通信が成功したので、シリアルポートの設定を確認しておく
シリアル通信(SPP)の接続確認:Android Bluetooth
ポート:COM3
ボー・レート:9600
データ:8bit
パリティー:none
ストップ:1 bit
フロー制御:none

送信遅延
0ミリ秒/字 0ミリ秒/行

アンドロイド端末にシリアル通信で文字を送るプログラムを書いてみる。
import java.io.*;

import gnu.io.*;

public class SerialTestClass {
 public static void main(String arg[]) {

  try {

   // 使用するCOMポートを取得
   CommPortIdentifier comID = CommPortIdentifier.getPortIdentifier("COM3");

   // COMポートを開きます
   CommPort commPort = comID.open("SerialTestClass", 2000);

   // シリアルポートのインスタンスを生成…
   SerialPort port = (SerialPort) commPort;

   // シリアルポートの設定
   // ボーレート、データビット数、ストップビット数、パリティを設定
   port.setSerialPortParams(9600, SerialPort.DATABITS_8,SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

   // フロー制御はしない
   port.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);

   // ストリームを生成して、1文字ずつ送信していきます
   OutputStream out = port.getOutputStream();
   out.write('r');
   out.write('i');
   out.write('g');
   out.write('h');
   out.write('t');
   out.write('\r');
   out.write('\n');

   // ストリームとCOMポートを閉じる処理
   out.close();
   port.close();

  } catch (NoSuchPortException e) {
   // TODO 自動生成された catch ブロック
   e.printStackTrace();
  } catch (PortInUseException e) {
   // TODO 自動生成された catch ブロック
   e.printStackTrace();
  } catch (UnsupportedCommOperationException e) {
   // TODO 自動生成された catch ブロック
   e.printStackTrace();
  } catch (IOException e) {
   // TODO 自動生成された catch ブロック
   e.printStackTrace();
  }

 }
}

アンドロイド側で受信するためにBlutooyhSPPを起動させる。
受信するために一番上の
Real-time mode を選択する。


作成したプログラムを実行する。
うまく送られているようだ。


シリアル通信(SPP)の接続確認:Android Bluetooth

PC側の準備:
Tera Term VT をダウンロードして起動させる。


Android側の準備:
Google play からアプリダウンロードしてインストールする。
アプリ名:BlutooyhSPP(無料)

アプリを起動させる。
Connect ボタンを押す。

Command Line をクリックする。

char:(\r\n) をクリックする。


Android端末で、おはよう と入力する。

パソコンに文字が送られる。

参考:
なぜか、Bluetooth Chat では接続できなかった。

準備・接続確認:Android Bluetooth

使用Bluetoothアダプタ:BUFFALO BSHSBD04BK

ペアリングする。
アンドロイド端末から接続要求すると、PC側でも接続するか聞いてくるので接続する。


シリアルポートの設定をする。

ネットワークアダプタを設定する。(シリアル通信に必要かどうかよくわからないけと一応入れておく)
接続をクリックしたらドライバがインストールされる。