我有一个带有edittexts的表单和一个按钮来调用相机(返回一个放入imageview的位图)......从纵向模式我输入所有edittext文件,然后单击将我转发到的相机按钮相机 - 在相机中,我在返回到活动 1 后拍照(保持纵向 - 并且所有编辑文本字段都恢复onRestoreInstanceState()
) - 活动 1 的最后一个回调方法是onResume()
(没关系) - 但问题当我从纵向模式更改为横向模式时出现 - 回调方法如下
所以最后一个回调方向变化是onPause()
. 我不懂为什么?问题是 onSaveInstanceState 在 onPause 之前被调用 - 所以当我回到纵向模式时,一切都将是空的(edittexts,imageview ..) - 这种奇怪的行为在每次方向更改时都会继续(最后调用 onPause() )。
我确信这个问题与拍摄图像(startInentforResult ....)有关,因为一切(编辑文本字段)在拍摄图像之前在方向改变上都可以正常工作......有时我也可以拍摄图像并且它有效很好,但在大多数情况下不是...
所以我的问题是,是什么“驱动”我的 Activity 到onPause()
方法而不是onResume()
?
谢谢,如果有人知道解决方案,我将不胜感激,因为我已经为此苦苦挣扎了几天并且找不到解决方案。
该项目有很多类,但这是活动代码(需要注意的是,只有当我从相机应用程序拍摄图像时才会出现问题,之后活动生命周期变得疯狂 - 这个活动也是从主活动中调用的,带有'startIntentforResult ()'。我不使用 'android:configChanges="orientation|keyboardHidden"' 来停止娱乐):
public class NewCounterActivity extends Activity {
Button btnCreate;
Button btnCancel;
Button btnTakeImg;
ImageView counterImgView;
CheckBox existsDamage;
EditText inputNameFirst;
EditText inputNameLast;
EditText inputAdresse;
EditText inputCounterID;
EditText inputCounterValue;
EditText inputDescription;
TextView registerErrorMsg;
DatabaseHandler db;
//Data to be submitted
String nameFirst;
String nameLast;
String adresse;
String counterID;
String counterValue;
String countDescript;
String existsDmg;
Bitmap counterBitmap;
Bitmap recievedBitmap;
String longitude;
String latitude;
LocationTracker gps;
// JSON Response node names
private static String KEY_SUCCESS = "success";
private static String KEY_ERROR = "error";
private static String KEY_ERROR_MSG = "error_msg";
//The dimensions of the ImageView
int targetW;
int targetH;
// Some lifecycle callbacks so that the image can survive orientation change
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.e("onSaveInstanceState", "fadsfass");
outState.putParcelable("bitmap", counterBitmap);
outState.putString("fname", inputNameFirst.getText().toString());
outState.putString("lname", inputNameLast.getText().toString());
outState.putString("adrese", inputAdresse.getText().toString());
outState.putString("cID", inputCounterID.getText().toString());
outState.putString("cValue", inputCounterValue.getText().toString());
outState.putString("Descript", inputDescription.getText().toString());
outState.putString("ErrorMsg", registerErrorMsg.getText().toString());
outState.putBoolean("damageCheck", existsDamage.isChecked());
((MyApplicationClass) getApplication()).detach(this);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Log.e("onRestoreInstanceState", "fadsfass");
counterBitmap = savedInstanceState.getParcelable("bitmap");
counterImgView.setImageBitmap(counterBitmap);
inputNameFirst.setText(savedInstanceState.getString("fname"));
inputNameLast.setText(savedInstanceState.getString("lname"));
inputAdresse.setText(savedInstanceState.getString("adrese"));
inputCounterID.setText(savedInstanceState.getString("cID"));
inputCounterValue.setText(savedInstanceState.getString("cValue"));
inputDescription.setText(savedInstanceState.getString("Descript"));
registerErrorMsg.setText(savedInstanceState.getString("ErrorMsg"));
existsDamage.setChecked(savedInstanceState.getBoolean("damageCheck"));
((MyApplicationClass) getApplication()).attach(this);
}
@Override
public void onContentChanged() {
// TODO Auto-generated method stub
super.onContentChanged();
Log.e("onContetnChanged", "fadsfass");
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.e("onDestroy", "fadsfass");
}
@Override
public void onDetachedFromWindow() {
// TODO Auto-generated method stub
super.onDetachedFromWindow();
Log.e("onDetachedFromWindow", "fadsfass");
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
Log.e("onPause", "fadsfass");
}
@Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
Log.e("onRestart", "fadsfass");
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
Log.e("onResume", "fadsfass");
}
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Log.e("onStart", "fadsfass");
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
Log.e("onStop", "fadsfass");
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.newcounteractivity_layout);
Log.e("onCreate", "mActivity equals NULL");
inputNameFirst = (EditText) findViewById(R.id.createFirstName);
inputNameLast = (EditText) findViewById(R.id.createLastName);
inputAdresse = (EditText) findViewById(R.id.createAdresse);
inputCounterID = (EditText) findViewById(R.id.createCounterID);
inputCounterValue = (EditText) findViewById(R.id.createCounterValue);
inputDescription = (EditText) findViewById(R.id.createDescription);
registerErrorMsg = (TextView) findViewById(R.id.create_error);
btnCreate = (Button) findViewById(R.id.btnCreate);
btnCancel = (Button) findViewById(R.id.btnCancel);
btnTakeImg = (Button) findViewById(R.id.btnImage);
counterImgView = (ImageView) findViewById(R.id.counterImgView);
existsDamage = (CheckBox) findViewById(R.id.createDamageExists);
//REGISTER BUTTON CLICK EVENTS
btnCreate.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//new DoBackgroundTask(NewCounterActivity.this).execute();
//CounterUser data to submit
nameFirst = inputNameFirst.getText().toString().trim();
nameLast = inputNameLast.getText().toString().trim();
adresse = inputAdresse.getText().toString().trim();
counterID = inputCounterID.getText().toString().trim();
counterValue = inputCounterValue.getText().toString().trim();
countDescript = inputDescription.getText().toString().trim();
existsDmg = Integer.toString((existsDamage.isChecked()) ? 1 : 0);
// create LocationTracker class object
gps = new LocationTracker(NewCounterActivity.this);
if(!gps.canGetLocation()){
gps.stopUsingGPS();
gps.showSettingsAlert();
//Ovo se mozda treba i izbaciti
gps.getLocation();
}
else{
processInput();
}
}
});
btnCancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent returnIntent = new Intent();
setResult(RESULT_CANCELED, returnIntent);
finish();
}
});
btnTakeImg.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(isIntentAvailable(NewCounterActivity.this, MediaStore.ACTION_IMAGE_CAPTURE)){
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takePictureIntent,2);
}
else {
Toast.makeText(NewCounterActivity.this, "No Camera Available", Toast.LENGTH_SHORT).show();
}
}
});
}
/************************************************************************************************
* Methods used in this class
* */
public void processInput(){
//Get current Longitude and Latitude
longitude = Double.toString(gps.getLongitude());
latitude = Double.toString(gps.getLatitude());
//Na kraju iskljuci location updatese - ne moze na emulatru jer ja emit coordinate preko DDMS... a kad emit on mora biti ukljucen da bi primio
//gps.stopUsingGPS();
Toast.makeText(getApplicationContext(), "Your Location is - \nLat: " + longitude + "\nLong: " + latitude, Toast.LENGTH_LONG).show();
if (!nameFirst.equals("") && !nameLast.equals("") && !adresse.equals("") && !counterID.equals("") && !counterValue.equals("")
&& counterBitmap != null ){
new DoBackgroundTask(NewCounterActivity.this).execute();
}
else{
// Not all fields are filled
registerErrorMsg.setText("Not all fields are filled");
}
}
//Method to check whether an app can handle your intent
public boolean isIntentAvailable(Context context, String action) {
final PackageManager packageManager = context.getPackageManager();
final Intent intent = new Intent(action);
List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}
/**************************************************************************************************
*
* When the calling activity, Activity #1, resumes after having called another activity, Activity #2, using startActivityForResult,
* the method onActivityResult in Activity #1 is called BEFORE onResume.
* This is important to know if you are instantiating your SQLite Database objects from within onResume in Activity #1. If so, you will also need to instantiate the object from within onActivityResult,
* when returning from Activity #2.
*
* startActivityForResult() is asynchronous. It can feel synchronous to the user since the UI will change and your calling activity will be paused
* (your onPause() method will be called).
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
Log.e("onActivityResult", "fadsfass");
if (requestCode == 2) {
if(resultCode == RESULT_OK){
Bundle extras = data.getExtras();
recievedBitmap = (Bitmap) extras.get("data");
}
if (resultCode == RESULT_CANCELED) {
Toast.makeText(NewCounterActivity.this, "No Image Taken", Toast.LENGTH_SHORT).show();
}
}
}
/**
* Koristim onWindowFocusChanged jer kad se vratim na Activity 1 onda dodje do potpunog recreate Activitija i getWidth()/height() ne mogu dobiti
* ni u jednom od lifecicle methoda - naime ide start onCreate,...onActivityResult(), onResume() - u onactivityResult izvadim bitmap i pohranim ga u receivedBitmap
* te kad getWidth() postane dostupan system invoke ovu dole methodu. :D
*/
@Override
public void onWindowFocusChanged(boolean hasFocus){
if(recievedBitmap != null){
targetW=counterImgView.getWidth();
targetH=counterImgView.getHeight();
Log.e("onWindowFocusChanged", "fadsfass" + " " + targetW + " " + targetH);
// http://stackoverflow.com/questions/4837715/how-to-resize-a-bitmap-in-android
// http://sunil-android.blogspot.com/2013/03/resize-bitmap-bitmapcreatescaledbitmap.html
// Scale or resize Bitmap to ImageView dimensions
counterBitmap = Bitmap.createScaledBitmap(recievedBitmap, targetW, targetH, false);
/**
* Canvas: trying to use a recycled bitmap android.graphics - This exception occurs when you try to recycle a bitmap which is already recycled.
* http://androdevvision.blogspot.com/2011/10/solution-for-out-of-memory-error-and.html
*/
if(recievedBitmap != null && !recievedBitmap.isRecycled()){
recievedBitmap.recycle();
recievedBitmap = null;
}
counterImgView.setImageBitmap(counterBitmap);
}
}
/************************************************************************************************
* Background AsyncTask to create new counterUser - https://github.com/callorico/CustomAsyncTask - najbolje radi
* new DoBackgroundTask(NewCounterActivity.this).execute();
* */
private static class DoBackgroundTask extends CustomAsyncTask<Void, Integer, JSONObject> {
private static final String TAG = "DoBackgroundTask";
private ProgressDialog mProgress;
private int mCurrProgress;
private NewCounterActivity myActivity = null;
public DoBackgroundTask(NewCounterActivity activity) {
super(activity);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
showProgressDialog();
}
@Override
protected void onActivityDetached() {
if (mProgress != null) {
mProgress.dismiss();
mProgress = null;
}
}
@Override
protected void onActivityAttached() {
showProgressDialog();
}
private void showProgressDialog() {
mProgress = new ProgressDialog(mActivity);
mProgress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgress.setIndeterminate(true);
mProgress.setMessage(" Saljem na server... ");
mProgress.setCancelable(true);
mProgress.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
cancel(true);
}
});
mProgress.show();
mProgress.setProgress(mCurrProgress);
}
@Override
protected JSONObject doInBackground(Void... params) {
//so you need to either pass an instance of the outer class to the inner class method (or its constructor) as a parameter,
//or create it inside the method.
JSONObject json = null;
if(mActivity != null){
myActivity = (NewCounterActivity) mActivity;
//Prepare counterBitmap as String
ByteArrayOutputStream stream = new ByteArrayOutputStream();
//Write a compressed version of the bitmap to the specified output stream.
myActivity.counterBitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream);
byte [] b_array = stream.toByteArray();
String bitmapString = Base64.encodeBytes(b_array);
//Get workerId from logged worker
Functions workerFunction = new Functions();
DatabaseHandler db = new DatabaseHandler(mActivity);
String workerID = db.retrieveWorker().get("workerId");
if(myActivity != null){
//Get JsonObject from Functions.java
json = workerFunction.newCounterUser(myActivity.counterID, myActivity.counterValue, myActivity.adresse, myActivity.nameFirst, myActivity.nameLast, bitmapString, myActivity.existsDmg, myActivity.countDescript, workerID, myActivity.longitude, myActivity.latitude);
}
}
return json;
}
@Override
protected void onPostExecute(JSONObject jsonObject) {
super.onPostExecute(jsonObject);
if (mActivity != null) {
mProgress.dismiss();
try {
if (jsonObject.getString(KEY_SUCCESS) != null) {
myActivity.registerErrorMsg.setText("");
String res = jsonObject.getString(KEY_SUCCESS);
if(Integer.parseInt(res) == 1){
// counterUser successfully registered
Toast.makeText(mActivity, "New counterUser is created", Toast.LENGTH_LONG).show();
// Return back to MainActivity
Intent returnIntent = new Intent();
returnIntent.putExtra("result",jsonObject.toString());
mActivity.setResult(RESULT_OK,returnIntent);
// Close all views before launching MainActivity
returnIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mActivity.finish();
}else{
// Error in registration
myActivity.registerErrorMsg.setText("Error occured in registration");
}
}
} catch (JSONException e) {
Log.e("Error","NO Json at all");
e.printStackTrace();
}
} else {
Log.d(TAG, "AsyncTask finished while no Activity was attached.");
}
}
}