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)