私の問題は、閉じたアクティビティの onCreate() と onPause() が呼び出されるべきではないときに呼び出されることです。
私は私が呼び出す開始アクティビティ:
Intent intent = new Intent(this, SelectTransportActivity.class);
startActivity(intent);
this.finish();
SelectTransport アクティビティを開始したいとき。
しかし、SelectTransport アクティビティから Stop アクティビティを開始したいときに呼び出します。
Intent i = new Intent(this, StopActivity.class);
startActivity(i);
this.finish();
デバッガーで、Start アクティビティの onCreate() が Stop アクティビティの開始前に呼び出されていることを確認できます。
同様に、Stop アクティビティを終了すると、Start アクティビティの onPause() が呼び出され、その後 Start アクティビティが開始されます。
開始アクティビティで onCreate() と onPause() が呼び出されるべきではないのに、他のアクティビティから呼び出され、アクティビティを終了したのはなぜですか?
マニフェスト:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.greenenergy"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<!-- Launching -->
<uses-permission android:name="android.permission.BATTERY_STATS" />
<!-- All probes -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- Storage -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Location probe -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:name=".GreenEnergyApplication">
<service android:name="edu.mit.media.funf.FunfManager" >
<meta-data
android:name="default"
android:value="@string/default_pipeline" />
</service>
<receiver
android:name="edu.mit.media.funf.Launcher"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.BATTERY_CHANGED" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.DOCK_EVENT" />
<action android:name="android.intent.action.ACTION_SCREEN_ON" />
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
<activity
android:name="com.example.greenenergy.StartupActivity"
android:screenOrientation="portrait"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.greenenergy.StartActivity"
android:screenOrientation="portrait"
android:label="@string/title_activity_start" >
</activity>
<activity
android:name="com.example.greenenergy.WaysActivity"
android:screenOrientation="portrait"
android:label="@string/title_activity_ways" >
</activity>
<activity
android:name="com.example.greenenergy.StopActivity"
android:screenOrientation="portrait"
android:label="@string/title_activity_stop">
</activity>
<activity
android:name="com.example.greenenergy.StatisticsActivity"
android:screenOrientation="portrait"
android:label="@string/title_activity_statistics">
</activity>
</application>
開始アクティビティ:
public class StartActivity extends BaseActivity implements OnClickListener {
private Button bStart, bStats;
Controller controller;
GPSCollectorSingleton gpsCollectorSingleton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
autoDetect();
}
private void init() {
setContentView(R.layout.activity_main);
bStart = (Button) findViewById(R.id.bStart);
bStats = (Button) findViewById(R.id.bStatisticsStart);
bStart.setOnClickListener(this);
bStats.setOnClickListener(this);
controller = new Controller(); // Init controller
Database database = new Database(getApplicationContext());
controller.controlDatabase(database);
controller.createTable(); // Create table if not exist
gpsCollectorSingleton = GPSCollectorSingleton.getInstance(); // Init model
// Bind to the service, to create the connection with FunfManager
getApplicationContext().bindService(new Intent(this, FunfManager.class), funfManagerConn, BIND_AUTO_CREATE);
}
private void autoDetect() {
boolean auto = ((GreenEnergyApplication) getApplication()).getAutoPreference(getApplicationContext());
boolean started = ((GreenEnergyApplication) getApplication()).getStartPreference(getApplicationContext());
if (auto && !started) {
controller.enableAutoDetection(getApplicationContext(), gpsCollectorSingleton);
}
}
@Override
protected void onPause() {
super.onPause();
this.finish();
}
@Override
public void onClick(View v) {
Intent intent;
switch (v.getId()) {
case R.id.bStart:
startDataCollector();
break;
case R.id.bStatisticsStart:
intent = new Intent(this, StatisticsActivity.class);
startActivity(intent);
break;
}
}
private void startDataCollector() {
if (((GreenEnergyApplication) getApplication()).getStartPreference(getApplicationContext()) == false) {
controller.datahandlerObserver(getApplicationContext(), gpsCollectorSingleton); // Observer
((GreenEnergyApplication) getApplication()).setStartPreference(getApplicationContext(), true);
}
Intent intent = new Intent(this, WaysActivity.class);
startActivity(intent);
}
}
SelectTransport アクティビティ:
public class SelectTransportActivity extends BaseActivity implements OnItemClickListener {
GridView gridview;
private static int DATABASE_ID_OFFSET = 2;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ways);
gridview = (GridView) findViewById(R.id.gridview);
gridview.setAdapter(new ImageAdapter(this));
gridview.setOnItemClickListener(this);
}
@Override
protected void onPause() {
super.onPause();
this.finish();
}
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
((GreenEnergyApplication)getApplication()).setTransportationPreference(getApplicationContext(), arg2+DATABASE_ID_OFFSET);
Log.i("WayActivity",
"ARG0: " + arg0.toString() + " Arg1: " + arg1.toString() + " "
+ " Arg2: " + arg2 + " Arg3: " + arg3);
Intent i = new Intent(this, StopActivity.class);
startActivity(i);
}
}
停止アクティビティ:
public class StopActivity extends StartActivity implements OnClickListener, Observer {
Button stopButton, statsButton;
TextView statusTextView;
int distance, time, transportTypeEstimate, transportType;
int sessionStartTime = 0;
int sessionStartDistance = 0;
GPSCollectorSingleton gpsCollectorSingleton;
LocationData location;
boolean transportEstimation;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GPSCollectorSingleton gps = GPSCollectorSingleton.getInstance();
if (((GreenEnergyApplication) getApplication()).getStartPreference(getApplicationContext()) == false) {
Log.i("STOP - STOP", "hasspeed");
stopDataCollector();
}
setContentView(R.layout.activity_stop);
stopButton = (Button) findViewById(R.id.bStop);
statsButton = (Button) findViewById(R.id.bStatisticsStop);
statusTextView = (TextView) findViewById(R.id.tvStatus);
stopButton.setOnClickListener(this);
statsButton.setOnClickListener(this);
gpsCollectorSingleton = GPSCollectorSingleton.getInstance(); // Init model
gpsCollectorSingleton.addObserver(this); // Observe on models state
initTransportTypeDetection();
}
/**
* Initializes estimating of transport type or manually chosen transport type
*/
private void initTransportTypeDetection() {
transportType = ((GreenEnergyApplication) getApplication())
.getTransportationPreference(getApplicationContext());
transportTypeEstimate = transportType;
if (transportType == TransportationDefinerSingleton.TRANSPORT_UNKNOWN) { // Start transport type estimation
TransportationDefinerSingleton transport = TransportationDefinerSingleton.getInstance(); // Get model
transport.addObservable(gpsCollectorSingleton); // Add observer for estimating transport type
transportEstimation = true;
} else { // Transport type manually specified
setSessionStartDistanceAndTime();
transportEstimation = false;
}
}
private void setSessionStartDistanceAndTime() {
Controller controller = new Controller();
Database database = new Database(getApplicationContext());
controller.controlDatabase(database);
sessionStartDistance = controller.getDistanceFromID(transportType);
sessionStartTime = controller.getTimeFromID(transportType);
}
@Override
public void onClick(View v) {
Intent intent;
switch (v.getId()) {
case R.id.bStop:
stopDataCollector();
break;
case R.id.bStatisticsStop:
intent = new Intent(this, StatisticsActivity.class);
startActivityForResult(intent, -1);
break;
}
}
private void stopDataCollector() {
((GreenEnergyApplication) getApplication()).setTransportationPreference(getApplicationContext(),
TransportationDefinerSingleton.TRANSPORT_UNKNOWN);
((GreenEnergyApplication) getApplication()).setStartPreference(getApplicationContext(), false);
gpsCollectorSingleton.deleteObservers(); // Delete all observers
Controller controller = new Controller();
Database database = new Database(getApplicationContext());
controller.controlDatabase(database);
// Get unknown data. From estimate of transport type or data collected while deciding transport type.
int distance = controller.getDistanceFromID(TransportationDefinerSingleton.TRANSPORT_UNKNOWN);
int time = controller.getTimeFromID(TransportationDefinerSingleton.TRANSPORT_UNKNOWN);
if (transportEstimation) { // Estimate
controller.updateTable(transportTypeEstimate, distance, time);
} else { // Manually chosen transport type
controller.updateTable(transportType, distance, time);
}
controller.resetTable(TransportationDefinerSingleton.TRANSPORT_UNKNOWN);
Intent intent = new Intent(this, StartActivity.class);
startActivity(intent);
this.finish();
}
@Override
public void update(Observable observable, Object data) {
Controller controller = new Controller();
Database database = new Database(getApplicationContext());
controller.controlDatabase(database);
transportTypeEstimate = getTransportType();
distance = controller.getDistanceFromID(transportType) - sessionStartDistance;
time = controller.getTimeFromID(transportType) - sessionStartTime;
location = (LocationData) data;
runOnUiThread(new Runnable() {
@Override
public void run() {
String transportName = getTransportName(transportTypeEstimate);
statusTextView.setText("Transport type: " + transportName + " Distance: " + distance + " Time: " + time
+ "\nTimeStamp: " + location.getTime() + "\nSpeed: " + location.getSpeed()
+ " Seconds since last: " + location.getSecondsSinceLastSample());
}
});
}
private int getTransportType() {
if (transportEstimation) {
TransportationDefinerSingleton transport = TransportationDefinerSingleton.getInstance();
Controller controller = new Controller();
controller.controlTransportationDefinerSingleton(transport);
transportTypeEstimate = controller.getTransportType();
}
return transportTypeEstimate;
}
private String getTransportName(int type) {
switch (type) {
case TransportationDefinerSingleton.TRANSPORT_UNKNOWN:
return "Unknown";
case TransportationDefinerSingleton.TRANSPORT_WALK:
return "Walking";
case TransportationDefinerSingleton.TRANSPORT_BIKE:
return "Bike";
case TransportationDefinerSingleton.TRANSPORT_CAR:
return "Car";
case TransportationDefinerSingleton.TRANSPORT_BUS:
return "Bus";
case TransportationDefinerSingleton.TRANSPORT_TRAIN:
return "Train";
case TransportationDefinerSingleton.TRANSPORT_MOTORCYCLE:
return "Motor Cycle";
case TransportationDefinerSingleton.TRANSPORT_CARPOOL:
return "Carpool";
}
return "";
}
}
他のアクティビティのスーパークラスである Base アクティビティ。オプションメニューとその他の基本的なものを設定するだけです。
public class BaseActivity extends Activity {
private Controller controller;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GPSCollectorSingleton gpsCollectorSingleton = GPSCollectorSingleton.getInstance(); // Init model
controller = new Controller();
controller.controlGPSCollectorSingleton(gpsCollectorSingleton); // Init controller
}
protected ServiceConnection funfManagerConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("OnServiceConnected", "MainActivity");
controller.onServiceConnected(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
controller.onServiceDisconnected();
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
disableService();
closeActivity();
return true;
case R.id.action_clear:
Database database = new Database(getApplicationContext());
database.dropTable();
return true;
case R.id.action_toggle_auto:
if (item.isChecked()) {
item.setChecked(false);
((GreenEnergyApplication) getApplication()).setAutoPreference(getApplicationContext(), false);
} else {
item.setChecked(true);
((GreenEnergyApplication) getApplication()).setAutoPreference(getApplicationContext(), true);
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
if (((GreenEnergyApplication) getApplication()).getAutoPreference(getApplicationContext()) == true) {
menu.findItem(R.id.action_toggle_auto).setChecked(true);
}
return true;
}
/**
* Disables the service and the pipeline
*/
private void disableService() {
controller.disablePipeline(); // Disable pipeline
boolean isBound = false;
isBound = getApplicationContext().bindService(new Intent(getApplicationContext(), FunfManager.class),
funfManagerConn, BIND_AUTO_CREATE);
if (isBound) {
getApplicationContext().unbindService(funfManagerConn); // Disable
// service
}
}
private void closeActivity() {
this.finish();
}
}