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技術メモへ
にほんブログ村

2015年12月21日月曜日

GAEのデータストアからの検索、挿入、削除、更新

目次へ



GAEのデータストアにJDOでアクセスし、データの検索、挿入、削除、更新をする方法です。
データストアには、Persistence Managerというオブジェクトを使い、アクセスします。
  • Persistence Managerの取得
  • カインドの定義(RDBのテーブルの定義にあたる)
  • データの挿入
  • JDOQLによる検索
  • データの削除
  • データの更新


■■■■Persistence Managerの取得

JDOによるデータストアからの検索、書き込みにはPersistence Managerというオブジェクトを使います。
Persistence ManagerオブジェクトはPersistence Manager Factoryというファクトリオブジェクトを使って作成します。
下のPMFクラスはPersistence Manager Factoryのインスタンスを1つだけ作成するシングルトンです。
PMFクラス
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;

public final class PMF {
 private static final PersistenceManagerFactory pmfInstance = 
       JDOHelper.getPersistenceManagerFactory("transactions-optional");
 
 private PMF(){}
 public static PersistenceManagerFactory get() {
  return pmfInstance;
 }
}



■■■■カインドの定義

JDOではアノテーション付きのクラスを定義することでカインドを定義します。
下のSyouhinクラスはnameとpriceというプロパティとLong型のキーを持つSyouhinカインドを定義しています。
カインドとはRDBの表だと思ってください

  • @PersistenceCapable このクラスがカインドを定義するためのクラスであることを示します。
  • @PrimaryKey このフィールドがキーであることを示します
  • @Persistent(valueStrategy=IdGeneratorStrategy.IDENTITY) キーを自動で作成することを示します
  • @Persistent このフィールドをデータストアへ書き込むことを示します
Syouhinクラス
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.search.SortExpression.SortDirection;

@PersistenceCapable
public class Syouhin {

 @PrimaryKey
 @Persistent(valueStrategy=IdGeneratorStrategy.IDENTITY)
 private Long key; //自動で作成するキー

 @Persistent
 private String name; //商品名

 @Persistent
 private Integer price; //価格

 //-------------------------------- getter setter
 public Long getKey() {
  return key;
 }
 public void setKey(Long key) {
  this.key = key;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public Integer getPrice() {
  return price;
 }
 public void setPrice(Integer price) {
  this.price = price;
 }



■■■■データの挿入

次のメソッドはsyouhinオブジェクトをデータストアに格納します
格納するメソッド
public boolean insert(Syouhin syouhin) {
 PersistenceManager pm = PMF.get().getPersistenceManager();
 try {
  pm.makePersistent(syouhin);
  return true;
 } catch(Exception e) {
  e.printStackTrace();
  return false;
 } finally {
  pm.close();
 }
}



■■■■JDOQLによる検索

次のメソッドはどちらも、データストアの中のSyouhinカインド内のすべてのエンティティを取得します
Single-String JDOQLによる全検索
public List selectAll() {
 PersistenceManager pm = PMF.get().getPersistenceManager();

 try {
  //------------- Single-String JDOQLによる検索
  Query query = pm.newQuery("SELECT FROM SYOUHIN");
  List list = (List)query.execute();
  return list;
 } catch(Exception e) {
  e.printStackTrace();
  return null;
 } finally {
  pm.close();
 }
}



Declarative JDOQLによる全検索
public List selectAll() {
 PersistenceManager pm = PMF.get().getPersistenceManager();
 
 try {
  //------------- Declarative JDOQLによる検索
  Query query = pm.newQuery(Syouhin.class);
  List list = (List)query.execute();
  return list;
 } catch(Exception e) {
  e.printStackTrace();
  return null;
 } finally {
  pm.close();
 }
}



キーを指定して検索(キー以外でも使える)
public Syouhin selectByKey(long number) {
 PersistenceManager pm = PMF.get().getPersistenceManager();

 try {
  //---キーを作成
  Key key = KeyFactory.createKey(Syouhin.class.getName(), number);

  //---そのキーのデータを取得
  Syouhin syouhin = pm.getObjectById(Syouhin.class, key);

  return syouhin;
 } catch(Exception e) {
  e.printStackTrace();
  return null;
 } finally {
  pm.close();
 }
}



条件を指定して検索(キー以外でも使える)
public List selectByKey(long number) {
 PersistenceManager pm = PMF.get().getPersistenceManager();

 try {
  //------------- とりあえずすべてを選択するクエリー
  Query query = pm.newQuery(QData.class);
 
  //---条件作成 numberというパラメータを指定している
  query.setFilter("key==number");

  //---パラメータnumberの型を指定
  query.declareParameters("long number");

  //---パラメータに実際の値を入れて実行
  List results = (List) query.execute(number);

  return list;
 } catch(Exception e) {
  e.printStackTrace();
  return null;
 } finally {
  pm.close();
 }
}



Single-String JDOQLによる条件検索
public List selectByKey(String name) {
 PersistenceManager pm = PMF.get().getPersistenceManager();

 try {
  //------------- JDOQL作成
  String str = "select from " + Syouhin.class.getName() +
   " WHERE name==" + name + " order by price ASC";
  List list = (List) pm.newQuery(str).execute();

  pm.close();
  return list;
 } catch(Exception e) {
  e.printStackTrace();
  return null;
 } finally {
  pm.close();
 }
}



■■■■データの削除

次のメソッドはすべてのsyouhinオブジェクトをデータストアから削除します
Syouhinカインド内のすべてのエンティティを削除するメソッド
public boolean deleteAll() {
 PersistenceManager pm = PMF.get().getPersistenceManager();
 try {
  Query query = pm.newQuery(Syouhin.class);
  List list = (List)query.execute();
  // いったん取得したものすべてを削除
  pm.deletePersistentAll(list);
  return true;
 } catch (Exception e) {
  e.printStackTrace();
  return false;
 } finally {
  pm.close();
 }
}



選択した1つのSyouhinを削除するメソッド
public boolean deleteByKey(long number) {
 PersistenceManager pm = PMF.get().getPersistenceManager();
 try {
  //---キーを作成
  Key key = KeyFactory.createKey(Syouhin.class.getName(), number);

  //---そのキーのデータを取得
  Syouhin syouhin = pm.getObjectById(Syouhin.class, key);

  // 取得したものを削除
  pm.deletePersistent(syouhin);
  return true;
 } catch (Exception e) {
  e.printStackTrace();
  return false;
 } finally {
  pm.close();
 }
}



■■■■データの更新

更新は、選択したオブジェクトを変更すればよい
public boolean update(Syouhin s) {
 PersistenceManager pm = PMF.get().getPersistenceManager();
 try {
  //---キーを作成しそのキーのデータを取得
  Key key = KeyFactory.createKey(Syouhin.class.getName(), s.getNumber());
  Syouhin syouhin = pm.getObjectById(Syouhin.class, key);
  syouhin.setName(s.getName());
  syouhin.setPrice(s.getPrice());
  return true;
 } catch(Exception e) {
  e.printStackTrace();
  return false;
 } finally {
  pm.close();
 }
}



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

2015年12月7日月曜日

GAEのデータストア上のデータ構造

目次へ

  • データストア上のデータ構造
  • データストアに格納できるデータ型


■■■■データストア上のデータ構造

データストアに格納するデータ構造は次のようになります。


おおざっぱに言うとRDBのテーブルにあたるものがデータストアのカインド。
RDBのレコードにあたるものがエンティティ。
RDBの列項目にあたるものがプロパティになります。

また、各エンティティには、ユニークなキーが必要で、アプリケーションで指定することも、自動で作成することもできます。


■■■■データストアに格納できるデータ型

エンティティの各プロパティには下表のような型の値を格納することができます。
文字列、バイト列に対しては、500バイト未満と500バイト以上の型があります。

対応するJavaクラス
短い文字列(500バイト未満) String
長い文字列(500バイト以上) com.google.appengine.api.datastore.Text
短いバイト列(500バイト未満) com.google.appengine.api.datastore.ShortBlog
長いバイト列(500バイト以上) com.google.appengine.api.datastore.Blob
真偽値 boolean,Boolean
整数値 short,int,long,Short,Integer,Long
浮動小数点数 float,double,Float,Double
日時 java.util.Date
Googleアカウント com.google.appengine.api.users.User
エンティティキー com.google.appengine.api.datastore.Key
カテゴリ com.google.appengine.api.datastore.Category
電子メールアドレス com.google.appengine.api.datastore.Email
位置情報 com.google.appengine.api.datastore.GeoPt
インスタントメッセージのハンドル com.google.appengine.api.datastore.IMHandle
URL com.google.appengine.api.datastore.Link
電話番号 com.google.appengine.api.datastore.PhoneNumber
郵便番号 com.google.appengine.api.datastore.PostalAddress
評価値(1~100の整数値) com.google.appengine.api.datastore.Rating






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

2015年8月31日月曜日

SwingWorker サンプル

目次へ



  • イベントディスパッチスレッドとは
  • SwingWorkerとは
  • SwingWorkerの2つの引数
  • SwingWorkerサンプル


■■■■イベントディスパッチスレッドとは

Swingの描画に関連する処理と、イベントに対する応答処理(たとえばJButtonが押された時に呼び出されるactionPerformed等は イベントディスパッチスレッドと呼ばれる一つのスレッドで実行されます。
そのため、たとえば、ボタンを押すと画像を表示しているJLabelが300msecおきに5ピクセルづつ10回動くようにしたくて(ゆっくり進めたい)、 下のようなプログラムを作ったとすると、うまくいきません。
このプログラムを実行し、ボタンを押すと、300×10msecの間、画像は何も動かず、3000msec後にいきなり、5×10ピクセル移動してしまうことになります。

これはactionPerformedと、label.setBoundsを実行することによる描画処理が1つのスレッドで行われるためです。


なぜこうなるのでしょう
ボタンを押すと、①のactionPerformedがイベントディスパッチスレッド上で実行開始します。
1回目のループで②が実行されると、描画処理はイベントディスパッチスレッド上で行われなければいけないのですが、 イベントディスパッチスレッド上ではactionPerformedを実行中のため、これが終了したら実行できるように、 イベントキューにこの処理をならべます。
イベントキューとは、複数のイベントが発生した時に同時にその処理を実行できないため、それらのイベントを並べておく待ち行列です。
イベントディスパッチスレッドは、イベントキューに並んでいる処理を順番に実行していくことになります。

actionPerformedはイベントキューに描画処理を並べた後、300msecのスリープに入ります。
actionPerformedが終了するまでイベントキューに並んでいる処理は実行できませんから、まだ、描画処理は実行されず、待ち続けます。
2回目のループでも同じで、②の位置まで来ると、ひとつ前の②の処理がまだ実行されずにイベントキューで待っていますが、 その後ろに、②の処理を並べ、スリープします。
こうして、10回のループがやっと終了すると、イベントキューに並んでいる10個の処理が順番に実行されます。
10個の処理はスリープもなく、すぐに実行できますから、人間の目には1ぺんに、最初の位置から、最後の位置まで動いたように見えます。


うまくいかないプログラム
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class SwingworkerNasiTest extends JFrame {
 private static int WIDTH = 29; //画像幅
 private static int HEIGHT = 41; //画像高さ

 JButton btnWalk = new JButton("歩く");
 JLabel  label   = new JLabel(new ImageIcon("./penguin.gif"));
 JPanel  panel = new JPanel();
 JPanel  contentPane = (JPanel)getContentPane();

 int labelX = 0;   //ラベルの位置x
 int  labelY = 0;   //ラベルの位置y

 public SwingworkerNasiTest() {
  //--------------------------- パネルとボタンを置く
  contentPane.add(panel,BorderLayout.CENTER);
  contentPane.add(btnWalk,BorderLayout.SOUTH);

  //---------------------------画面の設定
  this.setSize(500,300);
  this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  this.setVisible(true);

  //----------------- パネルの右下にペンギンの乗ったラベルを置く
  panel.setLayout(null);
  labelX = panel.getWidth()-WIDTH;
  labelY = panel.getHeight()-HEIGHT;
  label.setBounds(labelX, labelY, WIDTH, HEIGHT);
  panel.add(label);

  //--------------------------- ボタンの処理
  btnWalk.addActionListener(new ActionListener(){
   public void actionPerformed(ActionEvent e) {   //①
    for(int i=0; i<10; i++) {
     labelX -= 5;
     label.setBounds(labelY, labelY, WIDTH, HEIGHT); //②
     try {
      Thread.sleep(300);
     } catch (InterruptedException e1) {}
    }
   }
  });
 }
 public static void main(String[] args) {
  new SwingworkerNasiTest();
 }
}



■■■■SwingWorkerとは

SwingWorkerクラスはイベントディスパッチスレッドと別スレッドで処理をしたいときに使います。
たとえば、イベントディスパッチスレッド上で実行されるactionPerformedの中で長~い処理を書いた場合、 その間、描画処理などができなくなってしまいます。
その長い処理は別スレッドで行えればよいわけです。
別スレッドで行う処理はSwingWorkerを継承したクラスのdoInBackgroundに記述し、actionPerformedの中でこのクラスのインスタンスを作成し、 実行を開始します。

これだけなら、普通のスレッドと同じ気もしますが、SwingWorkerの場合、別スレッドで行いたい処理と、 イベントディスパッチスレッドで行いたい処理 の両方を書くことができます。
別スレッドで行いたい長~い処理は、上述のとおり、doInBackgroundに記述し、 イベントディスパッチスレッド上で行いたい処理は、done()あるいはprocess()に記述します。
doneはdoInBackgroundが終了してから実行したい場合
processはdoInBackground実行中に実行したい場合に使います。

doneメソッドの中に書いた処理は、doInBackgourndメソッドが終了すると自動で呼び出され、イベントディスパッチスレッド上で実行されます。
processメソッドの中に書いた処理は、doInBackgroundの中で、publish()を呼び出すと、やはり、イベントディスパッチスレッド上で実行されます。

また、イベントディスパッチスレッド上で実行しなければいけないような処理が無い場合にはdoInBackgroundのみ作成すればよいのです。


■■■■SwingWorkerの2つの引数

SwingWorkerには
SwingWorker<Object,Object>
のように2つの引数があります。
この2つの型はdone、あるいは、processに渡すためのデータの型で、必要な型を書けばよいのです。

まず、1つ目の型はdoInBackgroundの戻り値の型で、これは、doneメソッドの中でget()を呼び出すことで使えます。

2つ目の型はdoInBackgroundの中でpublishを呼び出すときに、引数として使います。
この引数はprocessメソッドに渡されます。
また、doInBackgroundと、processは別スレッドで実行されるため、 1回目のporocessがまだ実行される前に2回目のprocessが呼び出される可能性もあります。
そのような場合、効率のために、processは1回の呼び出しにまとめられ、publish2回分の引数がprocessに渡されます。

たとえば、SwingWorker<T,V>とした場合、
void publish(V... chunks)
void process(List<V> chunks)
となり、publishで渡せるのは、V型の引数をいくつでも渡せるし、processでは、たまたま、publishを2回分実行するような場合には、 2回渡された引数を2個のListとして受け取ることができるようになります。
また、publishは可変個引数ですから、processに引数で渡すものが無い場合には、引数なしで呼び出せばよいことになります。


■■■■SwingWorkerサンプル

さて、上でうまくいかなかったプログラムをSwingWorkerを使って変更してみます。
まずSwingWorkerを継承したクラスを作成します。②
別スレッドで行うのは、300msec待つという長い処理です。これをdoInBackgroundに書きます。③
label.setBoundsの部分はイベントディスパッチスレッド上で実行しなければいけないので、processに書きます。⑤
ループの途中でprocessを呼び出したいので、publishを呼び出し、間接的にprocessを呼び出します。④

10回のループが終わった後、イベントディスパッチスレッド上で実行しなければいけないことはないので、 doneメソッドは、本当は作る必要はないです。削除しても大丈夫です。⑥

doInBackgroundからprocessに渡すデータはないので、publishの引数はなしです。④
引数の型は、使わないので、<Object,Object>としています。②

これで、SwingWorkerを継承したクラスができたので、actionPerformedの中で、このインスタンスを作り、executeを呼び出します。①
executeを呼び出すことにより、別スレッドで、doInBackgroundの実行が開始されます。


SwingWorkerを使ったクラス
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;

public class SwingworkerTest extends JFrame{
 private static int WIDTH = 29;
 private static int HEIGHT = 41;

 JButton btnWalk = new JButton("歩く");
 JLabel  label   = new JLabel(new ImageIcon("./penguin.gif"));
 JPanel  panel = new JPanel();
 JPanel  contentPane = (JPanel)getContentPane();

 int  labelX = 0;
 int  labelY = 0;

 public SwingworkerTest() {
  //--------------------------- パネルとボタンを置く
  contentPane.add(panel,BorderLayout.CENTER);
  contentPane.add(btnWalk,BorderLayout.SOUTH);

  //---------------------------画面の設定
  this.setSize(500,200);
  this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  this.setVisible(true);

  //----------------- パネルの右下にペンギンの乗ったラベルを置く
  panel.setLayout(null);
  labelX = panel.getWidth()-WIDTH;
  labelY = panel.getHeight()-HEIGHT;
  label.setBounds(labelX, labelY, WIDTH, HEIGHT);
  panel.add(label);

  //--------------------------- ボタンの処理
  btnWalk.addActionListener(new ActionListener(){
   public void actionPerformed(ActionEvent e) {
    MySwingWorker worker = new MySwingWorker();
    worker.execute(); //①
   }
  });
 }
 class MySwingWorker extends SwingWorker <Object,Object> { //②
  protected Object doInBackground() throws Exception { //③
   for(int i=0; i<10; i++) {
    publish(); //process()を呼び出す④
    try {
     Thread.sleep(300);
    } catch (InterruptedException e1) {}
   }
   return null;
  }
  protected void process(List <Object>  chunks) {  //⑤
   labelX -= 5;
   label.setBounds(labelX, labelY, WIDTH, HEIGHT);
   System.out.println("process");
  }
  protected void done() {     //⑥
   System.out.println("doInBackgroundの処理が終了しました");
  }
 }
 public static void main(String[] args) {
  new SwingworkerTest();
 }
}



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

2015年5月26日火曜日

AndroidのListView内に複数項目を表示する方法(SimpleAdapterを使う)

目次へ



  • ListViewとは
  • ListViewをレイアウトの中で作成
  • ListViewの中の各項目用レイアウトの作成
  • プログラムでSimpleAdapterを作成し表示


■ListViewとは

いろいろなデータを一覧で表示するにはListViewを使うと便利です。
項目がたくさんあればスクロールも自動でできます
下の画面がListViewを使ったものです。
必要なものは
  • activity_main.xml この中でListViewを定義
  • item.xml ListViewの中の1つ分のデータ(下図の赤の部分)を定義
  • ActivityのonCreateメソッドでSimpleAdapterを作成しListViewの中に複数の項目を作成



■ListViewをレイアウトの中で作成

activity_main.xmlの内容

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:drawSelectorOnTop="false"
        android:layout_weight="1" />

    <TextView
        android:id="@id/test"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

</LinearLayout>



■ListViewの中の各項目用レイアウトの作成

item.xmlの内容

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/vw1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <TextView
           android:id="@+id/comment"
             android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>

</LinearLayout>



■プログラムでSimpleAdapterを作成し表示

MainActivity.javaの内容


public class MainActivity extends ActionBarActivity {

 ArrayList<Map<String,Object>> list = new ArrayList<Map<String, Object>>();
 SimpleAdapter adapter;

 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  // ListView を取得
  ListView listView = (ListView) findViewById(R.id.listView);

  // SimpleAdapterに渡すArrayList作成
  createData();

  // リストビューに渡すアダプタを生成
  adapter = new SimpleAdapter(
   this,
   list,               //ArrayList
   R.layout.item,          //ListView内の1項目を定義したxml
   new String[] { "title", "comment","img" },    //mapのキー
   new int[] {R.id.title, R.id.comment, R.id.img });//item.xml内のid

  // アダプタをセット
  listView.setAdapter(adapter);
 }

 private void createData() {
  for (int n = 0; n < 15; n++) {
   Map data = new HashMap();
   data.put("title", "title" + n);
   data.put("comment", "comment" + n);
   data.put("img", R.drawable.ic_launcher);
   list.add(data);
  }
 }
}










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

2015年4月2日木曜日

AndroidのSoundPoolを使って効果音を鳴らす方法

目次へ



  • SoundPoolとMediaPlayer
  • SoundPoolを使って効果音を鳴らす方法


■■■■SoundPoolとMediaPlayer■■■■

SoundPool、MediaPlayer のどちらも音を鳴らすときに使います。
BGMのような長い音楽を鳴らすにはMediaPlayer、短い効果音などを鳴らすときには、SoundPoolが向いています。
SoundPoolの場合には、メモリにロードされた状態にしておいて、音を鳴らすため、遅延が少ないのが特徴です。

■■■■SoundPoolを使って効果音を鳴らす方法■■■■

使いたい効果音データはリソースとして、プロジェクトのresフォルダ内にrawという名前のフォルダを作成し、その中に保存をします。
SoundPoolのインスタンスを作成するには、SoundPool.Builderクラスのbuildメソッドを使います。
音を再生するにはplayメソッドを使います。
playメソッドの引数は次のようになっています。

int play (int soundID, float leftVolume, float rightVolume, 
   int priority, int loop, float rate)

soundID  サウンドID。loadメソッドが返した値
leftVolume 左のボリューム。範囲は0.0 ~ 1.0
rightVolume 右のボリューム。範囲は0.0 ~ 1.0
priority 優先度。0が優先度が最も低い
loop  ループモード。0:ループしない。-1:ループする
rate  再生速度。1:ノーマル。範囲は 0.5 ~ 2.0




下の例はbutton1を押すと、nyao.wav、button2を押すとgao.wavを再生します
playメソッドの引数を変更することにより、button1の方が小さい音。button2の方が大きい音となり、 また、button2の再生スピードの方が速く(高く)なります。

リソースは res/rawにnyao.wav、gao.wavを入れています。

public class MainActivity extends Activity {
 SoundPool soundPool;
 int sound1;
 int sound2;

 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
 
  //--------------------- SoundPoolのインスタンス作成
  SoundPool.Builder builder = new SoundPool.Builder();
  soundPool = builder.build();

  //--------------------- 効果音をロードしておく。
  //------------引数はContext、リソースID、優先度
  sound1 = soundPool.load(this, R.raw.gao, 1);
  sound2 = soundPool.load(this, R.raw.nyao, 1);
 
  //---------------- button1を押すと効果音(nyao.wav)が鳴る。
  Button button1 = (Button) findViewById(R.id.button1);
  button1.setOnClickListener(new View.OnClickListener() {
   public void onClick(View v) {
    soundPool.play (sound1,0.5f,0.5f,0,0,1);
   }
  });

  //------------------button2を押すと効果音(gao.wav)が鳴る。
  Button button2 = (Button) findViewById(R.id.button2);
  button2.setOnClickListener(new View.OnClickListener() {
   public void onClick(View v) {
    soundPool.play (sound2,1.0f,1.0f,0,0,2);
   }
  });
 }
}





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

AndroidのMediaPlayerを使ってBGMを流す方法

目次へ



  • MediaPlayerを使ってBGMを流す


■■■■MediaPlayerを使ってBGMを流す方法■■■■

BGMを鳴らすには、MediaPlayerを使います。
使いたい音楽データはリソースとして、プロジェクトのresフォルダ内にrawという名前のフォルダを作成し、その中に保存をします。
MediaPlayerのインスタンスを作成するには、MediaPlayer#createメソッドを使います。
下の例はstartボタンを押すとBGMがスタートし、stopボタンを押すとストップするだけのプログラムです


stopを呼び出した後、もう1回再生するには、もう1度createを実行し、MediaPlayerを作り直しています。
なにかほかに方法がありそうな気がします。
stopのあと、prepareメソッドを呼び出したりしてみましたが、うまくいきませんので、とりあえず、忘れないように、createし直す方法だけ書いておきます。
何かわかったら、また追記します。


参考までに、例外の種類は次のとおりです。
stopした後、すぐstartを実行すると、IOException。
stopした後、prepareを呼び出すと、IllegalStateExceptionとなります。


ActivityクラスのonCreateメソッドで次のようにしました
res/rawにはbgm.mp3を入れています。

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

 mp = MediaPlayer.create(this, R.raw.bgm);

 //--------------startボタンの処理
 Button buttonStart = (Button) findViewById(R.id.buttonStart);
 buttonStart.setOnClickListener(new View.OnClickListener() {
  public void onClick(View v) {
   if(!mp.isPlaying()){
    mp.start();
   }
  }
 });
 //--------------stopボタンの処理
 Button buttonStop = (Button) findViewById(R.id.buttonStop);
 buttonStop.setOnClickListener(new View.OnClickListener() {
  public void onClick(View v) {
   if(mp.isPlaying()){
    mp.stop();
    mp.release();
    mp = MediaPlayer.create
     (MainActivity.this, R.raw.bgm);
   }
  }
 });
}





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