2つのウィンドウでアプリを作成します。メインウィンドウから設定に移動すると、すべて問題ありませんが、メインアクティビティに戻ろうとすると、スレッドが既に開始されているというエラーでアプリがクラッシュします。
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new GameView(this));
startService(new Intent(this, MyService.class));
}
public void onResume(){
super.onResume();
}
// Initiating Menu XML file (menu.xml)
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.layout.menu, menu);
return true;
}
public void onBackPressed() {
super.onBackPressed();
stopService(new Intent(this, MyService.class));
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
更新:LogCatからのログは次のとおりです(私はEclipseを使用しています):
09-30 11:59:17.348: D/AndroidRuntime(2917): Shutting down VM
09-30 11:59:17.348: W/dalvikvm(2917): threadid=1: thread exiting with uncaught exception (group=0x40aa7210)
09-30 11:59:17.368: E/AndroidRuntime(2917): FATAL EXCEPTION: main
09-30 11:59:17.368: E/AndroidRuntime(2917): java.lang.IllegalThreadStateException: Thread already started.
09-30 11:59:17.368: E/AndroidRuntime(2917): at java.lang.Thread.start(Thread.java:1045)
09-30 11:59:17.368: E/AndroidRuntime(2917): at com.examples.todolist.GameView$1.surfaceCreated(GameView.java:45)
ManiFestファイル(それからのアクティビティ):
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<service
android:name="MusicService"
android:enabled="true">
</service>
<activity
android:name=".MainActivity"
android:label="@string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="PreferencesActivity"></activity>
<service android:enabled="true" android:name=".MyService" />
</application>
私のプロジェクトには、MainActivity.java(メインウィンドウ)、PreferencesActivity.java(設定ウィンドウ)、GameView.java(描画を担当)、GameManager.java(FPSを制御)があります。ゲームビューでは、メインイベント、onDrawイベント、onTouchイベントがあります。GameViewのメインは次のとおりです。
public GameView(Context context) {
super(context);
gameLoopThread = new GameManager(this);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
gameLoopThread.setRunning(false);
while (retry) {
try {
gameLoopThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
bmp = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
bmp1 = BitmapFactory.decodeResource(getResources(),
R.drawable.wall_sprite);
}
これがgameManager.javaです。これは、実行と関係があることがわかったためです。私はまだスレッド(またはスクリーン?)を破壊してから再び作る方法を理解しようとしています。
パブリッククラスGameManagerはスレッドを拡張します{
static final long FPS = 30;
private GameView view;
private boolean running = false;
// class constructor
public GameManager(GameView view) {
this.view = view;
}
public void setRunning(boolean run) {
running = run;
}
public void run() {
long ticksPS = 1000 / FPS;
long startTime;
long sleepTime;
while (running) {
Canvas c = null;
startTime = System.currentTimeMillis();
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
view.onDraw(c);
}
} finally {
if (c != null) {
view.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = ticksPS - (System.currentTimeMillis() - startTime);
try {
if (sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
} catch (Exception e) {
}
}
}
}