2013年12月23日月曜日

USB Host に挑戦

アンドロイドのドキュメント:USB Host

USBディバイスはMbed を使いました。

参考サイト:kshoji:自作のUSBデバイスを、Androidで動かす

参考サイトに詳細に解説されています。

参考サイトの一部必要な所だけ取り出してみました。

とりあえず、Mbed に送信してLED4を点灯させてみる。
点灯と消灯の二つのボタンを置いて操作する。
USBディバイスを接続した時に使うアプリを聞いてくる。

回路図:アンドロイドとUSBホストケーブルで接続する
Mbed のソースコード:参考サイトのソースコードをそのまま使いました。
#include "mbed.h"
#include "USBHID.h"

// device
USBHID hid;

// read
HID_REPORT recv;
BusOut leds(LED1, LED2, LED3, LED4);

// write
HID_REPORT send;
AnalogIn input(p15);

int main(void)
{
    int lastData = 0;
    int currentData;

    send.length = 64;
    while (1) {
        // read
        hid.readNB(&recv);
        if (recv.length > 0) {
            leds = recv.data[0];
            
        }

        currentData = input.read_u16();
        if (currentData != lastData) {
            lastData = currentData;

            // write
            send.data[0] = (currentData >> 8) & 0xff;
            send.data[1] = currentData & 0xff;
            //hid.send(&send);
        }
        
    }
}

アンドロイドアプリのソースコード
エラー処理や例外・終了処理は考慮していない。
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.hidtest002"
    android:installLocation="preferExternal"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="12"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.hidtest002.MainActivity"
            android:label="@string/app_name" >

            <intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
            </intent-filter>

            <meta-data
                android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
                android:resource="@xml/device_filter" />
        </activity>
    </application>

</manifest>

res/xml/device_filter.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- Interface class: USB HID -->
    <usb-device class="3" subclass="0" protocol="0" />
</resources>

MainActivity.java
package com.example.hidtest002;

import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity implements OnClickListener {

 private static final String TAG = "HidTest";
 private TextView text;
 private UsbDeviceConnection deviceConnection = null;
 private UsbEndpoint outputEndpoint2;

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

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

  //  ボタンがクリックされた時の処理
  Button btn1 = (Button) findViewById(R.id.button1);
  btn1.setOnClickListener(this);
  Button btn2 = (Button) findViewById(R.id.button2);
  btn2.setOnClickListener(this);

  //  USB ディバイスが接続されていない時は終了
  if (!UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(getIntent().getAction())) {
   finish();
  } else {
   // USB ディバイスを接続
   Intent intent = getIntent();
   UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
   if (device != null) {
    Log.v(TAG, "UsbDevice がある");
    UsbInterface usbInterface = findUsbInterface(device);
    if (usbInterface != null) {
     // アタッチ
     UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
     deviceConnection = usbManager.openDevice(device);
     deviceConnection.claimInterface(usbInterface, true);
    }
   }
  }

 }

 /*
  * UsbInterface の確認 
  */
 private UsbInterface findUsbInterface(UsbDevice device) {
  // TODO 自動生成されたメソッド・スタブ
  text.setText("UsbDevice.getDeviceName():" + device.getDeviceName() + "\n");
  int count = device.getInterfaceCount();// 4
  text.append("UsbDevice.getInterfaceCount():" + count + "\n");
  for (int i = 0; i < count; i++) {
   UsbInterface usbInterface = device.getInterface(i);

   UsbEndpoint inputEndpoint = null;
   UsbEndpoint outputEndpoint = null;

   text.append("**************************" + "\n");
   text.append(" UsbInterface.getEndpointCount():" + usbInterface.getEndpointCount() + "\n");
   if (usbInterface.getEndpointCount() >= 1) {
    for (int endpointIndex = 0; endpointIndex < usbInterface.getEndpointCount(); endpointIndex++) {
     UsbEndpoint endpoint = usbInterface.getEndpoint(endpointIndex);
     text.append(endpointIndex + ":");

     if ((endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK || endpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_INT)) {
      if (endpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
       outputEndpoint = outputEndpoint == null ? endpoint : outputEndpoint;
       outputEndpoint2 = endpoint;
       text.append("  UsbEndpoint:getDirection()" + endpoint.getDirection() + "\n");// USB_DIR_OUT
      }
     }
    }

    if (inputEndpoint != null || outputEndpoint != null) {
     return usbInterface;
    }
   }
  }

  return null;
 }

 /*
  * ボタンが押された時の処理
  */
 @Override
 public void onClick(View v) {
  // TODO 自動生成されたメソッド・スタブ
  byte data1 = 0;
  byte data2 = 0;
  byte data3 = 0;
  byte data4 = 0;

  switch (v.getId()) {
  case R.id.button1:
   Log.i("buttonTest", "点灯ボタンが押された");
   data1 = 0;
   data2 = 0;
   data3 = 0;
   data4 = (byte) 8;
   break;
  case R.id.button2:
   Log.i("buttonTest", "消灯ボタンが押された");
   data1 = 0;
   data2 = 0;
   data3 = 0;
   data4 = 0;
   break;

  }
  outPutMbed(new byte[] { (byte) (data1 | data2 | data3 | data4) });

 }

 // Mbed に送信
 private void outPutMbed(byte[] bytes) {
  // TODO 自動生成されたメソッド・スタブ
  final int maxPacketSize = outputEndpoint2.getMaxPacketSize();
  for (int i = 0; i < bytes.length; i += maxPacketSize) {
   byte[] writeBuffer = new byte[maxPacketSize];
   int length = (bytes.length - i) < writeBuffer.length ? bytes.length - i : writeBuffer.length;
   System.arraycopy(bytes, i, writeBuffer, 0, length);
   deviceConnection.bulkTransfer(outputEndpoint2, writeBuffer, writeBuffer.length, 0);
  }
 }

 /*
  * メニューの処理
  */
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  switch (item.getItemId()) {
  case R.id.itemFinish:
   Log.v(TAG, "finish");
   finish();
   return true;
  }

  return false;
 }
}

activity_main.xml
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

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

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

            <Button
                android:id="@+id/button1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="点灯" />

            <Button
                android:id="@+id/button2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="消灯" />

        </LinearLayout>

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

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

        </LinearLayout>

    </LinearLayout>

</RelativeLayout>


2013年10月6日日曜日

IntentService を使ってみる:android

http://developer.android.com/guide/components/services.html で紹介されているソースコードを実行してみる。
サービスの終了操作を気にしないでいいようです。
5秒後にサービス終了するコード。

package com.example.intentservice;

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

public class MainActivity extends Activity {

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

  Intent intent = new Intent(this, HelloIntentService.class);
  startService(intent);
 }
}

package com.example.intentservice;

import android.app.IntentService;
import android.content.Intent;
import android.util.Log;

public class HelloIntentService extends IntentService {

 private static final String TAG = "HelloIntentService";

 /** 
  * A constructor is required, and must call the super IntentService(String)
  * constructor with a name for the worker thread.
  */
 public HelloIntentService() {
  super("HelloIntentService");

  Log.v(TAG, "HelloIntentService");
 }

 /**
  * The IntentService calls this method from the default worker thread with
  * the intent that started the service. When this method returns, IntentService
  * stops the service, as appropriate.
  */
 @Override
 protected void onHandleIntent(Intent intent) {
  Log.v(TAG, "onHandleIntent");

  // Normally we would do some work here, like download a file.
  // For our sample, we just sleep for 5 seconds.
  long endTime = System.currentTimeMillis() + 5 * 1000;
  while (System.currentTimeMillis() < endTime) {
   synchronized (this) {
    try {
     wait(endTime - System.currentTimeMillis());
    } catch (Exception e) {
    }
   }
  }
  Log.v(TAG, "onHandleIntent 終了");
 }

 @Override
 public void onDestroy() {
  Log.v(TAG, "onDestroy");
 }

}


UIの変更を考えてみる
package com.example.intentservice;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.widget.TextView;

public class MainActivity extends Activity {

 public static class SampleHandler extends Handler {
  private MainActivity con;

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

  @Override
  public void handleMessage(Message msg) {
   Bundle bundle = msg.getData();
   
    TextView textView = (TextView) con.findViewById(R.id.textView1);
    textView.setText( bundle.getString("mystring") );
  }
 }

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  SampleHandler handler = new SampleHandler(this);

  Intent intent = new Intent(this, HelloIntentService.class);
  intent.putExtra("messenger", new Messenger(handler));
  startService(intent);
 }
}

package com.example.intentservice;

import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

public class HelloIntentService extends IntentService {

 private static final String TAG = "HelloIntentService";

 public HelloIntentService() {
  super("HelloIntentService");

  Log.v(TAG, "HelloIntentService");
 }

 @Override
 protected void onHandleIntent(Intent intent) {
  Log.v(TAG, "onHandleIntent");

  Bundle bundle = intent.getExtras();
  if (bundle != null) {
   Messenger messenger = (Messenger) bundle.get("messenger");
   Message msg = Message.obtain();
   
   Bundle data = new Bundle();
   data.putString("mystring", "Hello!");
   msg.setData(data);
   try {
    messenger.send(msg);
   } catch (RemoteException e) {
    Log.i("error", "error");
   }
  }
 }

 @Override
 public void onDestroy() {
  Log.v(TAG, "onDestroy");
 }

}

while ループが永遠に終わらない処理の場合、
呼び出し元のアクティビティーが終了しても、動き続けるので、
IntentServiceを終了させる処理が必要なようです。


package com.example.intentservice;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.widget.TextView;

public class MainActivity extends Activity {

 public static class SampleHandler extends Handler {
  private MainActivity con;

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

  @Override
  public void handleMessage(Message msg) {
   Bundle bundle = msg.getData();

   TextView textView = (TextView) con.findViewById(R.id.textView1);
   textView.setText(bundle.getString("mystring"));
  }
 }

 private SampleHandler handler;
 private Intent intent;

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

  handler = new SampleHandler(this);

  intent = new Intent(this, HelloIntentService.class);
  intent.putExtra("messenger", new Messenger(handler));
  startService(intent);
 }

 @Override
 public void onDestroy() {
  super.onDestroy();
  // The service is no longer used and is being destroyed

  if (intent != null) {
   stopService(intent);
   intent = null;
  }
 }
}
package com.example.intentservice;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;

import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

public class HelloIntentService extends IntentService {

 private static final String TAG = "HelloIntentService";
 private boolean loopFlag = true;

 public HelloIntentService() {
  super("HelloIntentService");

  Log.v(TAG, "HelloIntentService");

 }

 @Override
 protected void onHandleIntent(Intent intent) {
  Log.v(TAG, "onHandleIntent");

  Bundle bundle = intent.getExtras();

  while (loopFlag) {
   synchronized (this) {
    try {
     Log.v(TAG, "HelloIntentService");
     GregorianCalendar gc = (GregorianCalendar) GregorianCalendar.getInstance(TimeZone.getTimeZone("Asia/Tokyo"));
     String stringTime = gc.get(Calendar.HOUR_OF_DAY) + ":" + gc.get(Calendar.MINUTE) + ":" + gc.get(Calendar.SECOND);

     if (bundle != null) {
      Messenger messenger = (Messenger) bundle.get("messenger");
      Message msg = Message.obtain();

      Bundle data = new Bundle();

      data.putString("mystring", stringTime);
      msg.setData(data);
      try {
       messenger.send(msg);
      } catch (RemoteException e) {
       Log.i("error", "error");
      }
     }

     wait(1000);
    } catch (Exception e) {
    }
   }
  }

 }

 @Override
 public void onDestroy() {
  Log.v(TAG, "onDestroy");
  loopFlag = false;
 }

}

2013年10月5日土曜日

Service と BroadcastReceiver :android



Activity で レシーバーを登録して、インテントでサービスを開始する。

サービスでは、システムの時間を取得して、レシーバーに送る。

レシーバーでは受っとった時間を画面に表示する。

package com.example.servicetest;

import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends Activity {
 IntentFilter intentFilter;
 MyService4Receiver receiver;
 Intent intent = null;

 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  // レシーバーの登録
  receiver = new MyService4Receiver();
  receiver.activity = this;
  intentFilter = new IntentFilter();
  intentFilter.addAction(MyService4Service.actionName);
  registerReceiver(receiver, intentFilter);
 }
 
 public void onResume() {
  super.onResume();
  Log.i("タグ", "onResume()");

  intent = new Intent(getBaseContext(), MyService4Service.class);
  startService(intent);
 }
 
 public void onDestroy() {
  super.onDestroy();
  Log.i("タグ", "onDestroy()");
  
  unregisterReceiver(receiver);//レシーバー登録解除
  
  if (intent != null)
  {
   stopService(intent);//サービスの停止
  }
  intent = null;

 }

}

package com.example.servicetest;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;

public class MyService4Service extends Service {
 public static final String actionName = "MYSERVICE4_ACTION";
 MyHandler mHandler = null;
 private static Context contex;

 @Override
 public int onStartCommand(Intent intent, int flags, int startId) {
  Log.i("MyService4Service", "onStartCommand");

  if (mHandler == null)
  {
   mHandler = new MyHandler();
   mHandler.sendEmptyMessage(1);
  }
  
  contex = getBaseContext();

  return START_NOT_STICKY;//サービスの強制終了後、再起動しない
 }

 public void onDestroy()
 {
  if (mHandler != null)
  {
   mHandler.removeMessages(1);
   mHandler = null;
  }
  super.onDestroy();
 }

 @Override
 public IBinder onBind(Intent arg0) {
  // TODO 自動生成されたメソッド・スタブ
  return null;
 }

 static class MyHandler extends Handler
 {
  public void handleMessage(Message msg)
  {
   GregorianCalendar gc = (GregorianCalendar) GregorianCalendar.getInstance(TimeZone.getTimeZone("Asia/Tokyo"));
   String stringTime = gc.get(Calendar.HOUR_OF_DAY) + ":" + gc.get(Calendar.MINUTE) + ":" + gc.get(Calendar.SECOND);

   Intent broadcastIntent = new Intent();
   broadcastIntent.putExtra("message", stringTime);
   broadcastIntent.setAction(actionName);
   contex.sendBroadcast(broadcastIntent);

   sendEmptyMessageDelayed(1, 1000);
  }
 }
}
package com.example.servicetest;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class MyService4Receiver extends BroadcastReceiver {
 MainActivity activity;// onCreate の receiver.activity = this;


 @Override
 public void onReceive(Context context, Intent intent) {
  // メッセージを取ってくる
  
  Log.i("MyService4Receiver", "onReceive");
  
  Bundle bundle = intent.getExtras();
  String message = bundle.getString("message");
  // そいつを表示する
  if (activity != null)
  {
   TextView tv = (TextView) activity.findViewById(R.id.textView1);
   tv.setText(message);
  }
 }
}

サービスはマニフェストにも登録しておく、
レシーバはregisterReceiver();で動的に登録してあるので、マニフェストには登録しなくても動く。

2013年10月4日金曜日

サービスのバインドについて考えてみる


サービスをバインドして、サービスからUIを変更
package com.example.bindservice;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.TextView;

import com.example.bindservice.SampleService.LocalBinder;

public class MainActivity extends Activity {

 private static final String TAB = "MainActivity";
 private TextView tv;

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

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

 }

 @Override
 public void onStart() {
  Log.i(TAB, "onStart");
  super.onStart();
  // Bind
  Intent intent = new Intent(getApplicationContext(), SampleService.class);
  bindService(intent, mySrviceConnection, Context.BIND_AUTO_CREATE);//サービスをバインド
 }

 @Override
 public void onStop() {
  Log.i(TAB, "onStop");
  super.onStop();
  // Unbind
  unbindService(mySrviceConnection);//サービスをアンバインド
 }

 private ServiceConnection mySrviceConnection = new ServiceConnection() {

  @Override
  public void onServiceConnected(ComponentName name, IBinder service) {
   // TODO 自動生成されたメソッド・スタブ
   LocalBinder binder = (SampleService.LocalBinder) service;
   binder.getService(tv);
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
   // TODO 自動生成されたメソッド・スタブ

  }
 };

}
package com.example.bindservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.TextView;

public class SampleService extends Service {

 private static final String TAB = "SampleService";
 private IBinder mBinder = new LocalBinder();

 public class LocalBinder extends Binder {
        SampleService getService(TextView tv) {
      Log.i(TAB, "LocalBinder");//
      tv.setText("サービスから変更");
            return SampleService.this;
        }
    }

 @Override
 public IBinder onBind(Intent intent) {
  // TODO 自動生成されたメソッド・スタブ
  Log.i(TAB, "onBind");//起動時に呼ばれる

  return mBinder;
 }

 @Override
 public void onDestroy() {
  Log.i(TAB, "onDestroy");
 }
}

ボタンクリックでUIを変更してみる
package com.example.bindservice;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import com.example.bindservice.SampleService.LocalBinder;

public class MainActivity extends Activity {

 private static final String TAB = "MainActivity";
 private TextView tv;
 private LocalBinder binder;

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

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

  Button button = (Button) findViewById(R.id.button1);
  button.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View v) {
    Log.i(TAB, "ボタン2が押された");
    if (binder != null){
     Log.i(TAB, "binder は null で無い");
     binder.getService(tv);
    }else{
     Log.i(TAB, "binder は null");
    }
   }
  });
 }

 @Override
 public void onStart() {
  Log.i(TAB, "onStart");
  super.onStart();
  // Bind
  Intent intent = new Intent(getApplicationContext(), SampleService.class);
  bindService(intent, mySrviceConnection, Context.BIND_AUTO_CREATE);//サービスをバインド
 }

 @Override
 public void onStop() {
  Log.i(TAB, "onStop");
  super.onStop();
  // Unbind
  unbindService(mySrviceConnection);//サービスをアンバインド
 }

 private ServiceConnection mySrviceConnection = new ServiceConnection() {

  @Override
  public void onServiceConnected(ComponentName name, IBinder service) {
   // TODO 自動生成されたメソッド・スタブ
   binder = (SampleService.LocalBinder) service;
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
   // TODO 自動生成されたメソッド・スタブ

  }
 };

}
package com.example.bindservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.TextView;

public class SampleService extends Service {

 private static final String TAB = "SampleService";
 private IBinder mBinder = new LocalBinder();

 public class LocalBinder extends Binder {
  void getService(TextView tv) {
   Log.i(TAB, "LocalBinder");//
   tv.setText("サービスから変更");
  }
 }

 @Override
 public IBinder onBind(Intent intent) {
  // TODO 自動生成されたメソッド・スタブ
  Log.i(TAB, "onBind");//起動時に呼ばれる

  return mBinder;
 }

 @Override
 public void onDestroy() {
  Log.i(TAB, "onDestroy");
 }
}


サービスでスレッドを利用して定期的にUIを更新
package com.example.bindservice;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import com.example.bindservice.SampleService.LocalBinder;

public class MainActivity extends Activity {

 private static final String TAB = "MainActivity";
 private TextView tv;
 private LocalBinder binder;

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

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

  Button button = (Button) findViewById(R.id.button1);
  button.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View v) {
    Log.i(TAB, "ボタン2が押された");
    if (binder != null){
     Log.i(TAB, "binder は null ではない");
     binder.getService(tv);
    }else{
     Log.i(TAB, "binder は null");
    }
   }
  });
 }

 @Override
 public void onStart() {
  Log.i(TAB, "onStart");
  super.onStart();
  // Bind
  Intent intent = new Intent(getApplicationContext(), SampleService.class);
  bindService(intent, mySrviceConnection, Context.BIND_AUTO_CREATE);//サービスをバインド
 }

 @Override
 public void onStop() {
  Log.i(TAB, "onStop");
  super.onStop();
  // Unbind
  unbindService(mySrviceConnection);//サービスをアンバインド
 }

 private ServiceConnection mySrviceConnection = new ServiceConnection() {

  @Override
  public void onServiceConnected(ComponentName name, IBinder service) {
   // TODO 自動生成されたメソッド・スタブ
   binder = (SampleService.LocalBinder) service;
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
   // TODO 自動生成されたメソッド・スタブ

  }
 };

}
package com.example.bindservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;

public class SampleService extends Service {

 private Handler handler;

 public class MyThread implements Runnable {

  private int data;

  @Override
  public void run() {
   // TODO 自動生成されたメソッド・スタブ
   while (true) {
    Log.i(TAB, "run::" + data);//二番目に呼ばれる

    data++;
    Message msg = handler.obtainMessage();
    msg.arg1 = data;
    handler.sendMessage(msg);
    try {
     Thread.sleep(2000);
    } catch (InterruptedException e) {
     // TODO 自動生成された catch ブロック
     e.printStackTrace();
    }
   }
  }

 }

 private static final String TAB = "SampleService";
 private IBinder mBinder = new LocalBinder();

 public class LocalBinder extends Binder {

  void getService(final TextView tv) {
   Log.i(TAB, "LocalBinder");//
   //tv.setText("setData から変更");//ここでも変更可能

   new Thread(new MyThread()).start();

   /*
   //動くがメモリーリークの可能性がある
   //This Handler class should be static or leaks might occur
   handler = new Handler() {
    public void handleMessage(Message msg) {
     //updata.update(tv, data);
     Log.i(TAB, "handleMessage::" + msg);

     tv.setText(String.valueOf(msg.arg1));//ここでも変更可能

    }
   };
   */
   handler = new MyHandler(tv);
  }
 }

 @Override
 public IBinder onBind(Intent intent) {
  // TODO 自動生成されたメソッド・スタブ
  Log.i(TAB, "onBind");//起動時に呼ばれる

  return mBinder;
 }

 @Override
 public void onDestroy() {
  Log.i(TAB, "onDestroy");
 }

 public static class MyHandler extends Handler {
  private TextView tv;

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

  @Override
  public void handleMessage(Message msg) {
   Log.i(TAB, "handleMessage::" + msg);
   tv.setText(String.valueOf(msg.arg1));//ここでも変更可能
  }

 }
}

サービスで変更された値をアクティビティに戻してUIを変更する。
package com.example.bindservice;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import com.example.bindservice.SampleService.LocalBinder;
import com.example.bindservice.SampleService.UpdateData;

public class MainActivity extends Activity {

 private static final String TAB = "MainActivity";
 private TextView tv;
 private LocalBinder binder;

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

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

  Button button = (Button) findViewById(R.id.button1);
  button.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View v) {
    Log.i(TAB, "ボタン2が押された");
    if (binder != null) {
     Log.i(TAB, "binder は null ではない");
     binder.getService(new UpdateData() {

      @Override
      public void update(int data) {
       // TODO 自動生成されたメソッド・スタブ
       tv.setText(data + "");
      }
     });

    } else {
     Log.i(TAB, "binder は null");
    }
   }
  });
 }

 @Override
 public void onStart() {
  Log.i(TAB, "onStart");
  super.onStart();
  // Bind
  Intent intent = new Intent(getApplicationContext(), SampleService.class);
  bindService(intent, mySrviceConnection, Context.BIND_AUTO_CREATE);//サービスをバインド
 }

 @Override
 public void onStop() {
  Log.i(TAB, "onStop");
  super.onStop();
  // Unbind
  unbindService(mySrviceConnection);//サービスをアンバインド
 }

 private ServiceConnection mySrviceConnection = new ServiceConnection() {

  @Override
  public void onServiceConnected(ComponentName name, IBinder service) {
   // TODO 自動生成されたメソッド・スタブ
   binder = (SampleService.LocalBinder) service;
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
   // TODO 自動生成されたメソッド・スタブ

  }
 };

}
package com.example.bindservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;

public class SampleService extends Service {

 public interface UpdateData {
  public void update(int data);
 }

 private Handler handler;

 public class MyThread implements Runnable {

  private int data;

  @Override
  public void run() {
   // TODO 自動生成されたメソッド・スタブ
   while (true) {
    Log.i(TAB, "run::" + data);//二番目に呼ばれる

    data++;
    Message msg = handler.obtainMessage();
    msg.arg1 = data;
    handler.sendMessage(msg);
    try {
     Thread.sleep(2000);
    } catch (InterruptedException e) {
     // TODO 自動生成された catch ブロック
     e.printStackTrace();
    }
   }
  }

 }

 private static final String TAB = "SampleService";
 private IBinder mBinder = new LocalBinder();

 public class LocalBinder extends Binder {

  void getService(UpdateData updata) {
   Log.i(TAB, "LocalBinder");//
   //tv.setText("setData から変更");//ここでも変更可能

   new Thread(new MyThread()).start();

   handler = new MyHandler(updata);
  }
 }

 @Override
 public IBinder onBind(Intent intent) {
  // TODO 自動生成されたメソッド・スタブ
  Log.i(TAB, "onBind");//起動時に呼ばれる

  return mBinder;
 }

 @Override
 public void onDestroy() {
  Log.i(TAB, "onDestroy");
 }

 public static class MyHandler extends Handler {
  private UpdateData updata;

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

  @Override
  public void handleMessage(Message msg) {
   Log.i(TAB, "handleMessage::" + msg);
   //tv.setText(String.valueOf(msg.arg1));//ここでも変更可能
   updata.update(msg.arg1);
  }

 }
}

時間を表示してみる。
package com.example.bindservice;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import com.example.bindservice.SampleService.LocalBinder;
import com.example.bindservice.SampleService.UpdateData;

public class MainActivity extends Activity {

 private static final String TAB = "MainActivity";
 private TextView tv;
 private LocalBinder binder;

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

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

  Button button = (Button) findViewById(R.id.button1);
  button.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View v) {
    Log.i(TAB, "ボタン2が押された");
    if (binder != null) {
     Log.i(TAB, "binder は null ではない");
     binder.getService(new UpdateData() {

      @Override
      public void update(String data) {
       // TODO 自動生成されたメソッド・スタブ
       tv.setText(data + "");
      }
     });

    } else {
     Log.i(TAB, "binder は null");
    }
   }
  });
 }

 @Override
 public void onStart() {
  Log.i(TAB, "onStart");
  super.onStart();
  // Bind
  Intent intent = new Intent(getApplicationContext(), SampleService.class);
  bindService(intent, mySrviceConnection, Context.BIND_AUTO_CREATE);//サービスをバインド
 }

 @Override
 public void onStop() {
  Log.i(TAB, "onStop");
  super.onStop();
  // Unbind
  unbindService(mySrviceConnection);//サービスをアンバインド
 }

 private ServiceConnection mySrviceConnection = new ServiceConnection() {

  @Override
  public void onServiceConnected(ComponentName name, IBinder service) {
   // TODO 自動生成されたメソッド・スタブ
   binder = (SampleService.LocalBinder) service;
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
   // TODO 自動生成されたメソッド・スタブ

  }
 };

}
package com.example.bindservice;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;

public class SampleService extends Service {

 public interface UpdateData {
  public void update(String data);
 }

 private static final String TAB = "SampleService";
 private IBinder mBinder = new LocalBinder();

 public class LocalBinder extends Binder {

  void getService(UpdateData updata) {
   Log.i(TAB, "LocalBinder");//
   //tv.setText("setData から変更");//ここでも変更可能

   //new Thread(new MyThread()).start();

   MyHandler handler = new MyHandler(updata);
   handler.sendEmptyMessage(1);
  }
 }

 @Override
 public IBinder onBind(Intent intent) {
  // TODO 自動生成されたメソッド・スタブ
  Log.i(TAB, "onBind");//起動時に呼ばれる

  return mBinder;
 }

 @Override
 public void onDestroy() {
  Log.i(TAB, "onDestroy");
 }

 public static class MyHandler extends Handler {
  private UpdateData updata;

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

  @Override
  public void handleMessage(Message msg) {
   Log.i(TAB, "handleMessage::" + msg);

   GregorianCalendar gc = (GregorianCalendar) GregorianCalendar.getInstance(TimeZone.getTimeZone("Asia/Tokyo"));
   String data = gc.get(Calendar.HOUR_OF_DAY) + ":" + gc.get(Calendar.MINUTE) + ":" + gc.get(Calendar.SECOND);

   sendEmptyMessageDelayed(1, 1000);
   
   updata.update(data);
  }

 }
}




2013年9月24日火曜日

キャッチされなかった例外が発生した場合の処理:Android UncaughtExceptionHandler


キャッチされなかった例外が発生した場合、アプリを再起動させる。

package com.example.exceptionchach;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;

public class MainActivity extends Activity {

 protected static final String TAG = "123";

 private MainActivity activityMain;

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

  activityMain = this;

  //キャッチされない例外により、スレッドが突然終了したときや、  
  //このスレッドに対してほかにハンドラが定義されていないときに  
  //呼び出されるデフォルトのハンドラを設定します。  
  Thread.setDefaultUncaughtExceptionHandler(new CsUncaughtExceptionHandler(activityMain));

  findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
   @Override
   public void onClick(View v) {
    // 例外を発生させる
    throw new IllegalStateException();
   }
  });
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }

}

package com.example.exceptionchach;

import java.lang.Thread.UncaughtExceptionHandler;

import android.content.Intent;
import android.util.Log;

public class CsUncaughtExceptionHandler implements UncaughtExceptionHandler {

 private static final String TAG = "CsUncaughtExceptionHandler";

 // 現在設定されている UncaughtExceptionHandler を退避
 final UncaughtExceptionHandler savedUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();

 private MainActivity myContext;

 public CsUncaughtExceptionHandler(MainActivity context) {
  // TODO 自動生成されたコンストラクター・スタブ
  myContext = context;
 }

 /*
  * キャッチされない例外によって指定されたスレッドが終了したときに呼び出されます 
  */
 @Override
 public void uncaughtException(Thread thread, Throwable exception) {
  // TODO 自動生成されたメソッド・スタブ
  Log.d(TAG, "uncaughtException");

  // catchされなかった例外処理 エラーログを保存したりする。

  // 退避しておいた UncaughtExceptionHandler を実行
  //savedUncaughtExceptionHandler.uncaughtException(thread, ex);//例外のダイアログ表示

  //再起動処理
  Intent in = new Intent(myContext, MainActivity.class);
  myContext.startActivity(in);

  myContext.finish();
  android.os.Process.killProcess(android.os.Process.myPid());

 }

}

2013年9月20日金曜日

PreferenceActivityのdeprecation対策


package com.example.preferencetest;

import android.annotation.TargetApi;
import android.os.Bundle;
import android.os.Build;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;

public class Pref extends PreferenceActivity {

 @TargetApi(11)
 public class prefFragment extends PreferenceFragment  {
  @Override
  public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   
      addPreferencesFromResource(R.xml.preferences);
  }

 }
 @TargetApi(11)
 @SuppressWarnings("deprecation")
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  // version3.0 より前 
  if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
   addPreferencesFromResource(R.xml.preferences);
        
  } else {
   // version3.0 以降
   getFragmentManager().beginTransaction().replace(android.R.id.content, new prefFragment()).commit();
  }
 }
}




2013年9月16日月曜日

別スレッドで位置情報を取得する:Android GPS Looper



package com.example.gpsintent2;

import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.widget.TextView;

public class MainActivity extends Activity {

 private MyLocThread thread1;
 private TextView textView;
 private Handler viewHandler;
 private static final String TAG = "********************";

 public class MyLocThread extends Thread  {

  private LocationManager locationManager;

  private LocationHelper loc;
  private Handler handler;
  

  public MyLocThread() {
   Log.v(TAG, "------MyLocThread----");

   setDaemon(true);
   setName("LocationThread");
   locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
   
   loc = new LocationHelper(  );
   

  }

  public void run() {
   Log.v(TAG, "------run----");
   
   Looper.prepare();
   handler = new Handler();
   locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 0f, loc );
   Looper.loop();

  }

  private void StopRequest() {
   // TODO 自動生成されたメソッド・スタブ
   if( locationManager != null){
    locationManager.removeUpdates(loc);
   }
   
   if ( this.handler != null ){
    Log.i(TAG, "looper と handler 停止処理");
    
    this.handler.getLooper().quit();
    this.handler  = null;
    
   }
  }
 }

 public class LocationHelper implements LocationListener {

  private Location loc;

  @Override
  public void onLocationChanged(Location location) {
   // TODO 自動生成されたメソッド・スタブ
   Log.v(TAG, "onLocationChanged");
   
   loc = location;

   viewHandler.post(new Runnable() {
    public void run() {
     textView.setText( "緯度" + loc.getLatitude() );
    }
   });

   Log.i("Latitude", String.valueOf(location.getLatitude()));
   Log.i("Longitude", String.valueOf(location.getLongitude()));
   Log.i("Accuracy", String.valueOf(location.getAccuracy()));
   Log.i("Altitude", String.valueOf(location.getAltitude()));
   Log.i("Time", String.valueOf(location.getTime()));
   Log.i("Speed", String.valueOf(location.getSpeed()));
   Log.i("Bearing", String.valueOf(location.getBearing()));
  }

  @Override
  public void onProviderDisabled(String arg0) {
   // TODO 自動生成されたメソッド・スタブ
   Log.v(TAG, "onProviderDisabled");
  }

  @Override
  public void onProviderEnabled(String arg0) {
   // TODO 自動生成されたメソッド・スタブ
   Log.v(TAG, "onProviderEnabled");
  }

  @Override
  public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
   // TODO 自動生成されたメソッド・スタブ
   Log.v(TAG, "onStatusChanged");
  }

 }

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  
  textView = (TextView) findViewById(R.id.textView1);
  
  //UI を変更したい場合必要
  viewHandler = new Handler();

 }

 @Override
 protected void onResume() {
  super.onResume();

  Log.i(TAG, "onResume");

  thread1 = new MyLocThread();
  thread1.start();

 }

 @Override
 protected void onPause() {
  super.onPause();

  Log.i(TAG, "onPause");
  
  // 便宜的にここで停止処理
  thread1.StopRequest();

 }

}


AVDに位置情報を送る:Android gps

エミュレータに位置情報を送るのに、苦労したのでメモしておく。

結論はAVDのターゲットをGoogle APIs にする。


ターゲットに選択肢が出ない場合は、Android SDK Manager を起動させてダウンロードしておく。

あとは、DDMSパースペクティブ のエミュレーター制御から、
Location Controls の送信ボタンを押す。


端数に違いが?


その他:
プログラムでは、GPS_PROVIDER を使う。
マニフェストにも、<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> の許可を与える。


2013年9月15日日曜日

BroadcastReceiver を使って位置情報取得 エンクロージング:GPS

BroadcastReceiver はプログラムから登録しているのでマニフェストでは指定していない。


package com.example.gpsintent2;

import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
import android.widget.TextView;

public class MainActivity extends Activity {

 private static final String TAG = "MainActivity";
 private static final String ACTION_LOCATION_UPDATE = "com.android.practice.ACTION_LOCATION_UPDATE";
 private LocationManager locationManager;
 private PendingIntent pendingIntent;
 private LocationUpdateReceiver receiv;
 
 public class LocationUpdateReceiver extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent) {
   // TODO 自動生成されたメソッド・スタブ
   Log.i(TAG, "onReceive");

   String action = intent.getAction();

   if (action != null && action.equals(ACTION_LOCATION_UPDATE)) {
    final Location location = (Location) intent.getExtras().get(LocationManager.KEY_LOCATION_CHANGED);
    
    if (location == null) {
     return;
    }
    updateView(location);
   }
  }

  private void updateView(Location location) {
   // TODO 自動生成されたメソッド・スタブ

   TextView textView = (TextView) findViewById(R.id.textView1);
   textView.setText(String.valueOf(location.getLatitude()));
  }

 }

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

  Log.i(TAG, "************** onCreate");

  locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

  IntentFilter filter = new IntentFilter();
  filter.addAction(ACTION_LOCATION_UPDATE);

  receiv = new LocationUpdateReceiver();
  registerReceiver(receiv, filter);

 }

 @Override
 protected void onResume() {
  super.onResume();

  Log.i(TAG, "onResume");

  Intent intent = new Intent();
  intent.setAction(ACTION_LOCATION_UPDATE);

  pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);


  for (String providerName : locationManager.getAllProviders()) {
   if (locationManager.isProviderEnabled(providerName)) {
     Log.d(TAG, "Provider: " + providerName);
    // LocationManagerにPendingIntentを登録
    locationManager.requestLocationUpdates(providerName, 0, 0, pendingIntent );
   }
  }
 }

 @Override
 protected void onPause() {
  super.onPause();

  Log.i(TAG, "onPause");

  unregisterReceiver(receiv);
  locationManager.removeUpdates(pendingIntent);

 }

}

<?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="match_parent"
    android:orientation="vertical" >

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

</LinearLayout>

2013年9月5日木曜日

Android 2.x系 でタブを実現:ActionBarSherlock



とりあえずやってみる。

ActionBarSherlock のサイトから

JakeWharton-ActionBarSherlock-4.4.0-0-g4a79d53.zip をダウンロードし解凍する。
解凍したらJakeWharton-ActionBarSherlock-5a15d92 フォルダが作成される。

eclipse で使ええるようにする。
ファイル->インポートを選んで、
ウインドウでAndroidのExisting Android Code Into Workspace を選択する。

インポートするプロジェクトを選択する。
解凍して出来たフォルダの中にある、
actionbarsherlock フォルダを選択する。


プロジェクトエクスプローラに読みこまれる。

ActionBarSherlock の準備はとりあえず完了。

タブを使うAndroid プロジェクトを作成する。

プロジェクトで ActionBarSherlock を使えるようにする。
パッケージエクスプローラからプロジェクトを選択して、
右クリックからプロパティーを選択する。
左のAndroid を選択して、ライブラリの追加ボタンをクリックする。
現れたウインドウから、actionbarsherlock を選択してOKボタンをクリックする。



エラーが発生した。
[2013-09-05 08:36:56 - TabTest] Found 2 versions of android-support-v4.jar in the dependency list,
[2013-09-05 08:36:56 - TabTest] but not all the versions are identical (check is based on SHA-1 only at this time).
[2013-09-05 08:36:56 - TabTest] All versions of the libraries must be the same at this time.
[2013-09-05 08:36:56 - TabTest] Versions found are:
[2013-09-05 08:36:56 - TabTest] パス: D:\workspaceTop\workspace\actionbarsherlock\libs\android-support-v4.jar
[2013-09-05 08:36:56 - TabTest] 長さ: 271754
[2013-09-05 08:36:56 - TabTest] SHA-1: 53307dc2bd2b69fd5533458ee11885f55807de4b
[2013-09-05 08:36:56 - TabTest] パス: D:\workspaceTop\workspace\TabTest\libs\android-support-v4.jar
[2013-09-05 08:36:56 - TabTest] 長さ: 556198
[2013-09-05 08:36:56 - TabTest] SHA-1: 4a6be13368bb64c5a0b0460632d228a1a915f58f
[2013-09-05 08:36:56 - TabTest] Jar mismatch! Fix your dependencies

actionbarsherlock と 自分で作成したプロジェクトで使っている、android-support-v4.jar が違うと想像されるるので、
自分で作ったプロジェクトの中のlibsフォルダに入っている、android-support-v4.jar を
actionbarsherlock の中のlibsフォルダにコピーする。

これで本当に準備完了だと思う。

タブが2つあるページを作る
1つ目のタブに表示する xml レイアウトを作成する。
パッケージエクスプローラからプロジェクトを選択して、右クリックで、
新規->Android XML ファイルを選択する。

fragment_tab1.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="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Tab1" />

</LinearLayout>
同様に、
2つ目のタブに表示する 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="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Tab2" />

</LinearLayout>

1つ目のタブの Fragment を作成する。
プロジェクトエクスプローラからプロジェクトを選択して、
src フォルダの中のcom.example.tabtest を選択して、右クリックから新規からクラスを選択する。
Tab1Fragment.java
package com.example.tabtest;

import android.os.Bundle;  
import android.support.v4.app.Fragment;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.ViewGroup;  
  
public class Tab1Fragment extends Fragment {  
    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
               
        return inflater.inflate(R.layout.fragment_tab1, container, false);  
    }  
}  
Tab2Fragment.java
package com.example.tabtest;

import android.os.Bundle;  
import android.support.v4.app.Fragment;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.ViewGroup;  
  
public class Tab2Fragment extends Fragment {  
    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
                 
        return inflater.inflate(R.layout.fragment_tab2, container, false);  
    }  
}  

タブを選択した時の処理をする。
TabListener.java を作る。
package com.example.tabtest;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.app.SherlockFragmentActivity;

public class TabListener<T extends Fragment> implements ActionBar.TabListener {

 private Fragment mFragment;
 private final SherlockFragmentActivity mActivity;
 private final String mTag;
 private final Class<T> mClass;

 private static final String TAG = "TabListener";

 public TabListener(MainActivity activity, String tag, Class<T> clz) {
  // TODO 自動生成されたコンストラクター・スタブ
  mActivity = activity;
  mTag = tag;
  mClass = clz;

  mFragment = mActivity.getSupportFragmentManager().findFragmentByTag(
    mTag);
 }

 /*
  * 概要: タブが選択されたときの処理
  */
 @Override
 public void onTabSelected(Tab tab, FragmentTransaction ft) {
  // TODO 自動生成されたメソッド・スタブ

  if (mFragment == null) {
   mFragment = Fragment.instantiate(mActivity, mClass.getName());
   FragmentManager fm = mActivity.getSupportFragmentManager();

   fm.beginTransaction().add(android.R.id.content, mFragment, mTag)
     .commit();
  } else {
   if (mFragment.isDetached()) {
    FragmentManager fm = mActivity.getSupportFragmentManager();
    fm.beginTransaction().attach(mFragment).commit();
   }
  }
 }

 /*
  * タブの選択が解除されたときの処理
  */
 @Override
 public void onTabUnselected(Tab tab, FragmentTransaction ft) {
  // TODO 自動生成されたメソッド・スタブ

  FragmentManager fm = mActivity.getSupportFragmentManager();
  fm.beginTransaction().detach(mFragment).commit();
 }

 @Override
 public void onTabReselected(Tab tab, FragmentTransaction ft) {
  // TODO 自動生成されたメソッド・スタブ

 }

}



MainActivity.java にタブを設定する
package com.example.tabtest;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity;

import android.os.Bundle;

public class MainActivity extends SherlockFragmentActivity {

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

  // テーマを設定する
  setTheme(R.style.Theme_Sherlock_Light);

  // アクションバーを設定する。
  ActionBar actionBar = getSupportActionBar();
  actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

  actionBar.addTab(actionBar
    .newTab()
    .setText("タブ1")
    .setTabListener(
      new TabListener<Tab1Fragment>(this, "tag1",
        Tab1Fragment.class)));
  actionBar.addTab(actionBar
    .newTab()
    .setText("タブ2")
    .setTabListener(
      new TabListener<Tab2Fragment>(this, "tag2",
        Tab2Fragment.class)));
 }

 // @Override
 // public boolean onCreateOptionsMenu(Menu menu) {
 // // Inflate the menu; this adds items to the action bar if it is present.
 // getMenuInflater().inflate(R.menu.main, menu);
 // return true;
 // }

}


参考ページ:Android ActionBarとFragmentを使用してTab画面を表示する(Android 2.x)

2013年8月27日火曜日

サービスの使い方。バインド、ブロードキャスト

サービスとブロードキャストレシーバの利用方法
サービスの開始は
startServiceと
bindServiceをボタンで指定


package com.example.servicetest;

import android.os.Bundle;
import android.os.IBinder;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.util.Log;
import android.view.View;

public class MainActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
 }
 
 @Override
 protected void onResume() {
  super.onResume();
  
  // broadcastReceiver の登録
  IntentFilter intentFilter = new IntentFilter();
  intentFilter.addAction("MY_ACTION");
  registerReceiver(broadcastReceiver, intentFilter);
 }
 @Override
    protected void onPause() {
        super.onPause();
        //レシーバーの登録解除
        unregisterReceiver(broadcastReceiver);
    }
 /*
  * 概要:ブロードキャストを受け取った時の処理
  */
 private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
   Bundle bundle = intent.getExtras();
   String str = bundle.getString("STRING_SERVICE");

   Log.i("TAG", str);
  }
 };

 // ボタンがクリックされた時の処理
 public void setOnClick(View v) {
  switch (v.getId()) {
  case R.id.buttonStart:
   Log.i("TAG", "スタートボタンが押された");
   startService(new Intent(MainActivity.this, MyService.class));
   break;
  case R.id.buttonStop:// stopServiceでサービスの終了
   Log.i("TAG", "ストップボタンが押された");
   stopService(new Intent(MainActivity.this, MyService.class));
   break;
   
  case R.id.buttonBind://doBindService
   Log.i("TAG", "バインド ボタンが押された");
            doBindService();
            break;
            
  case R.id.buttonUnbind://doUnbindService
   Log.i("TAG", "アンバインド ボタンが押された");
            doUnbindService();
            break;
 
        default:
            break;
  }
 }
 
 //以下 サービスのバインド処理
 private boolean mIsBound;
 
 private void doBindService() {
  // TODO 自動生成されたメソッド・スタブ
  //サービスとの接続を確立する。明示的にServiceを指定
     //(特定のサービスを指定する必要がある。他のアプリケーションから知ることができない = ローカルサービス)
     bindService(new Intent(MainActivity.this,MyService.class), mConnection, Context.BIND_AUTO_CREATE);
     mIsBound = true;
 }
 
 private void doUnbindService() {
  // TODO 自動生成されたメソッド・スタブ
  if (mIsBound) {
         // コネクションの解除
         unbindService(mConnection);
         mIsBound = false;
     }
 }
 
 private ServiceConnection mConnection = new ServiceConnection() {

  private MyService mBoundService;

  @Override
  public void onServiceConnected(ComponentName className, IBinder service) {
   // TODO 自動生成されたメソッド・スタブ
      Log.i("TAG", "onServiceConnected");
      
          // サービスにはIBinder経由で#getService()してダイレクトにアクセス可能
          mBoundService = ((MyService.MyServiceLocalBinder)service).getService();
   
          //必要であればmBoundServiceを使ってバインドしたサービスへの制御を行う
  }

  @Override
  public void onServiceDisconnected(ComponentName className) {
   // TODO 自動生成されたメソッド・スタブ
    // サービスとの切断(異常系処理)
         // プロセスのクラッシュなど意図しないサービスの切断が発生した場合に呼ばれる。
         mBoundService = null;
         Log.i("TAG", "onServiceDisconnected");
  }
  
 };
}


package com.example.servicetest;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

public class MyService extends Service {

 private static final String TAG = "TAG";
 private Timer timer;
 
 @Override
 public void onCreate() {
  Log.i(TAG, "onCreate");

  timer = new Timer();
  timer.schedule(new TimerTask() {

   private int counter;

   @Override
   public void run() {
    counter++;

    Intent broadcastIntent = new Intent();
    broadcastIntent.setAction("MY_ACTION");
    broadcastIntent.putExtra("STRING_SERVICE", "asd" + counter);
    getBaseContext().sendBroadcast(broadcastIntent);

    Log.v(TAG, "::" + counter);
   }

  }, 1000, 1000);
 }

 @Override
 public int onStartCommand(Intent intent, int flags, int startId) {
  Log.i(TAG, "onStartCommand Received start id " + startId + ": " + intent);
  // 明示的にサービスの起動、停止が決められる場合の返り値
  return START_STICKY;
 }

 @Override
 public void onDestroy() {
  Log.i(TAG, "onDestroy");
  timer.cancel();//タイマーの停止
 }

 
 //サービスに接続するためのBinder
    public class MyServiceLocalBinder extends Binder {
        //サービスの取得
        MyService getService() {
            return MyService.this;
        }
    }
    
  //Binderの生成
    private final IBinder mBinder = new MyServiceLocalBinder();
    
 @Override
 public IBinder onBind(Intent intent) {
  // TODO 自動生成されたメソッド・スタブ
  Log.i(TAG, "onBind" + ": " + intent);
  return mBinder;
 }
 
 @Override
 public void onRebind(Intent intent) {
  Log.i(TAG, "onRebind" + ": " + intent);
 }
 
 @Override
 public boolean onUnbind(Intent intent) {
  Log.i(TAG, "onUnbind" + ": " + intent);

  // onUnbindをreturn trueでoverrideすると次回バインド時にonRebildが呼ばれる
  return true;
 }

}


2013年7月24日水曜日

Android NDK に挑戦



やっと、HelloJni が動いたのでメモ

SDK は adt-bundle-windows-x86_64-20130717.zip を解凍して利用

eclipse は adt-bundle-windows-x86_64-20130717 の中にあるやつを利用。

NDK は android-ndk-r8e-windows-x86_64.zip を解凍して利用

eclipseの設定
NDK Location を設定

サンプルをワークスペースに読み込む。
ファイルからエクスポートを選択する。


D:\soft\android-ndk-r8e\samples\hello-jni を選択して、
ワークスペースにコピーにチェックを入れる。

読み込まれたプロジェクトを右クリックして、
Android Tool から Add Native Support... を選択する。

そのまま フィニッシュ

このまま実行してもエラーが出る。

sdk のバージョンを調整する。

Android SDK Manager で Android 2.3.3 のパッケージをダウンロードする。
eclipse の再起動が必要かも

AVD を作成する。

ビルドターゲットを変更する。
パッケージエクスプローラからブロジェクトを選んで右クリックして、
プロパティーを選択して、
Android 2.3.3 をを選択する。


マニフェストの minSdkVersion を9に変更する
たぶんこの辺が重要なんだろうか。

C++ のパースペクティブから、
プロジェクトのクリーン、
プロジェクトのビルド、をして、
実行すれば完了。

感想。
いろいろなサイトで、環境変数の登録との説明とかがあったが、
今のところ必要ないようです。

JNI は 、Java から C++ のライブラリを使ったり、その逆のための仕組み。
Android 固有の仕組みではない。

2013年7月18日木曜日

ListView の最後の行の下線を表示させる


layout_height の指定を、wrap_content から、match_parent に変更する。

  <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>

ListViewの中のボタンの処理

ListView の中のボタンを押したら2行目を非表示にする。


1行目のボタンを押した場合↓
package com.example.listviewtest;

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

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

public class MainActivity extends Activity {

 private HashMap<String, String> data;

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

  List<Map<String, String>> dataList = new ArrayList<Map<String, String>>();

  Map<String, String> data = new HashMap<String, String>();
  data.put("title", "タイトル欄");
  data.put("comment", "COMMENT欄");
  dataList.add(data);

  data = new HashMap<String, String>();
  data.put("title", "タイトル欄2");
  data.put("comment", "COMMENT欄");
  dataList.add(data);

  MySimpleAdapter adapter = new MySimpleAdapter(
    this, 
    dataList, 
    R.layout.row, 
    new String[] { "title", "comment" }, 
    new int[] { android.R.id.text1,
    android.R.id.text2 });

  ListView listView = (ListView) findViewById(R.id.listView1);
  listView.setAdapter(adapter);//
 }
}
package com.example.listviewtest;

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

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.SimpleAdapter;
import android.widget.TextView;

public class MySimpleAdapter extends SimpleAdapter {

 // private Context context;
 private LayoutInflater inflater;
 private List<? extends Map<String, ?>> listData;

 public class ViewHolder {
  TextView line1;
  TextView line2;
 }

 public MySimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) {
  super(context, data, resource, from, to);
  // TODO 自動生成されたコンストラクター・スタブ
  // this.context = context;
  this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  this.listData = data;
 }

 public View getView(final int position, View convertView, ViewGroup parent) {
  final ViewHolder holder;

  // ビューを受け取る
  View view = convertView;

  if (view == null) {
   view = inflater.inflate(R.layout.row, parent, false);
   // LayoutInflater inflater = (LayoutInflater)
   // context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
   // view = inflater.inflate(R.layout.raw, null);

   holder = new ViewHolder();
   holder.line1 = (TextView) view.findViewById(android.R.id.text1);
   holder.line2 = (TextView) view.findViewById(android.R.id.text2);

   view.setTag(holder);
  } else {
   holder = (ViewHolder) view.getTag();
  }

  String text1 = ((HashMap<?, ?>) listData.get(position)).get("title").toString();
  String text2 = ((HashMap<?, ?>) listData.get(position)).get("comment").toString();
  holder.line1.setText(text1);
  holder.line2.setText(text2);

  Button btn = (Button) view.findViewById(R.id.button1);
  btn.setTag(position);
  
  btn.setOnClickListener(new OnClickListener() {
   @Override
   public void onClick(View arg0) {
    // TODO 自動生成されたメソッド・スタブ
    Log.v("buttonクリック", "ポジション: " + position);
    if(holder.line2.getVisibility() == android.view.View.GONE){
     holder.line2.setVisibility(View.VISIBLE);
    }else
    holder.line2.setVisibility(View.GONE);
   }
  });
 
  return view;
 }
}
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="match_parent"
    android:orientation="vertical" >

    <ListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>

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

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

        <TextView
            android:id="@android:id/text1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="TextView"
            android:textSize="18dp" />

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button" />

    </LinearLayout>
 
    <TextView
        android:id="@android:id/text2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="TextView" >
    </TextView>
 
</LinearLayout>


2013年7月17日水曜日

GPSを利用する

AndroidManifest.xmlにパーミッションを設定する。

GPSによる位置情報利用
<uses-permission android:name=”android.permission.ACCESS_FINE_LOCATION”/>

ネットワークによる位置情報利用
<uses-permission android:name=”android.permission.ACCESS_COARSE_LOCATION”/>

ロケーションマネージャーのインスタンスを取得
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

GPSの状態を取得する
locationManager.addGpsStatusListener(this);
 /*
  * Listener
  * GPS の状態が通知されるメソッド
  */
 @Override
 public void onGpsStatusChanged(int event) {
  // TODO 自動生成されたメソッド・スタブ
  String status = "";
  if (event == GpsStatus.GPS_EVENT_FIRST_FIX) {
   status = "FIRST FIX:初めて位置情報を確定した:";
  } else if (event == GpsStatus.GPS_EVENT_SATELLITE_STATUS) {
   status = "SATELLITE STATUS:GPSが位置情報を取得中";
  } else if (event == GpsStatus.GPS_EVENT_STARTED) {
   status = "STARTED:GPSを使い位置情報の取得を開始した";
  } else if (event == GpsStatus.GPS_EVENT_STOPPED) {
   status = "STOPPED:GPSの位置情報取得が終了した";
  }
  Log.d("onGpsStatusChanged", status);
 }


利用できるプロバイダの一覧表示
List<String> providers = locationManager.getAllProviders();
  for (String provider : providers) {
   Log.d("providers", provider);
  }

実行結果:
07-17 12:55:05.809: D/providers(2053): network
07-17 12:55:05.809: D/providers(2053): passive
07-17 12:55:05.809: D/providers(2053): gps

gps(GPS, AGPS)
人工衛星より位置情報を取得する。
建物の中や、高い建物付近だとGPSが遮られて位置を取得できない。
バッテリー消費大。高精度。

network (AGPS, CellID, Wifi MACID)
携帯端末の基地局や接続しているWifiから位置情報を特定する。
バッテリー消費中。中精度。 

passive(CellID, Wifi MACID)
位置情報取得設定が全てオフの場合実行される。
network との違いは、AGPSを使用しない事。
バッテリー消費小。低精度

条件を指定して最適なプロバイダを取得する。
  Criteria criteria = new Criteria();
  criteria.setAccuracy(Criteria.ACCURACY_LOW);//細かい位置精度
/*  criteria.setBearingRequired(false); // 方位不要
  criteria.setSpeedRequired(false); // 速度不要
  criteria.setAltitudeRequired(false); // 高度不要
*/  
  String provider = locationManager.getBestProvider(criteria, true); 
  Log.d("getBestProvider", provider);//gps

プロバイダの状態を表示する
  List<String> providers = locationManager.getAllProviders();
    for (String provider : providers) {
    boolean status = locationManager.isProviderEnabled(provider);
    Log.d("providers", provider + "::" + status);
  }
表示結果:
07-17 13:25:37.829: D/providers(2297): network::false
07-17 13:25:37.830: D/providers(2297): passive::true
07-17 13:25:37.831: D/providers(2297): gps::true

使えるプロバイダを取得する場合
List<String> providers = locationManager.getProviders(true);


アプリのインストール場所を指定


android:installLocation="internalOnly"
内部メモリーに保存される。

android:installLocation="auto"
内部メモリーに保存するか、外部に保存するか自動的に決まります。
ユーザー自身で内部と外部への移動が可能。
android:installLocation="preferExternal"
外部メモリーに保存します。
ユーザー自身で内部と外部への移動が可能です。
外部メモリーがいっぱいだと、内部メモリーに保存される。

2013年6月3日月曜日

AdMob の受取口座の登録のメモ

英語で登録

ゆうちょ銀行の「海外の銀行からの送金」をみて、
英語表記の例を見ながら入力する。

2013年3月21日木曜日

別クラスからViewの変更


package com.example.temp;

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

public class MainActivity extends Activity {

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

}

package com.example.temp;

import android.content.Context;
import android.widget.TextView;

public class vewChange {

 public vewChange(Context context) {
  // TODO Auto-generated constructor stub
  
  TextView tv = (TextView) ((com.example.temp.MainActivity) context).findViewById(R.id.textView1);
  tv.setText("change");
 }

}

別パターン
package com.example.temp;

import android.widget.TextView;

public class vewChange {

 public vewChange(MainActivity mainActivity) {
  // TODO Auto-generated constructor stub
  TextView tv = (TextView) mainActivity.findViewById(R.id.textView1);
  tv.setText("change");
 }
}



2013年3月19日火曜日

日にち計算


  Calendar calendar1 = Calendar.getInstance();
  calendar1.set(2013, 4, 1);//日時1を2013/04/01 に設定
 
  Calendar calendar2 = Calendar.getInstance();
  calendar2.set(2013, 4, 10);
  
  // 2つの日付の差を求める(ミリ秒)
  long difference = calendar2.getTime().getTime() - calendar1.getTime().getTime();
  
  // ミリ秒を変換して表示
  System.out.println("日付の差は" + difference / 1000 / 60 / 60 / 24 + "日です。");





2013年3月15日金曜日

EditTextの入力制限

InputFilter で正規表現を使って入力制限のサンプル

EditText の取得とInputFilter の設定
 EditText ed = (EditText)findViewById(R.id.editWeight);  
 InputFilter[] filters = { new MyFilter() };
 ed.setFilters(filters);

InputFilter
 public class MyFilter implements InputFilter {
   
     @Override
     public CharSequence filter(CharSequence source, int start, int end,
             Spanned dest, int dstart, int dend) {
  
      //入力文字を繋げる
         String destStr = dest.toString();
         String newValue = destStr.substring(0, dstart) + source + destStr.substring(dend);
         
         Log.v("ログ", "destStr::" + dest.toString());
         Log.v("ログ", "newValue::" + newValue);
  
         if (newValue.matches("^\\d{1,3}(\\.\\d|\\.)?$")) {
          //正規表現にマッチしている時に入力可
             return source;
         } else {
             return "";
         }
     }
  
 }

入力可能な値は
三桁までの数値で小数点以下一桁

考察:最後が.で終わってしまった時の処理
フォーカスが去った時に.を削除するか0を追加する。


【参考】正規表現
便利なサイト:http://regexpal.com/


2013年3月13日水曜日

custom view をScrollView に表示

うまくいかない。
修正前のソースコード
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

public class testView extends View {

 public testView(Context context, AttributeSet attrs) {
  super(context);
  setFocusable(true);
  Log.v("testVire", "testVire(Context context");
 }

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

  // 通常はグラフィックを描画するコードをここに記述する。
  canvas.drawColor(Color.BLUE);

  Paint paint = new Paint();
  Bitmap bitmap = Bitmap.createBitmap(200, 500, Bitmap.Config.ARGB_8888);
  Canvas bitmapCanvas = new Canvas(bitmap);

  paint.setColor(Color.RED);
  bitmapCanvas.drawColor(Color.BLACK);
  bitmapCanvas.drawCircle(50, 50, 40, paint);
  canvas.drawBitmap(bitmap, 10, 10, null);

  Log.v("testVire", "onDraw");
 }
}




修正後のソースコード
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

public class testView extends View {
 
 public testView(Context context, AttributeSet attrs) {
  super(context);
  setFocusable(true);
  Log.v("testVire", "testVire(Context context");
 }
 
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     setMeasuredDimension(200, 500);
     Log.v("testVire", "onMeasure" + widthMeasureSpec);
 }
 

 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  
  // 通常はグラフィックを描画するコードをここに記述する。
  canvas.drawColor(Color.BLUE);
  
  Paint paint = new Paint();
  Bitmap bitmap = Bitmap.createBitmap(200, 500, Bitmap.Config.ARGB_8888);
  Canvas bitmapCanvas = new Canvas(bitmap);
  
  paint.setColor(Color.RED);
  bitmapCanvas.drawColor(Color.BLACK);
  bitmapCanvas.drawCircle(50, 50, 40, paint);
  canvas.drawBitmap(bitmap, 10, 10, null);
  
  Log.v("testVire", "onDraw");
 }
}

onMeasureメソッドを追加した

なぜか、XMLレイアウト画面でドラッグして追加できなくなった。