2016年6月22日水曜日

JARファイルに画像を入れる

目次へ



画像をプロジェクト内に保存し、JARファイルにすると画像が表示されません。 いろいろ試して、うまくいったので忘れないように書いておきます。
  • リソースフォルダの作成
  • クラスローダからリソースを取得
  • ECLIPSEの実行構成の設定
  • JARファイルの作成


■■■■リソースフォルダの作成

プロジェクトのフォルダの下にimageというフォルダを作成し、その中に画像ファイルを入れます。 ECLIPSEのパッケージエクスプローラで見ると下のようになります。




■■■■クラスローダからリソースを取得

クラスローダを使って画像を取り入れているのが下のプログラムです。
public class ImageLabel01 extends JFrame {

 JLabel label = new JLabel();

 public ImageLabel01() {
  Image im=null;
  URL url=this.getClass().getClassLoader().
     getResource("image/stream.jpg");
  try {
   im=this.createImage((ImageProducer)url.getContent());
   label.setIcon(new ImageIcon(im));
  }catch(Exception ex){ }

  //ラベルをフレームに乗せフレームを表示
  getContentPane().add(label, BorderLayout.CENTER);
  this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  this.setSize(350, 250);
  this.setVisible(true);
}
 public static void main(String[] args) {
  new ImageLabel01();
 }
}



■■■■ECLIPSEの実行構成の設定■■■■

メニューの[実行]から[実行構成]を選び、次のように設定をします。
[クラスパスのタブ]-[ユーザエントリをクリック]-[拡張ボタンを押す]
-[フォルダの追加にチェックを入れOK]
-[追加するフォルダとしてプロジェクトフォルダを選択しOK]
-[ユーザエントリにプロジェクト名-¥ が追加されていればOK(下の画像)]

これで、実行構成の設定が終わったのでこれで実行すればECLIPSE上で実行する分にはがぞうが表示されるはずです。

ユーザエントリにプロジェクト名-¥ が追加された様子



■■■■JARファイルの作成■■■■

あとは、次のように普通にJARファイルを作成すれば、JARファイルを実行したときにも画像が表示されるはずです。

[プロジェクトで右クリックしエクスポート]
-[Javaの中のJARファイルをクリックし次へボタン]
-[JARにしたいプロジェクトにチェックが入っていることを確認]
-[作成するJARファイルの出力先と名前を指定し次へボタン]
-[次の画面は何もせず次へ]
-[メインメソッドのあるクラスを指定し完了]


これでJARファイルができたらそれをダブルクリックすればちゃんと画像が出ます。


にほんブログ村 IT技術ブログ IT技術メモへ
にほんブログ村

2016年4月4日月曜日

AndroidでMediaRecorder、MediaPlayerを使う

目次へ



声を録音したら、すぐにその声で返事をしてくれるアプリを作りたかったので、 まずは、録音と再生のしかたを、忘れないようにまとめておきます。
今後、これを変更して、「こんにちは」というと、ちょっと違う声で「こんにちは」と 同じ言葉をしゃべってくれるアプリをつくりたいのですが、まだ、いろいろわからないことだらけです。


■■■■音声の録音と再生■■■■

録音はMediaRecorder、再生はMediaPlayerを使います。
下のような画面が表示され、開始ボタンで録音開始、終了ボタンで録音終了、再生ボタンで今録音したものが再生されます。




import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.view.View;
import android.widget.TextView;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {
    private boolean isRecording = false;
    private TextView text;
    private MediaRecorder recorder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

 //textは説明を表示しているTextViewです
        text = (TextView) findViewById(R.id.text1);
    }
    //-------- 開始ボタンを押したときの処理
    public void onStart(View view) {
        if (isRecording) return;

        //-------- 保存先 「内部ストレージ\test.3gp」ができる
        String path = Environment.getExternalStorageDirectory() + "/test.3gp";

        //-------- Recorder作成
        recorder = new MediaRecorder();
        //-------- オーディオソースをマイクとする
        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        //-------- ファイルのフォーマットを3GPPとする
        recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        //-------- エンコーダをデフォルトとする
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
        //-------- 出力先ファイル名指定
        recorder.setOutputFile(path);

        //-------- レコーディング
        try {
        //-------- 録音開始するには prepare,startを呼び出す
            recorder.prepare();
            recorder.start();
            isRecording = true;
            text.setText("isRecording");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //-------- 終了ボタンを押したときの処理
    public void onStop(View view) {
        if (!isRecording) {
            text.setText("録音中ではありません");
            return;
        }
        //-------- 終了には stop,reset,releaseを呼び出す
        recorder.stop();
        recorder.reset();
        recorder.release();
        isRecording = false;
        text.setText("録音終了");
    }
    //-------- 再生ボタンを押したときの処理
    public void onPlay(View view) {
        VoicePlayer player = new VoicePlayer();
        player.play();
    }
}





import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Environment;
import android.widget.TextView;
import java.io.IOException;

public class VoicePlayer implements MediaPlayer.OnCompletionListener {
    private MediaPlayer player = new MediaPlayer();
    private String path;

    public VoicePlayer() {
        //-------- 再生が終わった時のリスナを設定
        player.setOnCompletionListener(this);
        //-------- 再生ボリューム 左、右を0.0f~1.0fで設定
        player.setVolume(1.0f, 1.0f);
        path = Environment.getExternalStorageDirectory() + "/test.3gp";
    }

    //-------- 再生
    public void play() {
        try {
            player.setDataSource(path);
            //-------- 再生するには、prepare、startを呼び出す
            player.prepare();
            player.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //-------- 再生が終わった時に呼び出される
    public void onCompletion(MediaPlayer mp) {
        //-------- 終了したら、stop、releaseを呼び出す
        player.stop();
        player.release();
    }
}




にほんブログ村 IT技術ブログ IT技術メモへ
にほんブログ村

2016年3月21日月曜日

Androidのセンサーを使う

目次へ



Androidでは、いろいろなセンサーを使うことができますが、使い方が統一されているため、一つのセンサーの使い方を覚えれば別のセンサーも同じように使えます。
メインの画面が表示されている間センサーからデータを受け取るというつもりで次のようなステップを考えました。

メイン画面のonCreateで
 1.センサーマネージャ取得
 2.センサー取得
 3.リスナインスタンス作成

メイン画面のonResumeで
 4.センサーのリスナを登録する

メイン画面のonPauseで
 5.リスナの登録を解除する


■■■■センサーマネージャ取得■■■■

センサーを使うには、SensorManagerオブジェクトが必要です。
SensorManager sm;
sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);



■■■■センサー取得■■■■

上で作成したSensorManagerオブジェクトを使って必要なセンサーを取得します。
デフォルトの加速度センサーを取り出すなら
Sensor accele;
accele = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

そのタイプのすべてのセンサーを取り出すなら
Listlist;
list = sm.getSensorList(Sensor.TYPE_ACCELEROMETER);


センサータイプの定数
TYPE_ALL 全てのセンサー
TYPE_ACCELEROMETER 加速度センサー
TYPE_GRAVITY 重力センサー
TYPE_GYROSCOPE ジャイロセンサー
TYPE_LIGHT 光センサー
TYPE_LINEAR_ACCELERATION 単方向加速センサー
TYPE_MAGNETIC_FIELD 地磁気センサー
TYPE_PRESSURE 圧力センサー
TYPE_PROXIMITY 近接センサー
TYPE_ROTATION_VECTOR 回転ベクトルセンサー



■■■■リスナ作成■■■■

次にセンサーのリスナを作ります。
Activity自体をimplements SensorEventListenerとすれば簡単です。
class Xx implements SensorEventListener {
    //センサ精度が変更された時呼ばれる
    public void onAccuracyChanged(Sensor sensor, int accuracy) { }

    //センサ値が変更された時呼ばれる
    public void onSensorChanged(SensorEvent event) {
        event.values[0]~[2]にセンサーの値が格納されているので
        この値を使ってプログラムを書きます
    }
}



■■■■リスナ登録■■■■

メインのActivityが表示された時にセンサーからの値を使うのなら、onResumeメソッドで次のように、リスナを登録すればよいでしょう。
smはSensorManager、acceleはSensorです。
また、第3引数はイベントの発生間隔で次のような値が指定できます。
SENSOR_DELAY_FASTEST 最も短い間隔
SENSOR_DELAY_GAME ゲームに最適。FASTESTの次に短い間隔
SENSOR_DELAY_UI user interfaceに最適。GAMEの次に短い間隔
SENSOR_DELAY_NORMAL スクリーン方向の変化などに最適。最もゆっくり
数字 ミリ秒単位で自分で設定


sm.registerListener(リスナ,accele, SensorManager.SENSOR_DELAY_NORMAL); 



■■■■リスナ登録解除■■■■

メインのActivityが隠れた時に解除するなら、onPauseメソッドで次のように登録を解除すればよいと思います。
smはSensorManagerです。
sm.unregisterListener(リスナ);






にほんブログ村 IT技術ブログ IT技術メモへ
にほんブログ村

2016年3月15日火曜日

Androidで音声認識

目次へ



Androidでは、日本語の音声認識を、簡単に使うことができます。
Intentを使い音声認識のためのActivityを起動し、認識された文字列を元のActivityで受け取るのですが、自分で書くのは、ほんの少しです。


■■■■音声認識■■■■

下のプログラムでは「開始」と書いたボタンを押すと、 RecognizerIntent.ACTION_RECOGNIZE_SPEECHを指定して、Intentのインスタンスを作成します。
このオブジェクトにputExtraメソッドを使って、いくつか情報を追加し、startActivityForResultメソッドを使って音声認識用Acyivityを起動します。
マイクの画面(これが音声認識用Activity)が表示され、話した内容を認識すると、元の画面に戻り、認識した内容をTextViewに表示します。
現在「Hello World」と表示している場所がTextViewです。

  

音声認識のActivityを表示するための部分が下のプログラムの(1)から(6)です
認識された文字列を使っているのが、(7)から
  1. まず音声認識用のActivityを指定しIntentのインスタンスを作ります。

  2. RecognizerIntent.EXTRA_LANGUAGE_MODELでは、
    RecognizerIntent.LANGUAGE_MODEL_FREE_FORM
    RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH
    のどちらかを指定しますが、LANGUAGE_MODEL_WEB_SEARCHは、Web検索の際に使います。

  3. RecognizerIntent.EXTRA_PROMPTで指定するのは、マイクの上に表示される文字列です。

  4. EXTRA_MAX_RESULTSは、認識した候補のうち、最大いくつ返すかを指定します。
    これを1にして、どうぞといった場合「どうぞ」という文字列がひとつ返ってきましたが、
    これを指定しなかった場合には「どうぞドウゾzozodmsoどうゾ」という文字列が返ってきました。

  5. Activityを起動します。
    この時リクエストコードとして、適当な数字を渡すと、戻り値を受け取る場合に、このリクエストコードで起動したActivityからの戻り値であるかを確認できます。

  6. エミュレータで実行した場合には、音声認識機能が無いため、catchが必要です。


  7. onActivityResultは(5)のstartActivityForResultでスタートしたActivityが終了した時に呼び出されるメソッドです。

  8. (5)で自分が発行したIntentであるか判断するのが、REQUEST_CODEのチェックです。

  9. 音声認識された文字列の候補をArrayListとして受け取り、全てを表示しています。
    もし、(4)で指定したように、候補を一つだけ受け取るようにしているのなら、for文など使わずに、results.get(0)を表示するだけです。





import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;

public class MainActivity extends Activity implements View.OnClickListener {

    private static final int REQUEST_CODE = 100;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button1 = (Button)findViewById(R.id.button1);
        button1.setOnClickListener(this);
    }

    //button1をタップすると音声認識を行うActivityを起動する
    public void onClick(View v) {
        try {
            //--- (1)
            Intent intent = new Intent
                           (RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
            //--- (2)
            intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, 
                            RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
            //--- (3)
            intent.putExtra(RecognizerIntent.EXTRA_PROMPT, 
                              "どうぞお話しください");
            //--- (4)
            intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
            //--- (5)
            startActivityForResult(intent, REQUEST_CODE);
        //--- (6)
        } catch(ActivityNotFoundException e) {        
            Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
        }
    }


    //--- (7)
    public void onActivityResult(int requestCode,int resultCode,Intent data){
        //--- (8)
        if(requestCode==REQUEST_CODE && resultCode==RESULT_OK) {
            String str = "";

            //--- (9)
            ArrayList results = 
                data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
            for(String s : results) {
                str += s;
            }
            TextView text = (TextView)findViewById(R.id.text1);
            text.setText(str);
        }
    }
}




■■■■音声認識によるWeb検索■■■■

もしも、音声認識後、その文字列ですぐにWeb検索を行う場合には、上のプログラムの(1)(2)を次のようにし、(7)のメソッドは削除します。
これだけで、音声認識後、Web検索へと進みます。



           //--- (1)
            Intent intent = new Intent
                           (RecognizerIntent.ACTION_WEB_SEARCH);
            //--- (2)
            intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, 
                            RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);



にほんブログ村 IT技術ブログ IT技術メモへ
にほんブログ村

2016年2月19日金曜日

Android View部品の背景色や枠線の設定

目次へ



AndroidのいろいろなViewに背景色をつけたり、枠線をつけたりする方法をまとめておきます。
次の2つを設定することで、背景色などを設定することができます。

  • リソースのdrawableで色や枠線を決めたxmlを作成
  • layoutのandroid:backgroundにそのxmlを指定


■■■■layoutのbackgroundの設定■■■■

たとえば、下の画面は、4つのEditTextとボタンを横にならべたものですが、枠線や背景色が異なっています。
枠線や背景色はlayoutのxml内のandroid:backgroundで指定しています。
最初のEditTextだけは、この指定が無いので、一般的な下線だけが引かれたものになっています。
この、android:backgroundで指定しているのは、drawableに保存したxmlファイルのファイル名の拡張子の無いものです。






res/layout/content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="AB" />
    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@drawable/border"
        android:text="AB" />
    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@drawable/border1"
        android:text="AB" />
    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@drawable/gradient"
        android:text="AB" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="ボタン"
        android:id="@+id/buttonEq"
        android:background="@drawable/pink_gradient" />
</LinearLayout>



■■■■drawableのxml■■■■

2番目のEditTextに指定されているres/drawable/border.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <stroke android:width="20px" android:color="#CCCCFF" />
</shape>
ここでは、色と幅を指定した枠線をつけることが指定されています。



3番目のEditTextに指定されているres/drawable/border1.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <stroke android:width="20px" android:color="#CCCCFF" />
    <padding android:left="50px" android:top="2px"
        android:right="2px" android:bottom="2px" />
    <corners android:radius="5dp" />
</shape>
ここでは、枠線内の余白が指定されています。
また、cornersを指定することにより、枠線の角が少し丸くなっています。



4番目のEditTextに指定されているres/drawable/gradient.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
    <gradient
        android:startColor="#FFFFB7"
        android:endColor="#FF9900"
        android:angle="270" />
    <stroke
        android:color="#F95E00"
        android:width="2dp" />
    <corners android:radius="8dp" />
</shape>
ここでは、グラデーションの背景色が指定されています。
startColorからendColorまで徐々に色が変わっていきます。
android:angleは、グラデーションの方向を示します。
0にすると、左から右へのグラデーション。90にすると、下から上へのグラデーションになります。デフォルトは0です。



最後のボタンに指定されているres/drawable/pink_gradient.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient
        android:startColor="#FFAAAA"
        android:endColor="#FFEEEE"
        android:angle="0" />
    <stroke
        android:color="#F95E00"
        android:width="2dp" />
    <corners android:radius="8dp" />
</shape>
これも、背景色がグラデーションで左から右にFFAAAAの色からFFEEEEの色に変化していきます。



■■■■一般的なshape■■■■

Android Developers用の公式ページの shape drawableの説明ではshapeのSYNTAXの説明として以下のように記述されています。
<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape=["rectangle" | "oval" | "line" | "ring"] >
    <corners
        android:radius="integer"
        android:topLeftRadius="integer"
        android:topRightRadius="integer"
        android:bottomLeftRadius="integer"
        android:bottomRightRadius="integer" />
    <gradient
        android:angle="integer"
        android:centerX="integer"
        android:centerY="integer"
        android:centerColor="integer"
        android:endColor="color"
        android:gradientRadius="integer"
        android:startColor="color"
        android:type=["linear" | "radial" | "sweep"]
        android:useLevel=["true" | "false"] />
    <padding
        android:left="integer"
        android:top="integer"
        android:right="integer"
        android:bottom="integer" />
    <size
        android:width="integer"
        android:height="integer" />
    <solid
        android:color="color" />
    <stroke
        android:width="integer"
        android:color="color"
        android:dashWidth="integer"
        android:dashGap="integer" />
</shape>



にほんブログ村 IT技術ブログ IT技術メモへ
にほんブログ村

2016年1月26日火曜日

Androidアプリを実機で実行 USBドライバのインストール

目次へ



Androidアプリを作成したら、実機で動作させたいと思いますよね。
今まで、どうしても家のPCからは、USBケーブルでつなぐことができず、いろいろ苦労しました。
今回初めて、USBケーブルでつなぐことができましたので、忘れないうちに書いておきます。



■■■■実機のADB USBドライバをインストール■■■■

こちらのページこちらのページを 参考にさせていただきました。

まずは、ADB USBドライバをダウンロードします。
私は、AQUOSフォンなので、型番 デバイスドライバ で検索したところ、SHARP共通 ADB USBドライバを 使えばよいようなので、それをダウンロードしました。
zipファイルでしたので、適当なフォルダに展開しました。

コントロールパネルからデバイスマネージャを開き、「ほかのデバイス」の中にある端末名を右クリックし、 ドライバソフトウェアの更新をクリックします。
「コンピュータを参照してドライバソフトウェアを検索します」を選択し、次の画面で、 ダウンロードし展開したフォルダを選択します。
これでドライバがインストールできました。



■■■■実機をPCにUSBケーブルでつなぐ■■■■

次はいよいよ、USBでPCにつなぎます。

まずは、Android端末で、USBデバッグを有効にしておきます。
Android4.2.2の場合、設定の中に、開発者向けオプションという項目がありますので、その中の、USBデバッグにチェックを入れます。
また、その画面の1番上に開発者向けオプションをONにしたり、OFFにしたりできるボタンがありますので、それをONにしておきます。
これで、Android端末の設定は終わりなので、USBケーブルでPCにつなぎます。

その後、Android Studioから、プロジェクトを実行します。
この時、エミュレータは閉じておきます。
実行するとDevice Chooserが表示されますが、なぜかOFFLINEになっています。


やっぱり失敗だったのかと思ったのですが、この時、Android端末側に、USBデバッグを許可しますかというメッセージが出ており、 それを許可すると、OFFLINEではなくなり、めでたく、実機で実行することができました。



にほんブログ村 IT技術ブログ IT技術メモへ
にほんブログ村

2016年1月20日水曜日

Androidで別のActivity(画面)に移動する方法

目次へ



Androidで、あるActivityから別のActivityを開きたい時などには、Intentというクラスを使います。
IntentはOSであるAndroidに対して他のActivityを起動してほしいときに使うオブジェクトで、Activityを起動するための情報を持ちます。

注意
新しいActivityを追加する場合には、マニフェストに登録する必要があります。


  • 新しいActivityを表示するコード
  • マニフェストに登録


■■■■2番目のActivityを呼び出すコード■■■■

ここでは、SecondActivityという名前のActivityクラスが作成されているものとします。

Intentのコンストラクタの1番目の引数が呼び出し元Activityのインスタンスです。
2番目の引数が呼び出すActivityのClassオブジェクトです。
Intentのコンストラクタには、いろいろな引数のあるものがありますが、自分で作成した、 2番目のActivityを表示するためにはこのコンストラクタが使われることが多いようです。
 

   Intent intent = new Intent(this, SecondActivity.class);
   startActivity(intent);




■■■■マニフェストに登録■■■■

新しくActivityを作った時にはそのクラスをマニフェストに登録する必要があります。
追加するのは以下の ------- で囲った部分です。
android:nameで設定しているのが、新しいActivityのクラス名です。
SecondActivityクラスのパッケージは、manifestタグの中のpackageで指定したものと同じなので、.SecondActivityとしています。


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.yoko.intenttest" >

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

 --------------------ここから追加します
        <activity
            android:name=".SecondActivity"
            android:label="@string/app_name">
        </activity>
 -------------------ここまで
    </application>
</manifest>






にほんブログ村 IT技術ブログ IT技術メモへ
にほんブログ村