I am trying to develop an app with in app purchases in it, simply what I want to do is to have two buttons one to make the purchase(enabled) the second button to open the activity after purchase (at first is disabled then after purchase is enabled).
Two problems the first was to save the buttons state after the purchase as they were getting reset every time I restart the app. So I did some researches and found about shared preference and I did implemented it but the second problem came out that buttons statuses doesn’t seem to work right (between disabled to enabled) after implementing shared preference.
Note that in the app I have two buttons that do the same thing one enables the other buttons but with no purchase made and they work fine with shared preference, but the buttons associated with the in app purchase stopped changing their status from disabled to enabled after the purchase is made (they stay disabled after the purchase)
Here is my xml code:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainScreen">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Activity 1"
android:id="#+id/act1"
android:onClick="Activity1"
android:layout_marginTop="84dp"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/buyall"
android:layout_toStartOf="#+id/buyall"
android:enabled="false" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Buy Act 1"
android:id="#+id/buyButton"
android:onClick="buyClick"
android:layout_alignTop="#+id/act1"
android:layout_toRightOf="#+id/act1"
android:layout_toEndOf="#+id/act1"
android:layout_marginLeft="45dp"
android:layout_marginStart="45dp"
android:enabled="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Activity 2"
android:id="#+id/act2"
android:layout_below="#+id/act1"
android:layout_alignLeft="#+id/act1"
android:layout_alignStart="#+id/act1"
android:onClick="Activity2"
android:enabled="false" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Buy act 2"
android:id="#+id/buyact2"
android:layout_alignBottom="#+id/act2"
android:layout_alignLeft="#+id/buyButton"
android:layout_alignStart="#+id/buyButton"
android:onClick="buyAct2"
android:enabled="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Activity 3"
android:id="#+id/act3"
android:layout_below="#+id/act2"
android:layout_alignLeft="#+id/act2"
android:layout_alignStart="#+id/act2"
android:onClick="Activity3"
android:enabled="false" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Buy act 3"
android:id="#+id/buyact3"
android:layout_alignBottom="#+id/act3"
android:layout_alignLeft="#+id/buyact2"
android:layout_alignStart="#+id/buyact2"
android:onClick="buyAct3"
android:enabled="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Buy all"
android:id="#+id/buyall"
android:onClick="buyAll"
android:enabled="true"
android:layout_below="#+id/eact4"
android:layout_centerHorizontal="true" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ACT 4"
android:id="#+id/act4"
android:onClick="ACT4"
android:layout_below="#+id/act3"
android:layout_alignLeft="#+id/act3"
android:layout_alignStart="#+id/act3"
android:enabled="false" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Enable ACT 4"
android:id="#+id/eact4"
android:onClick="EACT4"
android:layout_below="#+id/buyact3"
android:layout_alignLeft="#+id/buyact3"
android:layout_alignStart="#+id/buyact3"
android:enabled="true" />
And that’s my java code:
package com.aseng90_test.smiap2;
import android.content.Intent;
import android.content.SharedPreferences;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.aseng90_test.smiap2.util.IabHelper;
import com.aseng90_test.smiap2.util.IabResult;
import com.aseng90_test.smiap2.util.Purchase;
public class MainScreen extends ActionBarActivity {
private static final String TAG = "com.aseng90_test.smiap2";
IabHelper mHelper;
private static final String ITEM_SKU = "com.aseng90_test.smiap2_button555";
private static final String ITEM_SKU2 = "com.aseng90_test.smiap2_buyact222";
private static final String ITEM_SKU3 = "com.aseng90_test.smiap2_buyact333";
private static final String ITEM_SKU4 = "com.aseng90_test.smiap2_buyall_11";
private Button Activity1;
private Button Activity2;
private Button Activity3;
private Button buyButton;
private Button buyAct2;
private Button buyAct3;
private Button buyAll;
private Button EAct4;
private Button Act4;
private SharedPreferences prefs;
private String prefName = "MyPref";
boolean Activity1_isEnabled;
boolean Activity2_isEnabled;
boolean Activity3_isEnabled;
boolean Act4_isEnabled;
boolean buyButton_isEnabled;
boolean buyAct2_isEnabled;
boolean buyAct3_isEnabled;
boolean buyAll_isEnabled;
boolean EAct4_isEnabled;
private static final String Activity1_state = "Activity1_state";
private static final String Activity2_State = "Activity2_state";
private static final String Activity3_State = "Activity3_state";
private static final String buyButton_State = "buyButton_state";
private static final String buyAct2_State = "buyAct2_state";
private static final String buyAct3_State = "buyAct3_state";
private static final String buyAll_State = "buyAll_state";
private static final String Act4_State = "Act4_state";
private static final String EAct4_State = "EAct4_state";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
buyButton = (Button) findViewById(R.id.buyButton);
buyAct2 = (Button) findViewById(R.id.buyact2);
buyAct3 = (Button) findViewById(R.id.buyact3);
buyAll = (Button) findViewById(R.id.buyall);
Activity1 = (Button) findViewById(R.id.act1);
Activity2 = (Button) findViewById(R.id.act2);
Activity3 = (Button) findViewById(R.id.act3);
EAct4 = (Button) findViewById(R.id.eact4);
Act4 = (Button) findViewById(R.id.act4);
String base64EncodedPublicKey =
"";
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.startSetup(new
IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
Log.d(TAG, "In-app Billing setup failed: " + result);
} else {
Log.d(TAG, "In-app Billing is set up OK");
}
}
});
}
public void EACT4(View view) {
EAct4.setEnabled(false);
Act4.setEnabled(true);
}
public void ACT4(View view) {
Toast.makeText(MainScreen.this,
"ACt4 Clicked", Toast.LENGTH_LONG).show();
}
public void buyClick(View view) {
mHelper.launchPurchaseFlow(this, ITEM_SKU, 10001,
mPurchaseFinishedListener, "mypurchasetoken");
}
public void buyAct2(View view) {
mHelper.launchPurchaseFlow(this, ITEM_SKU2, 10002, mPurchaseFinishedListener, "buyact2");
}
public void buyAct3(View view) {
mHelper.launchPurchaseFlow(this, ITEM_SKU3, 10003, mPurchaseFinishedListener, "buyact3");
}
public void buyAll(View view) {
mHelper.launchPurchaseFlow(this, ITEM_SKU4, 10004, mPurchaseFinishedListener, "buyall");
}
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (!mHelper.handleActivityResult(requestCode,
resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
= new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result,
Purchase purchase) {
if (result.isFailure()) {
// Handle error
return;
}
if (purchase.getSku().equals(ITEM_SKU)) {
Activity1.setEnabled(true);
buyButton.setEnabled(false);
}
if (purchase.getSku().equals(ITEM_SKU2)) {
Activity2.setEnabled(true);
buyAct2.setEnabled(false);
}
if (purchase.getSku().equals(ITEM_SKU3)) {
Activity3.setEnabled(true);
buyAct3.setEnabled(false);
}
if (purchase.getSku().equals(ITEM_SKU4)) {
Activity1.setEnabled(true);
Activity2.setEnabled(true);
Activity3.setEnabled(true);
buyAll.setEnabled(false);
buyButton.setEnabled(false);
buyAct2.setEnabled(false);
buyAct3.setEnabled(false);
}
}
};
public void Activity1(View view) {
startActivity(new Intent(MainScreen.this, Click1.class));
}
public void Activity2(View view) {
startActivity(new Intent(MainScreen.this, Activity2.class));
}
public void Activity3(View view) {
startActivity(new Intent(MainScreen.this, Activity3.class));
}
#Override
public void onDestroy() {
super.onDestroy();
if (mHelper != null) mHelper.dispose();
mHelper = null;
}
#Override
protected void onPause(){
super.onPause();
if (Act4.isEnabled()){
Act4_isEnabled = true;
}
else {
Act4_isEnabled = false;
}
if (Activity1.isEnabled()){
Activity1_isEnabled = true;
}
else {
Activity1_isEnabled = false;
}
if (Activity2.isEnabled()){
Activity2_isEnabled = true;
}
else {
Activity2_isEnabled = false;
}
if (Activity3.isEnabled()){
Activity3_isEnabled = true;
}
else {
Activity3_isEnabled = false;
}
if (buyButton.isEnabled()){
buyButton_isEnabled = true;
}
else {
buyButton_isEnabled = false;
}
if (buyAct2.isEnabled()){
buyAct2_isEnabled = true;
}
else {
buyAct2_isEnabled = false;
}
if (buyAct3.isEnabled()){
buyAct3_isEnabled = true;
}
else {
buyAct3_isEnabled = false;
}
if (buyAll.isEnabled()){
buyAll_isEnabled = true;
}
else {
buyAll_isEnabled = false;
}
prefs = getSharedPreferences(prefName,MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(Activity1_state,this.getLocalClassName());
editor.putBoolean(Act4_State,Act4_isEnabled);
editor.putBoolean(EAct4_State,EAct4_isEnabled);
editor.putBoolean(Activity1_state,Activity1_isEnabled);
editor.putBoolean(Activity2_State,Activity2_isEnabled);
editor.putBoolean(Activity3_State,Activity3_isEnabled);
editor.putBoolean(buyButton_State,buyButton_isEnabled);
editor.putBoolean(buyAct2_State,buyAct2_isEnabled);
editor.putBoolean(buyAct3_State,buyAct3_isEnabled);
editor.putBoolean(buyAll_State,buyAll_isEnabled);
editor.apply();
}
#Override
protected void onResume(){
super.onResume();
prefs = getSharedPreferences(prefName,MODE_PRIVATE);
Act4.setEnabled(prefs.getBoolean(Act4_State,false));
Activity1.setEnabled(prefs.getBoolean(Activity1_state,false));
Activity2.setEnabled(prefs.getBoolean(Activity2_State,false));
Activity3.setEnabled(prefs.getBoolean(Activity3_State,false));
EAct4.setEnabled(prefs.getBoolean(EAct4_State,true));
buyButton.setEnabled(prefs.getBoolean(buyButton_State,true));
buyAct2.setEnabled(prefs.getBoolean(buyAct2_State,true));
buyAct3.setEnabled(prefs.getBoolean(buyAct3_State,true));
buyAll.setEnabled(prefs.getBoolean(buyAll_State,true));
}
So Any suggestions if I have something wrong in my code?
Thanks a lot.
Try to call methods from Java part , don't call from xml using android:onClick
Use default value of the button(buy) state to false in shared preference .
and in this screen implement this if check inside oncreate() method as:
if(button(buy) state ==false)
{
//make button(buy) state enable
//make activity button state disable
}
else
{
//make button(buy) state disable
//make activity button state enable
}
And make button(buy) and activity calling button state to true/false according to result after in app purchase and also update shared prefrence state according to result
Related
I am getting Error that i wrote below when showing custom Dialog from FragmentActivity.
Error i am getting :
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
Here is my DriverMapActivity that i show custom Dialog from :
Note: I removed some codes that they are not related to my question
DriverMap FragmentActivity
public class DriverMapActivity extends FragmentActivity{
private GoogleMap mMap;
GoogleApiClient googleApiClient;
SupportMapFragment mapFragment;
LocationRequest mLocationRequest;
private Location lastLocation;
private FirebaseAuth mAuth;
private Switch workingswitch;
private String customerId, userId;
private Toolbar toolbar;
private NavigationView navigationView;
private DrawerLayout drawerLayout;
private DatabaseReference driverInfoDB;
private String name, surname, profileimageURL;
private String distancetopick,distancetodes;
private int distancefinal;
private Button yesBtn, noBtn;
private UserInfoShower cdd;
private int cameraupdatedandzoomed;
private Map<String,String> infoMap;
private LatLng pickupLoc;
private LatLng destiantionLoc;
private Marker pickupMarker, destinationMarker;
private float rideDistance;
private Button btnzoom;
private String customerprofileUrl;
private Button logoutbtn, settingsbtn, historybtn, opendrawer;
private boolean pickupgeted;
private String rideStatus = "";
private LatLng target;
#SuppressLint("NewApi")
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_driver_map);
customerId = "";
cameraupdatedandzoomed=0;
mAuth = FirebaseAuth.getInstance();
toolbar = findViewById(R.id.toolbar);
polylines = new ArrayList<>();
userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
btnzoom=findViewById(R.id.btnzoom);
pickupgeted = false;
startService(new Intent(DriverMapActivity.this,onAppKilled.class));
navigationView = (NavigationView) findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(this);
// This method will trigger on item Click of navigation menu
// Initializing Drawer Layout and ActionBarToggle
drawerLayout = (DrawerLayout) findViewById(R.id.drawer);
setDriverStuffToNavView();
btnzoom.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(lastLocation!=null)
{
}
else
{
Toast.makeText(DriverMapActivity.this, "Turn on Working
}
}
});
private void listenForCustomerRequest() {
String userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReferencelistenerRef=FirebaseDatabase.getInstance().getReference()
.child("Users").child("Drivers").child(userId).child("CustomerRequest");
listenerRef.addChildEventListener(new ChildEventListener() {
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, String s) {
if (dataSnapshot.exists()) {
customerId = dataSnapshot.getKey();
showUserInfo();
}
}
});
}
Here is method that i show CustomDialog:
UserInfoShower Method
Note: I removed some codes that they are not related to my question
private void showUserInfo() {
DatabaseReferenceuserinfoRef=FirebaseDatabase.getInstance().getReference()
.child("Users").child("Customers").child(customerId);
Log.i("TEST", "CustomerId Comes Driver " + customerId);
infoMap=new HashMap<>();
cdd = new UserInfoShower(DriverMapActivity.this,infoMap);
DatabaseReferenceuserInfoDB=FirebaseDatabase.getInstance().getReference()
.child("Users").child("Customers").child(customerId);
userInfoDB.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists() && dataSnapshot.getChildrenCount() > 0) {
Map<String, Object> map = (Map<String, Object>)
dataSnapshot.getValue();
infoMap.put("DriverOrCus", "1");
infoMap.put("Name", map.get("name").toString());
infoMap.put("Surname", map.get("surname").toString());
if(map.get("profileimageURL") !=null)
{
infoMap.put("profileimageURL",
map.get("profileimageURL").toString());
customerprofileUrl=map.get("profileimageURL").toString();
}
infoMap.put("customerId", customerId);
cdd = new UserInfoShower(DriverMapActivity.this,infoMap);
cdd.show();
cdd.setCanceledOnTouchOutside(false);
yesBtn = cdd.findViewById(R.id.yesBtn);
noBtn = cdd.findViewById(R.id.noBtn);
yesBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String userId=FirebaseAuth.getInstance().
getCurrentUser().getUid();
DatabaseReference decisionRef=FirebaseDatabase.
getInstance().getReference().
child("Users").child("Drivers").child(userId).child("CustomerRequest")
.child(customerId)
.child("driverDecision");
decisionRef.setValue("YES").addOnCompleteListener(newOnCompleteListener
<Void>() {
#Override
public void onComplete(#NonNull
Task<Void>task) {
cdd.cancel();
cdd.dismiss();
cdd=null;
getCustomerRideInfo();
}
});
}
});
}
Error happens when i call cdd.show();
Here is UserInfoShower Dialog:
public class UserInfoShower extends Dialog {
public Context c;
private Button noBtn, yesBtn;
private String name, surname, profileimageURL;
private TextView customerName, customerSurname;
private ImageView customerprofile;
private int position;
private String driverId;
private LatLng CustomerPickupLoc, CustomerDestinationLoc;
private String customerId, desName;
private SharedPreferences sharedpref;
Map<String,String> infoMap;
public UserInfoShower(Context a,Map<String,String> infoMap) {
super(a);
this.c = a;
this.infoMap=infoMap;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_customer_info_shower);
noBtn = findViewById(R.id.noBtn);
yesBtn = findViewById(R.id.yesBtn);
customerName = findViewById(R.id.customerName);
customerSurname = findViewById(R.id.customerSurname);
customerprofile = findViewById(R.id.customerprofile);
position = Integer.valueOf(infoMap.get("DriverOrCus"));
if (position == 1) {
showCusInfo();
} else {
showDriverInfo();
}
yesBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (position == 1) // If user is Driver
{
dismiss();
} else //if user is Cusomer And Liked Driver
{
dismiss();
}
}
});
noBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (position == 1) //if User is Driver
{
dismiss();
} else// if User is Customer And not liked Driver
{
dismiss();
}
}
});
}
private void showCusInfo() {
name = infoMap.get("Name");
surname = infoMap.get("Surname");
customerId = infoMap.get("customerId");
customerName.setText("Name " + name);
customerSurname.setText("Surname " + surname);
}
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
}
public static boolean isValidContextForGlide(final Context context) {
if (context == null) {
return false;
}
if (context instanceof Activity) {
final Activity activity = (Activity) context;
if (activity.isDestroyed() || activity.isFinishing()) {
return false;
}
}
return true;
}
}
Here is My Dialog xml file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://
schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".UserInfoShower">
<ImageView
android:id="#+id/customerprofile"
android:layout_width="90dp"
android:layout_height="102dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="30dp"
android:layout_marginTop="35dp"
android:src="#drawable/customer"
tools:ignore="RtlCompat" />
<TextView
android:layout_width="240dp"
android:layout_height="wrap_content"
android:id="#+id/customerName"
android:layout_alignParentTop="true"
android:layout_marginTop="36dp"
android:layout_toEndOf="#+id/customerprofile"
android:text="Name : Vuqar"
android:textColor="#color/colorPrimaryDark"
android:textSize="20sp"
tools:ignore="RtlCompat" />
<TextView
android:id="#+id/customerSurname"
android:layout_width="240dp"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginTop="92dp"
android:layout_toEndOf="#+id/customerprofile"
android:text="Surname : Samed"
android:textColor="#color/colorPrimaryDark"
android:textSize="20sp"
tools:ignore="RtlCompat" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginTop="219dp"
android:orientation="horizontal">
<Button
android:id="#+id/yesBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="OK.Looks Good" />
<Button
android:id="#+id/noBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Nope" />
</LinearLayout>
</RelativeLayout>
And finally here is whole error log :
Hope you can help me.Cheers !
Problem solved by : #dr3k
Here is solution. Solution
My app consists of two strings and two buttons, one English string and Hindi string, when i click on English speak button, the English string is pronouncing, when i come to Hindi string it is not responding to given word as it was mentioned.
Here is my MainActivity look likes,
public class MainActivity extends AppCompatActivity {
private TextView englishString, hindiString;
private Button englishButton, hindiButton;
private TextToSpeech textToSpeech;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
englishString = (TextView) findViewById(R.id.englishString);
hindiString = (TextView) findViewById(R.id.hindiString);
englishButton = (Button) findViewById(R.id.englishButton);
hindiButton = (Button) findViewById(R.id.hindiButton);
englishButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
loadSpeakingLanguages(englishString.getText().toString());
}
});
hindiButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
loadSpeakingLanguages(hindiString.getText().toString());
}
});
}
private void loadSpeakingLanguages(String textToTranslate) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ttsGreater21(textToTranslate);
} else {
ttsUnder20(textToTranslate);
}
}
#SuppressWarnings("deprecation")
private void ttsUnder20(String text) {
HashMap<String, String> map = new HashMap<>();
map.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "MessageId");
textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, map);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void ttsGreater21(String text) {
String utteranceId = this.hashCode() + "";
textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, null, utteranceId);
}
#Override
protected void onResume() {
textToSpeech = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR) {
textToSpeech.setLanguage(Locale.ENGLISH);
}
}
});
super.onResume();
}
public void onPause() {
if (textToSpeech != null) {
textToSpeech.stop();
textToSpeech.shutdown();
textToSpeech = null;
}
super.onPause();
}}
Here is my activity_main looks like,
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="ravi.texttospeech.MainActivity">
<TextView
android:id="#+id/englishString"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textSize="25dp" />
<TextView
android:id="#+id/hindiString"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/englishString"
android:text="नमस्ते दुनिया"
android:textSize="25dp" />
<Button
android:id="#+id/englishButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/hindiString"
android:text="Speak English Text" />
<Button
android:id="#+id/hindiButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/englishButton"
android:text="Speak Hindi Text" />
And here is how my app look like
I have done some modifications in your code.
hindiButton.setOnClickListener(new View.OnClickListener() {
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public void onClick(View view) {
loadSpeakingLanguages(hindiString.getText().toString());
textToSpeech.setLanguage(Locale.forLanguageTag("hin"));
}
});
its working fine for me.
You need to use ISO 639 3-letter word or ISO 639 2-letter word
check out the ISO country names and there corresponding codes in this link
Note: This method works only above lollipop and next versions .
setLanguage(new Locale("hi","IN"))
Try this:-
Locale locale = new Locale("hi", "IN");
int avail = textToSpeech.isLanguageAvailable(locale);
switch (avail) {
case TextToSpeech.LANG_AVAILABLE:
textToSpeech.setLanguage(Locale.forLanguageTag("hi"));
isLanguageAvailable = true;
break;
case TextToSpeech.LANG_COUNTRY_AVAILABLE:
case TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE:
textToSpeech.setLanguage(locale);
isLanguageAvailable = true;
break;
}
Changing the default engine to com.google.android.tts, worked for me.
Example:
new TextToSpeech(
context.getApplicationContext(),
new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR) {
if (textToSpeech != null) {
textToSpeech.setLanguage(new Locale("en", "IN"));
textToSpeech.setSpeechRate(1);
}
}
}
},
"com.google.android.tts");
Add this import:
import android.speech.tts.TextToSpeech
Implement this listener
class DetailDay : AppCompatActivity(), TextToSpeech.OnInitListener {
Then override (paste) this method:
override fun onInit(intVar: Int) {
if(intVar==TextToSpeech.SUCCESS){
var local= Locale("hi","IN")
val resultado=tts!!.setLanguage(local)
if(resultado==TextToSpeech.LANG_MISSING_DATA){
Log.i(TAG,"lang not found")
}
}
}
Then create this variable:
private var tts:TextToSpeech?=null
Initialize in onCreate (recommended)
tts= TextToSpeech(this,this)
To start playing, call this method:
tts!!.speak(stringData, TextToSpeech.QUEUE_FLUSH, null);
To Stop playing,
tts!!.stop()
I have an app that uses several activities. One activity is to manually enter some values and I have four buttons in that activity. When one of the buttons is clicked it starts a new activity to get the input.
The problem is that the layout for the activity is not displayed when the get_input() function of this activity is run. It should get a decimal value from an EditText. but I keep getting a runtime error of "Invalid Float """.
If I comment out the get_input() function then the layout for the activity is shown fine.
Here is the xml file :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/manually_entry" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Please enter the decimal Latitude"
android:singleLine="true"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Negative is South"
android:singleLine="true"
/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:inputType="numberDecimal|numberSigned"
android:id="#+id/enter_decimal_number" />
</LinearLayout>
And here is the calling activity :
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lat_long_manual_entry);
}
// manual entry dialog buttons
public void enter_lat_dec_deg(View v) {
Intent intent = new Intent(this.getApplicationContext(), ManuallyEnterNumbers.class);
startActivity(intent);
}
And here is the called activity that requests the actual input from the user :
package com.example.david.gpstest;
import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView;
/**
* Created by david on 06/03/16.
*/
public class ManuallyEnterNumbers extends Activity {
private EditText input;
private float decimal_input;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.manually_enter_numbers);
}
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onResume() {
super.onResume();
get_input();
}
public void get_input() {
input = (EditText) findViewById(R.id.enter_decimal_number);
input.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
decimal_input = Float.valueOf(input.getText().toString());
return true;
}
return false;
}
});
}
}
I am showing the function get_input() in the onStart() method but IO have also tried it in the onResume() method and that does not work either.
Any help here would be very much appreciated.
Thank You.
Float.valueOf(input.getText().toString());
The common mistake here newbies ofter make is lack of string sanitization prior attempting conversion. Even , (comma) instead of . (dot) entered as decimal part separator will cause exception to be thrown. So you simply must make string convertable (i.e. by checking what's inside, replacing , with . etc) not to mention you should expect exception to come and use try/catch to catch it to avoid app crash you are facing now.
David, hello, this is yourself. Basically you can forget about sanitizing the input. Because you have android:inputType="numberDecimal|numberSigned" in your xml you will get a numeric keypad with the comma, and space disabled. So all that the user can enter is digits a decimal point and a minus sign. Exactly what you want. Secondly, you can forget about the onStart() and onResume() methods and stick everything in onCreate() and then it will work. Your xml is absolutely fine. Your calling activity absolutely fine too although it would be a good idea to use an intent.putExtra() and an intent.getExtra() to pass the decimal_input value back to the calling activity. I have posted the code for the calling activity and the called activity below to help you out a bit.
public class ManualEntry extends Activity {
// private View layout;
// private PopupWindow enter_manual_dec_deg;
// LayoutInflater inflater;
// private EditText input;
// private float decimal_input;
// private String result;
static final int REQUEST_CODE = 1;
String button_pressed;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lat_long_manual_entry);
}
#Override
protected void onResume() {
super.onResume();
}
// manual entry dialog buttons
public void enter_lat_dec_deg(View v) {
Intent intent = new Intent(this.getApplicationContext(), ManuallyEnterNumbers.class);
button_pressed = "lat_dec_deg";
intent.putExtra("Button pressed", button_pressed);
startActivityForResult(intent, REQUEST_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE) {
if (resultCode == RESULT_OK) {
double result = data.getDoubleExtra("returnData", 0.0d);
if (result < -180 || result > 180) {
Toast.makeText(this, "Value outside range - Range is -180 to 180", Toast.LENGTH_LONG).show();
}
else {
DecimalFormat var = new DecimalFormat("###.########");
Toast.makeText(this, var.format(result), Toast.LENGTH_LONG).show();
disable_button(button_pressed);
}
}
}
}
void disable_button(String pressed_button) {
Button dec_deg_button = (Button) findViewById(R.id.button_lat_dec_deg);
Button d_m_s_button = (Button) findViewById(R.id.button_lat_deg_min_sec);
if (pressed_button != null) {
if (pressed_button == "lat_dec_deg" || button_pressed == "lat_d_m_s") {
dec_deg_button.setEnabled(false);
d_m_s_button.setEnabled(false);
}
}
}
}
/*
public void enter_lat_d_m_s (View v) {
}
public void enter_lon_dec_deg(View v) {
}
public void enter_lon_d_m_s(View v) {
}
*/
And the called activity
package com.example.david.gpstest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
/**
* Created by david on 06/03/16.
*/
public class ManuallyEnterNumbers extends Activity {
private EditText input;
private String inValue;
private double decimal_input;
private Bundle extras;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.manually_enter_numbers);
extras = getIntent().getExtras();
if (extras != null) {
String buttonPressed = extras.getString("Button pressed");
if (buttonPressed.contentEquals(buttonPressed) ) {
((TextView) findViewById(R.id.enter_decimal_number)).setHint("Decimal degrees of Latitude");
TextView title_text = (TextView) findViewById(R.id.manual_entry_hint);
title_text.setText("Please enter the decimal Latitude");
TextView hint_text = (TextView) findViewById(R.id.manual_entry_hint);
hint_text.setText("(Negative is South)");
}
}
get_input();
}
#Override
protected void onStart() {
super.onStart();
// get_input();
}
#Override
protected void onResume() {
super.onResume();
// get_input();
}
public void get_input() {
input = (EditText) findViewById(R.id.enter_decimal_number);
input.setOnEditorActionListener(new TextView.OnEditorActionListener(){
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
// do stuff here
inValue = input.getText().toString();
if (inValue.isEmpty()) {
Toast.makeText(getApplicationContext(), "Enter a value", Toast.LENGTH_SHORT).show();
}
else {
// some input
decimal_input = Double.parseDouble(inValue);
Intent returnIntent = getIntent();
returnIntent.putExtra("returnData", decimal_input);
setResult(RESULT_OK, returnIntent);
finish();
}
}
return true;
}
});
/*
Intent returnIntent = getIntent();
returnIntent.putExtra("returnData", decimal_input);
setResult(RESULT_OK, returnIntent);
finish();
*/
}
}
I hope that this helps you out a bit.
David.
I am trying to develop a simple app that when I buy an activity it makes the button enabled.
My code works fine but the problem is when I exit the app and reopen it, the buttons that was previously enabled after the purchase they become disabled however it doesn't allow to repurchase again.
(I need to do it on time purchase)
So how to keep the enabled buttons stays enabled when I restart the app?
Here is my code:
public class MainScreen extends ActionBarActivity {
private static final String TAG = "com.aseng90_test.smiap2";
IabHelper mHelper;
static final String ITEM_SKU = "com.aseng90_test.smiap2_button5";
static final String ITEM_SKU2 = "com.aseng90_test.smiap2_buyact2";
static final String ITEM_SKU3 = "com.aseng90_test.smiap2_buyact3";
static final String ITEM_SKU4 = "com.aseng90_test.smiap2_buyall";
public Button Activity1;
public Button Activity2;
public Button Activity3;
public Button buyButton;
public Button buyAct2;
public Button buyAct3;
public Button buyAll;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
buyButton = (Button) findViewById(R.id.buyButton);
buyAct2 = (Button) findViewById(R.id.buyact2);
buyAct3 = (Button) findViewById(R.id.buyact3);
buyAll = (Button) findViewById(R.id.buyall);
Activity1 = (Button) findViewById(R.id.act1);
Activity2 = (Button) findViewById(R.id.act2);
Activity3 = (Button) findViewById(R.id.act3);
Activity1.setEnabled(false);
Activity2.setEnabled(false);
Activity3.setEnabled(false);
String base64EncodedPublicKey =
"";
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.startSetup(new
IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result)
{
if (!result.isSuccess()) {
Log.d(TAG, "In-app Billing setup failed: " +
result);
} else {
Log.d(TAG, "In-app Billing is set up OK");
}
}
});
}
public void buyClick(View view) {
mHelper.launchPurchaseFlow(this, ITEM_SKU, 10001,
mPurchaseFinishedListener, "mypurchasetoken");
}
public void buyAct2 (View view){
mHelper.launchPurchaseFlow(this, ITEM_SKU2, 10002, mPurchaseFinishedListener, "buyact2");
}
public void buyAct3 (View view){
mHelper.launchPurchaseFlow(this,ITEM_SKU3, 10003, mPurchaseFinishedListener, "buyact3");
}
public void buyAll (View view){
mHelper.launchPurchaseFlow(this, ITEM_SKU4,10004, mPurchaseFinishedListener, "buyall");
}
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data)
{
if (!mHelper.handleActivityResult(requestCode,
resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
= new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result,
Purchase purchase)
{
if (result.isFailure()) {
// Handle error
return;
}
if (purchase.getSku().equals(ITEM_SKU)) {
Activity1.setEnabled(true);
buyButton.setEnabled(false);
}
if (purchase.getSku().equals(ITEM_SKU2)){
Activity2.setEnabled(true);
buyAct2.setEnabled(false);
}
if (purchase.getSku().equals(ITEM_SKU3)){
Activity3.setEnabled(true);
buyAct3.setEnabled(false);
}
if (purchase.getSku().equals(ITEM_SKU4)) {
Activity1.setEnabled(true);
Activity2.setEnabled(true);
Activity3.setEnabled(true);
buyAll.setEnabled(false);
buyButton.setEnabled(false);
buyAct2.setEnabled(false);
buyAct3.setEnabled(false);
}
}
};
public void Activity1 (View view)
{
startActivity(new Intent(MainScreen.this, Click1.class));
}
public void Activity2 (View view){
startActivity(new Intent(MainScreen.this, Activity2.class));
}
public void Activity3 (View view){
startActivity(new Intent(MainScreen.this, Activity3.class));
}
#Override
public void onDestroy() {
super.onDestroy();
if (mHelper != null ) mHelper.dispose();
mHelper = null ;
}
Thanks a lot
Ok so I used shared preference to save my activity state but it only works fine when I try to enable a button with another free button, but it doesn't work with the in app purchase button (simply it let me do the purchase but the deactivated button never turns enabled after the purchase) So I don't know if there is a conflict between in app purchase and shared preference in my code?
Here is my edited code:
package com.aseng90_test.smiap2;
import android.content.Intent; import
android.content.SharedPreferences; import
android.support.v7.app.ActionBarActivity; import android.os.Bundle;
import android.util.Log; import android.view.View; import
android.widget.Button; import android.widget.Toast;
import com.aseng90_test.smiap2.util.IabHelper; import
com.aseng90_test.smiap2.util.IabResult; import
com.aseng90_test.smiap2.util.Purchase;
public class MainScreen extends ActionBarActivity {
private static final String TAG = "com.aseng90_test.smiap2";
IabHelper mHelper;
static final String ITEM_SKU = "com.aseng90_test.smiap2_button55";
static final String ITEM_SKU2 = "com.aseng90_test.smiap2_buyact22";
static final String ITEM_SKU3 = "com.aseng90_test.smiap2_buyact33";
static final String ITEM_SKU4 = "com.aseng90_test.smiap2_buyall_1";
private Button Activity1;
private Button Activity2;
private Button Activity3;
private Button buyButton;
private Button buyAct2;
private Button buyAct3;
private Button buyAll;
private Button EAct4; private Button Act4;
private SharedPreferences prefs;
private String prefName = "MyPref";
boolean Activity1_isEnabled;
boolean Activity2_isEnabled;
boolean Activity3_isEnabled;
boolean Act4_isEnabled;
boolean buyButton_isEnabled;
boolean buyAct2_isEnabled;
boolean buyAct3_isEnabled;
boolean buyAll_isEnabled;
boolean EAct4_isEnabled;
private static final String Activity1_state = "Activity1_state";
private static final String Activity2_State = "Activity2_state";
private static final String Activity3_State = "Activity3_state";
private static final String buyButton_State = "buyButton_state";
private static final String buyAct2_State = "buyAct2_state";
private static final String buyAct3_State = "buyAct3_state";
private static final String buyAll_State = "buyAll_state";
private static final String Act4_State = "Act4_state";
private static final String EAct4_State = "EAct4_state";
public void buyClick(View view) {
mHelper.launchPurchaseFlow(this, ITEM_SKU, 10001,
mPurchaseFinishedListener, "mypurchasetoken");
}
public void buyAct2 (View view){
mHelper.launchPurchaseFlow(this, ITEM_SKU2, 10002, mPurchaseFinishedListener, "buyact2");
}
public void buyAct3 (View view){
mHelper.launchPurchaseFlow(this,ITEM_SKU3, 10003, mPurchaseFinishedListener, "buyact3");
}
public void buyAll (View view){
mHelper.launchPurchaseFlow(this, ITEM_SKU4,10004, mPurchaseFinishedListener, "buyall");
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
buyButton = (Button) findViewById(R.id.buyButton);
buyAct2 = (Button) findViewById(R.id.buyact2);
buyAct3 = (Button) findViewById(R.id.buyact3);
buyAll = (Button) findViewById(R.id.buyall);
Activity1 = (Button) findViewById(R.id.act1);
Activity2 = (Button) findViewById(R.id.act2);
Activity3 = (Button) findViewById(R.id.act3);
EAct4 = (Button) findViewById(R.id.eact4);
Act4 = (Button) findViewById(R.id.act4);
String base64EncodedPublicKey =
"";
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.startSetup(new
IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result)
{
if (!result.isSuccess()) {
Log.d(TAG, "In-app Billing setup failed: " + result);
} else {
Log.d(TAG, "In-app Billing is set up OK");
}
}
});
}
public void EACT4 (View view) {
EAct4.setEnabled(false);
Act4.setEnabled(true);
}
public void ACT4 (View view){
Toast.makeText(MainScreen.this,
"ACt4 Clicked", Toast.LENGTH_LONG).show();
}
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data)
{
if (!mHelper.handleActivityResult(requestCode,
resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
= new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result,
Purchase purchase)
{
if (result.isFailure()) {
// Handle error
return;
}
if (purchase.getSku().equals(ITEM_SKU)) {
Activity1.setEnabled(true);
buyButton.setEnabled(false);
}
if (purchase.getSku().equals(ITEM_SKU2)){
Activity2.setEnabled(true);
buyAct2.setEnabled(false);
}
if (purchase.getSku().equals(ITEM_SKU3)){
Activity3.setEnabled(true);
buyAct3.setEnabled(false);
}
if (purchase.getSku().equals(ITEM_SKU4)) {
Activity1.setEnabled(true);
Activity2.setEnabled(true);
Activity3.setEnabled(true);
buyAll.setEnabled(false);
buyButton.setEnabled(false);
buyAct2.setEnabled(false);
buyAct3.setEnabled(false);
}
}
};
public void Activity1 (View view)
{
startActivity(new Intent(MainScreen.this, Click1.class));
}
public void Activity2 (View view){
startActivity(new Intent(MainScreen.this, Activity2.class));
}
public void Activity3 (View view){
startActivity(new Intent(MainScreen.this, Activity3.class));
}
#Override
public void onDestroy() {
super.onDestroy();
if (mHelper != null ) mHelper.dispose();
mHelper = null ;
}
#Override
protected void onPause(){
super.onPause();
if (Act4.isEnabled()){
Act4_isEnabled = true;
}
else {
Act4_isEnabled = false;
}
if (Activity1.isEnabled()){
Activity1_isEnabled = true;
}
else {
Activity1_isEnabled = false;
}
if (Activity2.isEnabled()){
Activity2_isEnabled = true;
}
else {
Activity2_isEnabled = false;
}
if (Activity3.isEnabled()){
Activity3_isEnabled = true;
}
else {
Activity3_isEnabled = false;
}
if (buyButton.isEnabled()){
buyButton_isEnabled = true;
}
else {
buyButton_isEnabled = false;
}
if (buyAct2.isEnabled()){
buyAct2_isEnabled = true;
}
else {
buyAct2_isEnabled = false;
}
if (buyAct3.isEnabled()){
buyAct3_isEnabled = true;
}
else {
buyAct3_isEnabled = false;
}
if (buyAll.isEnabled()){
buyAll_isEnabled = true;
}
else {
buyAll_isEnabled = false;
}
prefs = getSharedPreferences(prefName,MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(Act4_State,Act4_isEnabled);
editor.putBoolean(EAct4_State,EAct4_isEnabled);
editor.putBoolean(Activity1_state,Activity1_isEnabled);
editor.putBoolean(Activity2_State,Activity2_isEnabled);
editor.putBoolean(Activity3_State,Activity3_isEnabled);
editor.putBoolean(buyButton_State,buyButton_isEnabled);
editor.putBoolean(buyAct2_State,buyAct2_isEnabled);
editor.putBoolean(buyAct3_State,buyAct3_isEnabled);
editor.putBoolean(buyAll_State,buyAll_isEnabled);
editor.apply();
}
#Override
protected void onResume(){
super.onResume();
prefs = getSharedPreferences(prefName,MODE_PRIVATE);
Act4.setEnabled(prefs.getBoolean(Act4_State,false));
Activity1.setEnabled(prefs.getBoolean(Activity1_state,false));
Activity2.setEnabled(prefs.getBoolean(Activity2_State,false));
Activity3.setEnabled(prefs.getBoolean(Activity3_State,false));
EAct4.setEnabled(prefs.getBoolean(EAct4_State,true));
buyButton.setEnabled(prefs.getBoolean(buyButton_State,true));
buyAct2.setEnabled(prefs.getBoolean(buyAct2_State,true));
buyAct3.setEnabled(prefs.getBoolean(buyAct3_State,true));
buyAll.setEnabled(prefs.getBoolean(buyAll_State,true));
}
Thanks again
When your activity is restarted, it does not save the state of its views from the previous instance. Thus you probably need to save your state data somewhere so that when you restart your activity, you can then reset your views looking at this saved state data.You can make use of "SharedPreferences" class. SharedPreferences lets you store information in key-value pair. I guess that serves your purpose.
SharedPreferences pref = getApplicationContext().getSharedPreferences("ProductCache", 0);
// 0 - for private mode
//First parameter is the name of your preference file.Could be "ProductCache" in your case.
// Default 0 for private access.
SharedPreferences.Editor editor = pref.edit(); // edit your preference file
editor.putString("KEY","VALUE");//save strings
editor.putBoolean("KEY",true);//save booleans or any other type of data.
editor.commit(); //commit your changes
You can set that your product is already bought in your mPurchaseFinishedListener.Next time your app is opened you can check the same file by using the same "keys" that you used to store information to check if the product is already bought and then you can set your views accordingly.
If this doesn't serve your purpose, then you might have to start implementing a SQLite database that keeps track of all purchases. Please go through this article on Android Developers as it might help you further:
http://developer.android.com/training/basics/data-storage/index.html
Hope this helps. Cheers!
Use CheckOut library it does everything for you, you can check for the purchased items and based on the sku you can enable or disable purchase button.
Well i have created a Google+ Signin successfully.
And i'm trying to signout the g+ from the other activity.
I tried the below code it's not working as per my expectation.
what I wanted is the app signin from LoginActivity & signout from MainActivity.
Below is my LoginActivity Code.
import java.util.ArrayList;
import java.util.List;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.TargetApi;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.plus.Plus;
//import android.app.LoaderManager.LoaderCallbacks;
//import android.content.CursorLoader;
//import android.content.Loader;
/**
* A login screen that offers login via email/password.
*/
public class LoginActivity extends FragmentActivity implements LoaderCallbacks<Cursor>, OnClickListener, com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks, com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener {
/* Request code used to invoke sign in user interactions. */
private static final int RC_SIGN_IN = 0;
/* Client used to interact with Google APIs. */
public static GoogleApiClient mGoogleApiClient;
/* A flag indicating that a PendingIntent is in progress and prevents
* us from starting further intents.
*/
private boolean mIntentInProgress;
/* Track whether the sign-in button has been clicked so that we know to resolve
* all issues preventing sign-in without waiting.
*/
private boolean mSignInClicked;
/* Store the connection result from onConnectionFailed callbacks so that we can
* resolve them when the user clicks sign-in.
*/
private ConnectionResult mConnectionResult;
/**
* A dummy authentication store containing known user names and passwords.
* TODO: remove after connecting to a real authentication system.
*/
private static final String[] DUMMY_CREDENTIALS = new String[] {
"foo#example.com:hello", "bar#example.com:world" };
/**
* Keep track of the login task to ensure we can cancel it if requested.
*/
private UserLoginTask mAuthTask = null;
// UI references.
private AutoCompleteTextView mEmailView;
private EditText mPasswordView;
private View mProgressView;
private View mLoginFormView;
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
mGoogleApiClient.connect();
}
/*
#Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
*/
public void disconnect(){
if (mGoogleApiClient.isConnected()) {
Log.e("LoginActivity()","before signout" + mGoogleApiClient.isConnected());
mGoogleApiClient.disconnect();
Log.e("LoginActivity()","after signout" + mGoogleApiClient.isConnected());
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API)
.addScope(Plus.SCOPE_PLUS_LOGIN)
.build();
/* Button signin = (Button)findViewById(R.id.sign_in_button);
signin.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (!mGoogleApiClient.isConnecting()) {
mSignInClicked = true;
resolveSignInErrors();
}
}
}); */
findViewById(R.id.sign_in_button).setOnClickListener(this);
Button signout = (Button)findViewById(R.id.signout_in_button);
signout.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Log.e("LoginActivity()","before signout" + mGoogleApiClient.isConnected());
if (mGoogleApiClient.isConnected()) {
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
}
Log.e("LoginActivity()","After signout" + mGoogleApiClient.isConnected());
}
});
// Set up the login form.
mEmailView = (AutoCompleteTextView) findViewById(R.id.email);
populateAutoComplete();
mPasswordView = (EditText) findViewById(R.id.password);
mPasswordView
.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView textView, int id,
KeyEvent keyEvent) {
if (id == R.id.login || id == EditorInfo.IME_NULL) {
attemptLogin();
return true;
}
return false;
}
});
Button mEmailSignInButton = (Button) findViewById(R.id.email_sign_in_button);
mEmailSignInButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
attemptLogin();
}
});
mLoginFormView = findViewById(R.id.login_form);
mProgressView = findViewById(R.id.login_progress);
}
//result.getResolution().getIntentSender()
/* A helper method to resolve the current ConnectionResult error. */
private void resolveSignInError() {
// if (mConnectionResult.hasResolution()) {
try {
mIntentInProgress = true;
startIntentSenderForResult(mConnectionResult.getResolution().getIntentSender(),
RC_SIGN_IN, null, 0, 0, 0);
} catch (SendIntentException e) {
// The intent was canceled before it was sent. Return to the default
// state and attempt to connect to get an updated ConnectionResult.
mIntentInProgress = false;
mGoogleApiClient.connect();
}
// }
}
private void populateAutoComplete() {
if (VERSION.SDK_INT >= 14) {
// Use ContactsContract.Profile (API 14+)
//getLoaderManager().initLoader(0, null, this);
getSupportLoaderManager().initLoader(0, null, this);
} else if (VERSION.SDK_INT >= 8) {
// Use AccountManager (API 8+)
new SetupEmailAutoCompleteTask().execute(null, null);
}
}
/**
* Attempts to sign in or register the account specified by the login form.
* If there are form errors (invalid email, missing fields, etc.), the
* errors are presented and no actual login attempt is made.
*/
public void attemptLogin() {
if (mAuthTask != null) {
return;
}
// Reset errors.
mEmailView.setError(null);
mPasswordView.setError(null);
// Store values at the time of the login attempt.
String email = mEmailView.getText().toString();
String password = mPasswordView.getText().toString();
boolean cancel = false;
View focusView = null;
// Check for a valid password, if the user entered one.
if (!TextUtils.isEmpty(password) && !isPasswordValid(password)) {
mPasswordView.setError(getString(R.string.error_invalid_password));
focusView = mPasswordView;
cancel = true;
}
// Check for a valid email address.
if (TextUtils.isEmpty(email)) {
mEmailView.setError(getString(R.string.error_field_required));
focusView = mEmailView;
cancel = true;
} else if (!isEmailValid(email)) {
mEmailView.setError(getString(R.string.error_invalid_email));
focusView = mEmailView;
cancel = true;
}
if (cancel) {
// There was an error; don't attempt login and focus the first
// form field with an error.
focusView.requestFocus();
} else {
// Show a progress spinner, and kick off a background task to
// perform the user login attempt.
showProgress(true);
mAuthTask = new UserLoginTask(email, password);
mAuthTask.execute((Void) null);
}
}
private boolean isEmailValid(String email) {
// TODO: Replace this with your own logic
return email.contains("#");
}
private boolean isPasswordValid(String password) {
// TODO: Replace this with your own logic
return password.length() > 4;
}
/**
* Shows the progress UI and hides the login form.
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
public void showProgress(final boolean show) {
// On Honeycomb MR2 we have the ViewPropertyAnimator APIs, which allow
// for very easy animations. If available, use these APIs to fade-in
// the progress spinner.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
int shortAnimTime = getResources().getInteger(
android.R.integer.config_shortAnimTime);
mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
mLoginFormView.animate().setDuration(shortAnimTime)
.alpha(show ? 0 : 1)
.setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
mLoginFormView.setVisibility(show ? View.GONE
: View.VISIBLE);
}
});
mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
mProgressView.animate().setDuration(shortAnimTime)
.alpha(show ? 1 : 0)
.setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
mProgressView.setVisibility(show ? View.VISIBLE
: View.GONE);
}
});
} else {
// The ViewPropertyAnimator APIs are not available, so simply show
// and hide the relevant UI components.
mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
mLoginFormView.setVisibility(show ? View.GONE : View.VISIBLE);
}
}
#TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
#Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
return new CursorLoader(this,
// Retrieve data rows for the device user's 'profile' contact.
Uri.withAppendedPath(ContactsContract.Profile.CONTENT_URI,
ContactsContract.Contacts.Data.CONTENT_DIRECTORY),
ProfileQuery.PROJECTION,
// Select only email addresses.
ContactsContract.Contacts.Data.MIMETYPE + " = ?",
new String[] { ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE },
// Show primary email addresses first. Note that there won't be
// a primary email address if the user hasn't specified one.
ContactsContract.Contacts.Data.IS_PRIMARY + " DESC");
}
#Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
List<String> emails = new ArrayList<String>();
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
emails.add(cursor.getString(ProfileQuery.ADDRESS));
cursor.moveToNext();
}
addEmailsToAutoComplete(emails);
}
#Override
public void onLoaderReset(Loader<Cursor> cursorLoader) {
}
private interface ProfileQuery {
String[] PROJECTION = { ContactsContract.CommonDataKinds.Email.ADDRESS,
ContactsContract.CommonDataKinds.Email.IS_PRIMARY, };
int ADDRESS = 0;
int IS_PRIMARY = 1;
}
/**
* Use an AsyncTask to fetch the user's email addresses on a background
* thread, and update the email text field with results on the main UI
* thread.
*/
class SetupEmailAutoCompleteTask extends
AsyncTask<Void, Void, List<String>> {
#Override
protected List<String> doInBackground(Void... voids) {
ArrayList<String> emailAddressCollection = new ArrayList<String>();
// Get all emails from the user's contacts and copy them to a list.
ContentResolver cr = getContentResolver();
Cursor emailCur = cr.query(
ContactsContract.CommonDataKinds.Email.CONTENT_URI, null,
null, null, null);
while (emailCur.moveToNext()) {
String email = emailCur
.getString(emailCur
.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
emailAddressCollection.add(email);
}
emailCur.close();
return emailAddressCollection;
}
#Override
protected void onPostExecute(List<String> emailAddressCollection) {
addEmailsToAutoComplete(emailAddressCollection);
}
}
private void addEmailsToAutoComplete(List<String> emailAddressCollection) {
// Create adapter to tell the AutoCompleteTextView what to show in its
// dropdown list.
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
LoginActivity.this,
android.R.layout.simple_dropdown_item_1line,
emailAddressCollection);
mEmailView.setAdapter(adapter);
}
/**
* Represents an asynchronous login/registration task used to authenticate
* the user.
*/
public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {
private final String mEmail;
private final String mPassword;
UserLoginTask(String email, String password) {
mEmail = email;
mPassword = password;
}
#Override
protected Boolean doInBackground(Void... params) {
// TODO: attempt authentication against a network service.
try {
// Simulate network access.
Thread.sleep(2000);
} catch (InterruptedException e) {
return false;
}
for (String credential : DUMMY_CREDENTIALS) {
String[] pieces = credential.split(":");
if (pieces[0].equals(mEmail)) {
// Account exists, return true if the password matches.
return pieces[1].equals(mPassword);
}
}
// TODO: register the new account here.
return true;
}
#Override
protected void onPostExecute(final Boolean success) {
mAuthTask = null;
showProgress(false);
if (success) {
finish();
} else {
mPasswordView
.setError(getString(R.string.error_incorrect_password));
mPasswordView.requestFocus();
}
}
#Override
protected void onCancelled() {
mAuthTask = null;
showProgress(false);
}
}
#Override
public void onConnectionFailed(ConnectionResult result) {
// TODO Auto-generated method stub
if (!mIntentInProgress) {
// Store the ConnectionResult so that we can use it later when the user clicks
// 'sign-in'.
mConnectionResult = result;
if (mSignInClicked) {
// The user has already clicked 'sign-in' so we attempt to resolve all
// errors until the user is signed in, or they cancel.
resolveSignInError();
}
}
}
#Override
protected void onActivityResult(int requestCode, int responseCode, Intent intent) {
//TODO Auto-generated method stub
if (requestCode == RC_SIGN_IN) {
if (responseCode != RESULT_OK) {
mSignInClicked = false;
}
mIntentInProgress = false;
if (!mGoogleApiClient.isConnecting()) {
mGoogleApiClient.connect();
}
}
}
#Override
public void onConnected(Bundle arg0) {
// TODO Auto-generated method stub
mSignInClicked = false;
Toast.makeText(this, "User is connected!", Toast.LENGTH_LONG).show();
Log.e("LoginActivity()","onconnected status :" + mGoogleApiClient.isConnected());
Intent i = new Intent(this,MainActivity.class);
LoginActivity.this.startActivity(i);
}
#Override
public void onConnectionSuspended(int arg0) {
// TODO Auto-generated method stub
mGoogleApiClient.connect();
}
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (v.getId() == R.id.sign_in_button
&& !mGoogleApiClient.isConnecting()) {
mSignInClicked = true;
resolveSignInError();
}
}
}
And Layout for this activity_login.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.dotncube.gmailtest.LoginActivity" >
<!-- Login progress -->
<ProgressBar
android:id="#+id/login_progress"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:visibility="gone" />
<ScrollView
android:id="#+id/login_form"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="#+id/email_login_form"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<AutoCompleteTextView
android:id="#+id/email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/prompt_email"
android:inputType="textEmailAddress"
android:maxLines="1"
android:singleLine="true" />
<EditText
android:id="#+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/prompt_password"
android:imeActionId="#+id/login"
android:imeActionLabel="#string/action_sign_in_short"
android:imeOptions="actionUnspecified"
android:inputType="textPassword"
android:maxLines="1"
android:singleLine="true" />
<Button
android:id="#+id/email_sign_in_button"
style="?android:textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="#string/action_sign_in"
android:textStyle="bold" />
<com.google.android.gms.common.SignInButton
android:id="#+id/sign_in_button"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="#+id/signout_in_button"
style="?android:textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Signout from google"
android:textStyle="bold" />
</LinearLayout>
</ScrollView>
</LinearLayout>
And in MainActivity I'm calling signout function of LoginActivity.
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void signout(View v){
LoginActivity obj = new LoginActivity();
obj.disconnect();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
What does "sign out" mean to you? Should the user expect to re-select their account? Or do you want to completely deauthorize your app so the next time they use it they'll see the account picker and sign-in dialog?
If you just want them to see the account picker next time, call Plus.AccountApi.clearDefaultAccount(...). If you want your app deauthorized, call Plus.AccountApi.revokeAccessAndDisconnect(...) and wait for the response.
https://developer.android.com/reference/com/google/android/gms/plus/Account.html