私の Android アプリには、スプラッシュ画面があり、ログイン画面が表示されます。ユーザーがログインすると、ウェルカム画面が表示されます。私のアプリは Samsung Galaxy S3 で頻繁にクラッシュするため、MAT でこれを調べることにしました。
ウェルカム画面でヒープ ダンプを取得したところ、メモリ内にスプラッシュ オブジェクトが表示されています。以下にコードを掲載しました。このメモリリークの原因は何ですか?
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.TextView;
public class SplashActivity extends CoreActivity implements ConnectionCallBack{
private static final String TAG = SplashActivity.class.getSimpleName();
private static final int LOGIN_SCREEN = 0;
protected static final String SPL = SplashActivity.class.getSimpleName();
private int SHOW_MESSAGE = 1;
private Timer timer;
private TextView connectionNotificationTV;
private int notificationCount = 0;
private Handler handler;
TimerTask timerTask;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splashscreen);
Globals.appContext = getApplicationContext();
connectionNotificationTV = (TextView) findViewById(R.id.splash_screen_connection_notification_TV);
handler = new Handler(){
public void handleMessage(Message msg) {
if(msg.what == SHOW_MESSAGE){
if(notificationCount == 0){
connectionNotificationTV.setVisibility(View.VISIBLE);
}else if(notificationCount == 1){
confirmationDialog();
}
notificationCount++;
}else if(msg.what == LOGIN_SCREEN){
loadNext(LOGIN_SCREEN);
}
};
};
LocationDisplay location = new LocationDisplay(getApplicationContext());
ConnectionCheckThread newConnectionThread = new ConnectionCheckThread(this);
newConnectionThread.start();
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
if(notificationCount == 0){
handler.sendEmptyMessage(SHOW_MESSAGE);
}
}
}, 30000);
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Utils.unbindDrawables(findViewById(R.id.root));
}
private void setScreenDimension(){
int screenHeight = getWindowManager().getDefaultDisplay().getHeight();
int screenWidth = getWindowManager().getDefaultDisplay().getWidth();
GeneralSettings.getInstance().setScreenHeight(screenHeight);
GeneralSettings.getInstance().setScreenWidth(screenWidth);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK){
System.exit(0);
return true;
}
return super.onKeyDown(keyCode, event);
}
public void confirmationDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.connection_error_title);
builder.setMessage(R.string.connection_error_message);
builder.setPositiveButton(R.string.connection_error_close_btn, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
System.exit(0);
}
});
builder.setCancelable(false);
builder.show();
}
@Override
public void loadNext(int code) {
if(code == LOGIN_SCREEN){
Intent intent = new Intent(SplashActivity.this,LoginActivity.class);
startActivity(intent);
finish();
}
}
@Override
public void loadPrev() {
}
@Override
public void onReceivedConnection(int returnCode) {
if(returnCode == ConnectionCheckThread.CONNECTION_TIMEOUT ||
returnCode == ConnectionCheckThread.UNKNOWN_HOST ||
returnCode == ConnectionCheckThread.UNKNOWN_ERROR){
handler.sendEmptyMessage(SHOW_MESSAGE);
}else if(returnCode == ConnectionCheckThread.CONNECTION_SUCCESS){
handler.sendEmptyMessage(LOGIN_SCREEN);
}
}
}
スレッド クラスのコードは次のとおりです。
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.AlertDialog;
import android.content.Context;
import android.os.Handler;
public class ConnectionCheckThread extends Thread{
private static final String TAG = ConnectionCheckThread.class.getSimpleName();
private ConnectionCallBack callback;
//private HttpURLConnection http = null;
//private InputStream is;
//private boolean isFirstTime = true;
public static int CONNECTION_TIMEOUT = 200;
public static int UNKNOWN_HOST = 201;
public static int UNKNOWN_ERROR = 202;
public static int CONNECTION_SUCCESS = 203;
public static int CONNECTION_FAILURE = 204;
// private int returnCode;
// private int retryCount = 0;
Context context;
public ConnectionCheckThread(Context con){
this.context = con;
this.callback = (ConnectionCallBack)con;
}
public void run(){
HttpURLConnection http = null;
boolean isFirstTime = true;
String urlString = "http://www.google.com/";
int returnCode = 0;
int retryCount = 0;
do{
try {
URL urls = new URL(urlString);
http = (HttpURLConnection)urls.openConnection();
int responsecode = http.getResponseCode();
System.out.println("responsecode = "+responsecode);
if(isFirstTime){
http.setConnectTimeout(30000);
}else{
http.setConnectTimeout(15000);
}
http.connect();
InputStream is = http.getInputStream();
returnCode = CONNECTION_SUCCESS;
} catch (java.net.SocketException ex) {
ex.printStackTrace();
Utils.log(TAG, "caught SocketException[" + ex.getMessage() + "]");
returnCode = CONNECTION_TIMEOUT;
} catch (java.net.SocketTimeoutException ex) {
ex.printStackTrace();
Utils.log(TAG, "caught SocketTimeoutException[" + ex.getMessage() + "]");
returnCode = CONNECTION_TIMEOUT;
} catch (java.net.UnknownHostException ex) {
ex.printStackTrace();
Utils.log(TAG, "caught UnknownHostException[" + ex.getMessage() + "]");
returnCode = UNKNOWN_HOST;
} catch (Exception e) {
e.printStackTrace();
Utils.log(TAG, "Exception in WebRequest Thread :" + e.getMessage());
returnCode = UNKNOWN_ERROR;
} finally {
try {
if (http != null) {
http.disconnect();
http = null;
}
} catch (Exception e) {
e.printStackTrace();
}
callback.onReceivedConnection(returnCode);
if(retryCount == 0){
isFirstTime = false;
}
retryCount++;
}
}while(retryCount <= 1 && returnCode != CONNECTION_SUCCESS);
}
Handler handler2 = new Handler(){
public void handleMessage(android.os.Message msg) {
if(msg.what == CONNECTION_FAILURE){
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle(context.getResources().getString(R.string.login_no_network_title));
alert.setMessage(context.getResources().getString(R.string.login_no_network_content));
alert.show();
}
};
};
}