Android Paypal Integration: Sandbox to Production - java

I've tested my android app successfully using Paypal Sandbox environment. I am about to release my app, so want to change the paypal configuration to 'PRODUCTION'
To do this, I've changed the following for production:
private static final String CONFIG_ENVIRONMENT = PaymentActivity.ENVIRONMENT_PRODUCTION;
private static final String CONFIG_CLIENT_ID = "my client id for production";
private static final String CONFIG_RECEIVER_EMAIL = "live-id#gmail.com";
Now when I try to make a payment using my another paypal account, I am getting error:
Login Failed
System error. Please try again later.
Same thing happens using the emulator with production settings.
My question is do I have to make any other changes to move from sandbox to production env?
Thanks
UPDATE 1
All the above settings are for the 'production' environment.
Using direct payment

I've noticed problems using paypal from my app when I name the String before onCreate so what I did was..
//When you want to initiate payment...
public void onBuyPressed(View pressed) {
PayPalPayment thingToBuy = new PayPalPayment(new BigDecimal(valuez), "USD", iu);
PaymentActivity.ENVIRONMENT_LIVE);//etc
I dont know if "PRODUCTION" or "LIVE" makes a difference but give it a try.
I'm going to add more hope this helps this is what i did
get rid of all those paypal strings before onCreate and just when they get ready to pay have textbox with onClick is onBuyPressed...
public void onBuyPressed(View pressed) {
TextView inptP =(TextView)findViewById(R.id.WHATHEYAREBUYING);
String iu =inptP.getText().toString();
TextView inptt =(TextView)findViewById(R.id.WHATITCOST);
String it =inptt.getText().toString();
try{
double valuez =Double.parseDouble(it);
if(valuez> 0)
{
PayPalPayment thingToBuy = new PayPalPayment(new BigDecimal(valuez), "USD", iu);
Intent intent = new Intent(this, PaymentActivity.class);
TextView id =(TextView)findViewById(R.id.MYPAYPALID);
String uname = id.getText().toString();
TextView iz =(TextView)findViewById(R.id.MYPAYPALEMAIL);
String insane = iz.getText().toString();
TextView name =(TextView)findViewById(R.id.MYCUSTOMERSNAME);
String custname = name.getText().toString();
Time now = new Time();
now.setToNow();
// comment this line out for live or set to PaymentActivity.ENVIRONMENT_SANDBOX for sandbox
intent.putExtra(PaymentActivity.EXTRA_PAYPAL_ENVIRONMENT, PaymentActivity.ENVIRONMENT_LIVE);
// it's important to repeat the clientId here so that the SDK has it if Android restarts your
// app midway through the payment UI flow.
intent.putExtra(PaymentActivity.EXTRA_CLIENT_ID, uname);
// Provide a payerId that uniquely identifies a user within the scope of your system,
// such as an email address or user ID.
intent.putExtra(PaymentActivity.EXTRA_PAYER_ID, custname);
intent.putExtra(PaymentActivity.EXTRA_RECEIVER_EMAIL, insane);
intent.putExtra(PaymentActivity.EXTRA_PAYMENT, thingToBuy);
startActivityForResult(intent, 0);
}
else{
Toast.makeText(getApplicationContext(), "You haven't entered anything.",
Toast.LENGTH_LONG).show();
}} catch (NumberFormatException e) {
}}
#Override
protected void onActivityResult (int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
PaymentConfirmation confirm = data.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION);
//THINGS YOU WANT IT TO WHEN THE PAYMENT IS FINISHED GO BETWEEN HERE
//AND HERE
if (confirm != null) {
try {
Log.i("paymentExample", confirm.toJSONObject().toString(4));
// TODO: send 'confirm' to your server for verification.
// see https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/
// for more details.
} catch (JSONException e) {
Log.e("paymentExample", "an extremely unlikely failure occurred: ", e);
}
}
}
else if (resultCode == Activity.RESULT_CANCELED) {
Log.i("paymentExample", "The user canceled.");
}
else if (resultCode == PaymentActivity.RESULT_PAYMENT_INVALID) {
Log.i("paymentExample", "An invalid payment was submitted. Please see the docs.");
}}

No need to put PaymentActivity.EXTRA_PAYPAL_ENVIRONMENT for live.

This is my code which is working fine.
Declare these constants is class scope. NOTE: There are two client ids in page of your application in developer Paypal. One in "Test credentials" and The other under "Live credentials" that you should click on "show" link in order to see it. Select client id of "Live credentials" if you want to release your application.
private static final String PAYPAL_CLIENT_ID = "YOUR-CLIENT-IT";
private static final String PAYPAL_RECEIVER_EMAIL = "YOUR-EMAIL";
Then define service in onCreate():
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// start Paypal service
Intent intent = new Intent(this, PayPalService.class);
// live: don't put any environment extra
// sandbox: use PaymentActivity.ENVIRONMENT_SANDBOX
intent.putExtra(PaymentActivity.EXTRA_PAYPAL_ENVIRONMENT, PaymentActivity.ENVIRONMENT_PRODUCTION);
intent.putExtra(PaymentActivity.EXTRA_CLIENT_ID, PAYPAL_CLIENT_ID);
startService(intent);
}
When user hit a button following method will run:
private void openDonateBtnPressed(BigDecimal donation) {
PayPalPayment payment = new PayPalPayment(donation, "USD", "Donation");
Intent intent = new Intent(this, PaymentActivity.class);
// comment this line out for live or set to PaymentActivity.ENVIRONMENT_SANDBOX for sandbox
intent.putExtra(PaymentActivity.EXTRA_PAYPAL_ENVIRONMENT, PaymentActivity.ENVIRONMENT_PRODUCTION);
// it's important to repeat the clientId here so that the SDK has it if Android restarts your
// app midway through the payment UI flow.
intent.putExtra(PaymentActivity.EXTRA_CLIENT_ID, PAYPAL_CLIENT_ID);
// Provide a payerId that uniquely identifies a user within the scope of your system,
// such as an email address or user ID.
intent.putExtra(PaymentActivity.EXTRA_PAYER_ID, "<someuser#somedomain.com>");
intent.putExtra(PaymentActivity.EXTRA_RECEIVER_EMAIL, PAYPAL_RECEIVER_EMAIL);
intent.putExtra(PaymentActivity.EXTRA_PAYMENT, payment);
startActivityForResult(intent, 0);
}
and this is onActivityResult():
#Override
protected void onActivityResult (int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
PaymentConfirmation confirm = data.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION);
if (confirm != null) {
try {
Toast.makeText(RateTheAppActivity.this, R.string.rate_donation_received, Toast.LENGTH_LONG).show();
Log.d(TAG, confirm.toJSONObject().toString(4));
} catch (JSONException e) {
Log.e(TAG, "an extremely unlikely failure occurred: ", e);
}
}
}
else if (resultCode == Activity.RESULT_CANCELED) {
Log.d(TAG, "The user canceled.");
}
else if (resultCode == PaymentActivity.RESULT_PAYMENT_INVALID) {
Log.e(TAG, "An invalid payment was submitted. Please see the docs.");
}
}

Related

How to Detect if user has confirmed for installation in PackageInstaller (Android)

Background: I am installing android app programmatically using PackageInstaller.
What am I doing: The code which I am using is mentioned below. This is the same code which has been provided in PackageInstaller sample by google.
private void init() {
PackageInstaller.Session session = null;
try {
PackageInstaller packageInstaller = getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
int sessionId = packageInstaller.createSession(params);
session = packageInstaller.openSession(sessionId);
addApkToInstallSession("HelloActivity.apk", session);
// Create an install status receiver.
Context context = InstallApkSessionApi.this;
Intent intent = new Intent(context, InstallApkSessionApi.class);
intent.setAction(PACKAGE_INSTALLED_ACTION);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
IntentSender statusReceiver = pendingIntent.getIntentSender();
// Commit the session (this will start the installation workflow).
session.commit(statusReceiver);
} catch (IOException e) {
throw new RuntimeException("Couldn't install package", e);
} catch (RuntimeException e) {
if (session != null) {
session.abandon();
}
throw e;
}
}
});
}
private void addApkToInstallSession(String assetName, PackageInstaller.Session session)
throws IOException {
// It's recommended to pass the file size to openWrite(). Otherwise installation may fail
// if the disk is almost full.
try (OutputStream packageInSession = session.openWrite("package", 0, -1);
InputStream is = getAssets().open(assetName)) {
byte[] buffer = new byte[16384];
int n;
while ((n = is.read(buffer)) >= 0) {
packageInSession.write(buffer, 0, n);
}
}
}
// Note: this Activity must run in singleTop launchMode for it to be able to receive the intent
// in onNewIntent().
#Override
protected void onNewIntent(Intent intent) {
Bundle extras = intent.getExtras();
if (PACKAGE_INSTALLED_ACTION.equals(intent.getAction())) {
int status = extras.getInt(PackageInstaller.EXTRA_STATUS);
String message = extras.getString(PackageInstaller.EXTRA_STATUS_MESSAGE);
switch (status) {
case PackageInstaller.STATUS_PENDING_USER_ACTION:
// This test app isn't privileged, so the user has to confirm the install.
Intent confirmIntent = (Intent) extras.get(Intent.EXTRA_INTENT);
startActivity(confirmIntent);
break;
case PackageInstaller.STATUS_SUCCESS:
Toast.makeText(this, "Install succeeded!", Toast.LENGTH_SHORT).show();
break;
case PackageInstaller.STATUS_FAILURE:
case PackageInstaller.STATUS_FAILURE_ABORTED:
case PackageInstaller.STATUS_FAILURE_BLOCKED:
case PackageInstaller.STATUS_FAILURE_CONFLICT:
case PackageInstaller.STATUS_FAILURE_INCOMPATIBLE:
case PackageInstaller.STATUS_FAILURE_INVALID:
case PackageInstaller.STATUS_FAILURE_STORAGE:
Toast.makeText(this, "Install failed! " + status + ", " + message,
Toast.LENGTH_SHORT).show();
break;
default:
Toast.makeText(this, "Unrecognized status received from installer: " + status,
Toast.LENGTH_SHORT).show();
}
}
}
Query: The code works perfectly fine but PackageInstaller doesn't give any status on clicking the INSTALL button where as onclicking the CANCEL button, it provides status. I have to perform some action when user confirms installation by clicking install button. Is there any other way to get the status when install button is clicked?
Note: I don't want the status after installation is successful but I want it when INSTALL button is clicked.
You can register a broadcast for action PACKAGE_ADDED and even check if the package is installed using PackageManager#getPackageInfo
Refer to these questions:
Receiving package install and uninstall events
Check if application is installed - Android
Edit: After realizing that you are trying to retrieve the click event on the "Install" button instead- I don't think it's possible by any good means. You can change the flow of your app and respond to the success of the installation instead or maybe wait for someone else to pick on this question. They might be some "hacky" way to do this but I'd still not recommend going with it.

Allow app unpinning with pin even with device ownership set to this app

I am setting device ownership for my app using dpm command (dpm set-device-admin) and in my MainActivity.java I have placed the code below :
DevicePolicyManager myDevicePolicyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
// get this app package name
ComponentName mDPM = new ComponentName(this, MyAdmin.class);
if (myDevicePolicyManager.isDeviceOwnerApp(this.getPackageName())) {
// get this app package name
String[] packages = {this.getPackageName()};
// mDPM is the admin package, and allow the specified packages to lock task
myDevicePolicyManager.setLockTaskPackages(mDPM, packages);
startLockTask();
} else {
Toast.makeText(getApplicationContext(),"Unable to auto pin - not device owner", Toast.LENGTH_LONG).show();
}
Whenever my app starts it auto pins itself, making it unable for users to leave. Without setting device ownership I am able to leave 'pinned' state by long pressing back button and providing the pin.
When I set the ownership this actions is overrided - all I see is 'App is pinned : unpinning isn't allowed on this device'. Is there any way to enable unpinning by providing pin as without device ownership? I still need it to make sure it autopins without any prompts.
Possible answer:
Override single/long key press, request pin and unpin app on success
MainActivity.java
#Override
public void onBackPressed() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
KeyguardManager km = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
Intent intent = km.createConfirmDeviceCredentialIntent(null, null);
if (intent != null) {
startActivityForResult(intent, REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS);
}
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS) {
// unpin the app
if (resultCode == RESULT_OK) {
stopLockTask();
} else {
// nope
Toast.makeText(this, "Pin is not correct", Toast.LENGTH_SHORT).show();
}
}
}

Passing bundle instance to place picker intent

I am working on an android app whose main purpose is to update the working location of the employees by admin. Now when I want to change/update the location of an employee from my recycler view(list of employees connected with my UserManagerAdapter), I have to pass the user name of that employee to the place picker intent so that when the admin pick the desired location, the database of that user will be changed accordingly.
My Steps(2 Steps)
I have passed the username to the place picker intent as bundle.
My UserManagerAdapter
holder.locationTv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
launchPicker(data.get(position).getUserName());
}
});
private void launchPicker(String userName) {
PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder();
Bundle bundle = new Bundle();
bundle.putString(USERNAME,userName);
try {
fragment.startActivityForResult(builder.build(fragment.getActivity()),PLACE_PICKER_REQUEST,bundle);
} catch (GooglePlayServicesRepairableException e) {
e.printStackTrace();
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
}
I received the location request inside of a fragment and update the location of that particular user
My ManageUserFragment
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == PLACE_PICKER_REQUEST){
if(resultCode == RESULT_OK){
Place place = PlacePicker.getPlace(getContext(),data);
address = place.getAddress().toString();
String latLng = place.getLatLng().toString();
latLang = latLng;
//update user's decided location
Bundle bundle = data.getExtras();
String userName = bundle.getString(USERNAME);// it returns null, Why?
updateLocation(latLang,userName);
Toast.makeText(getContext(), latLng, Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getContext(), getContext().getText(R.string.locationError), Toast.LENGTH_SHORT).show();
}
}
}
My constant is
public static final String USERNAME="Username";
Now,
My problem is
Why bundle.getString(USERNAME) always return null?
How to pass data to place picker intent so that we can receive it in
onActivityResult ?
After replicating your case and researching for a little bit, I found out that the third parameter in startActivityForResult() is not used to pass a bundle of values to the onActivityResult, it's used to pass options to Android itself, you can find those here. So if you want to pass any data you have to use an intent with putExtra("USERNAME", username), and you can retrieve it with getStringExtra("USERNAME"). It's explained in this answer as well.

Android confused implementing in app billing?

i am fairly new to android development, and am having major troubles understanding how to implement google in app billing. I have read the official google documentation, read through quite a few tutorials, etc. The one that i have found that is the most simple to me is the following. Even then i am struggling to get it working.
http://redappz.com/micro-transactions-tutorial-iap-for-android/
What i have done is, imported all helper classes from trivial drive. Have a google dev account with a signed apk.
The logic i want for my application is when a purchase is successful in Activity A. Activity B displays a button.
public class WorkoutPlan1 extends AppCompatActivity {
private Button WorkoutPlan1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_workoutplan1);
WorkoutPlan1 = (Button) findViewById(R.id.Workout1MoreInfo);
Base code with out any google billing stuff. Basic button just to run the google billing off.
public class WorkoutPlan1 extends AppCompatActivity {
private Button WorkoutPlan1;
//*************************************************************************************************************************
// Debug tag, for logging
static final String TAG = "test";
// SKUs for our products: the premium upgrade (non-consumable)
static final String SKU_PREMIUM = "android.test.purchased";
// Does the user have the premium upgrade?
boolean mIsPremium = false;
// (arbitrary) request code for the purchase flow
static final int RC_REQUEST = 1;
// The helper object
IabHelper mHelper;
//*************************************************************************************************************************
#Override
protected void onCreate(Bundle savedInstanceState) {
//*************************************************************************************************************************
String base64EncodedPublicKey = "KEY GOES HERE FROM MY GOOGLE DEV";
//It is recommended to add more security than just pasting it in your source code;
mHelper = new IabHelper(this, base64EncodedPublicKey);
Log.d(TAG, "Starting setup.");
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
Log.d(TAG, "Setup finished.");
if (!result.isSuccess()) {
// Oh noes, there was a problem.
Log.d(TAG, "Problem setting up In-app Billing: " + result);
}
// Hooray, IAB is fully set up!
// mHelper.queryInventoryAsync(mGotInventoryListener);
}
});
//*************************************************************************************************************************
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_workoutplan1);
WorkoutPlan1 = (Button) findViewById(R.id.Workout1MoreInfo);
}
//*************************************************************************************************************************
IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
Log.d(TAG, "Query inventory finished.");
if (result.isFailure()) {
Log.d(TAG, "Failed to query inventory: " + result);
return;
}
else {
Log.d(TAG, "Query inventory was successful.");
// does the user have the premium upgrade?
mIsPremium = inventory.hasPurchase(SKU_PREMIUM);
// update UI accordingly
WorkoutPlan1.setVisibility(View.VISIBLE);
Log.d(TAG, "User is " + (mIsPremium ? "PREMIUM" : "NOT PREMIUM"));
}
Log.d(TAG, "Initial inventory query finished; enabling main UI.");
}
};
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
if (result.isFailure()) {
Log.d(TAG, "Error purchasing: " + result);
return;
}
else if (purchase.getSku().equals(SKU_PREMIUM)) {
// give user access to premium content and update the UI
WorkoutPlan1.setVisibility(View.VISIBLE);
}
}
};
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data);
// Pass on the activity result to the helper for handling
if (!mHelper.handleActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
} else {
Log.d(TAG, "onActivityResult handled by IABUtil.");
}
}
Im aware i dont have an onclick listener on the button. But i dont even know how i would invoke the payment / purchase flow.
Any help AT ALL to point me in the right direction would be so appreciated, as at this point i just feel lost.
Thank you everyone
You would use the IabHelper object to invoke the purchase flow. For instance:
try {
mHelper.launchPurchaseFlow(this, SKU_BUNDLE, RC_REQUEST, mPurchaseFinishedListener,
payload);
} catch (IabAsyncInProgressException e) {
complain("Error launching purchase flow. Another async operation in progress.");
}
... So I would include this code snippet inside an onClickListener for your button. And then you would handle the purchases' response through the OnIabPurchaseFinishedListener.
P.S. I'm answering this with my mobile device, so excuse the poor formatting 😅😅😅

Android: cannot get values using .getStringExtra

I'll just go straight to the problem. In UploadNotesActivity.java....
First, I pick a .pdf file using intent
chooseNotesBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Create intent to Open Image applications like Gallery, Google Photos
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
// Start the Intent
startActivityForResult(intent, RESULT_LOAD_FILE);
}
});
and then, in `onActivityResult, I save the filePath of the picked file.
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RESULT_LOAD_FILE && resultCode == RESULT_OK && data != null) {
data.putExtra("filePath", data.getData().getPath());
choosenFile.setText(data.getStringExtra("filePath"));
} else {
Toast.makeText(this, "Error in choosing file",
Toast.LENGTH_LONG).show();
}
}
click Upload button to start upload the file
uploadNotesBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onUploadButtonClick();
}
});
the onUploadButtonClick()
private void onUploadButtonClick() {
final String serverUrlString = "http://XXXX/uploadNotes.php";
if (getIntent().getStringExtra("filePath").isEmpty()) {
Log.d(TAG, "filePath is null");
} else {
Log.d(TAG, getIntent().getStringExtra("filePath"));
}
final String fileToUploadPath = getIntent().getStringExtra("filePath");
final String paramNameString = "uploaded_file";
String fileName[] = fileToUploadPath.split("/");
final MultipartUploadRequest request =
new MultipartUploadRequest(this, UUID.randomUUID().toString(), serverUrlString);
request.addFileToUpload(fileToUploadPath, paramNameString,
fileName[fileName.length-1]+".pdf", ContentType.APPLICATION_OCTET_STREAM);
request.setNotificationConfig(R.drawable.ic_launcher,
getString(R.string.app_name),
getString(R.string.uploading),
getString(R.string.upload_success),
getString(R.string.upload_error),
false);
// if you comment the following line, the system default user-agent will be used
request.setCustomUserAgent("UploadServiceDemo/1.0");
// set the intent to perform when the user taps on the upload notification.
// currently tested only with intents that launches an activity
// if you comment this line, no action will be performed when the user taps
// on the notification
// request.setNotificationClickIntent(new Intent(this, MainActivity.class));
// set the maximum number of automatic upload retries on error
request.setMaxRetries(2);
try {
request.startUpload();
} catch (Exception exc) {
Toast toast = Toast.makeText(getApplicationContext(), "Malformed upload request. " + exc.getLocalizedMessage(), Toast.LENGTH_LONG);
toast.show();
}
}
But the problem is, it will throw null pointer exception, which I don't quite get the reason.
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.isEmpty()' on a null object reference
at com.fyp.mycyberlaw.Lecturer.UploadNotesActivity.onUploadButtonClick(UploadNotesActivity.java:73)
at com.fyp.mycyberlaw.Lecturer.UploadNotesActivity.access$100(UploadNotesActivity.java:19)
at com.fyp.mycyberlaw.Lecturer.UploadNotesActivity$2.onClick(UploadNotesActivity.java:53)
line 73: if (getIntent().getStringExtra("filePath").isEmpty())
line 19: public class UploadNotesActivity extends Activity
line 53: onUploadButtonClick();
Seems like the filePath in line 73 is empty and the way I save filePath into bundle (?) is incorrect. How to get the filePath from onActivityResult? Here's the .java class, just in case. Thank you in advance. Really need your help.
An Intentobject is used to pass params between activities. Ones you receives the file path you must to keep it in your activity.
Create a filePathvariable inside your activity, set it on onActivityResult and read it on onUploadButtonClick.
Notice that must save variable value during the onSaveInstanceState callback and restore it in onCreate because every time you turn your phone the activity is destroyed and recreated. Check this for more information: Recreating an Activity

Categories

Resources