Notify users for new version of Android app - android

I want to show a notification or dialog (when app opens) if the current installed app is not the Updated Version (available in play store).
How can i do that?

add this dependency to your gradle file..
com.github.rampo.updatechecker:library:2.1.8
And try this code in your Activity..
public static String NEW_VERSION = "1.1.0";
public void checkForAppUpdate () {
try {
if (!((Activity) context).isFinishing()) {
UpdateChecker.setNotice(Notice.NOTIFICATION);
UpdateChecker.setNoticeIcon(R.drawable.your_notification_logo);
String s = "Hello User, New version of this application is now available on play store.";
if (Comparator.isVersionDownloadableNewer((Activity) context, NEW_VERSION)){
SharedPreferences pref = context.getSharedPreferences(UpdateChecker.PREFS_FILENAME, 0);
boolean b = pref.getBoolean(UpdateChecker.DONT_SHOW_AGAIN_PREF_KEY + NEW_VERSION, false);
if (!b) {
displayAlertDialogforPlayStore(context, "Update Available", s);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
And Function displayAlertDialogforPlayStore() is...
public void displayAlertDialogforPlayStore(final Context context, String title,
String message) {
try {
final AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setIcon(R.drawable.your_notification_logo);
if (title != null) {
alert.setTitle(title);
}
alert.setMessage(message);
alert.setPositiveButton("Update Now", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
final String appPackageName = context.getPackageName();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("market://details?id=" + appPackageName));
context.startActivity(intent);
}
});
alert.setNegativeButton("Later", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
alert.show();
} catch (Exception e) {
e.printStackTrace();
}
}
This code display both notification and alertDailog for update.

You can use Firebase notifications as described here. You can choose your segment (e.g. app version) as described here.

Related

Class Context from other class android

I have two Classes (MainActivity & Dialogs)
I am trying to call the Dialogs Class (which as a context) to the MainAcitivity;
I have tried
Dialogs WorkOnDialog = (Dialogs)context;
WorkOnDialog.WorkOnSavedDialog();
This is my MainAcitivty
public class MainActivity extends AppCompatActivity {
Context context = this;
boolean WorkOn = false;
boolean WorkOff = false;
Dialogs WorkOnSaveDialog;
// Dialogs WorkOnSaveDialog = (Dialogs) context;
// Dialogs WorkOffSaveDialog = (Dialogs)context;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//Press Work On Button
public void WorkOnClicked(View v) {
//Creates ImageButton var for ActionListener
ImageButton WorkOnClicked = (ImageButton) findViewById(R.id.WorkOn);
WorkOnClicked.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Gets & Sets Date, Filename, Data Content
// Creates Output Stream to save to file
String nowDate = DateFormat.getDateTimeInstance().format(new Date());
String filename = "WorkOnFile";
String string = nowDate + " Work On";
FileOutputStream outputStream;
File file = new File(Environment.getDataDirectory(), filename);
System.out.println("Work On Button CLicked");
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
outputStream.write(string.getBytes());
outputStream.close();
System.out.println("!Wrote " + string + " !");
System.out.println("Wrote at " + file);
WorkOn = true;
} catch (Exception e) {
e.printStackTrace();
}
Dialogs WorkOnDialog = (Dialogs)context;
WorkOnDialog.WorkOnSavedDialog();
}
});
}
//Press WorkOff Button
public void WorkOffClicked(View v) {
//Creates ImageButton var for ActionListener
ImageButton WorkOffClicked = (ImageButton) findViewById(R.id.WorkOff);
WorkOffClicked.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Gets & Sets Date, Filename, Data Content
// Creates Output Stream to save to file
String nowDate = DateFormat.getDateTimeInstance().format(new Date());
String filename = "WorkOffFile";
String string = nowDate + " Work Off";
FileOutputStream outputStream;
File file = new File(Environment.getDataDirectory(), filename);
System.out.println(" Work Off Button CLicked");
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
outputStream.write(string.getBytes());
outputStream.close();
System.out.println("!Wrote " + string + " !");
System.out.println("Wrote at " + file);
WorkOn=false;
} catch (Exception e) {
e.printStackTrace();
}
// WorkOffSaveDialog.WorkOffSavedDialog();
}
});
This is my Dialogs class
public class Dialogs extends AppCompatActivity {
public Context context = this;
public void WorkOnSavedDialog() {
new AlertDialog.Builder(context)
.setTitle("Work On File Saved")
.setMessage("[Displaying for Test] Work On File Saved")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// continue with delete
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
public void WorkOffSavedDialog() {
new AlertDialog.Builder(context)
.setTitle("Work Off File Saved")
.setMessage("[Displaying for Test] Work Off File Saved")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// continue with delete
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
}
Can anyone explain to me why I am unable to call this "Dialogs" Class within the main method?
I have searched about calling methods with context, and everything I found did not work out, what exactly is going wrong and why?
You need to make constructor to your Dialog class and pass the MainActivity context to this constructor :
public class Dialogs extends AppCompatActivity {
public Context context;
public Dialogs(Context context) {
this.context = context;
}
public void WorkOnSavedDialog() {
new AlertDialog.Builder(context)
.setTitle("Work On File Saved")
.setMessage("[Displaying for Test] Work On File Saved")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// continue with delete
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
public void WorkOffSavedDialog() {
new AlertDialog.Builder(context)
.setTitle("Work Off File Saved")
.setMessage("[Displaying for Test] Work Off File Saved")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// continue with delete
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
}

Use parse.com in android app

I'm new in android developer and I use parse.com in my first android app.
My problem is when the user singup to the app, the user save in the core. but then the app crashes.
This is my code:
save = (Button) findViewById(R.id.saveButton);
save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!(password.getText().toString().equals(againPassword.getText().toString()))) {
Toast.makeText(getApplicationContext(), "You have mistake in password!", Toast.LENGTH_SHORT).show();
} else {
ParseUser newUser = new ParseUser();
newUser.put("name", firstName.getText().toString());
newUser.put("lastName", lastName.getText().toString());
newUser.setEmail(email.getText().toString());
newUser.setUsername(userName.getText().toString());
newUser.setPassword(password.getText().toString());
newUser.put("rosterArray", rosterArray);
myParse parse = new myParse();
try {
parse.saveUserInParse(newUser);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
});
The code of methed 'saveUserInParse' is
public void saveUserInParse(ParseUser newUser)
{
newUser.signUpInBackground(new SignUpCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
AlertDialog.Builder singUpSucceed = new AlertDialog.Builder(context);
singUpSucceed.setTitle("Sing up succeed!!!");
singUpSucceed.setCancelable(true);
singUpSucceed.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert11 = singUpSucceed.create();
alert11.show();
} else {
String theMessage = e.getMessage();
AlertDialog.Builder singUpSucceed = new AlertDialog.Builder(context);
singUpSucceed.setTitle("Sing up feild!!!");
singUpSucceed.setMessage(theMessage);
singUpSucceed.setCancelable(true);
singUpSucceed.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert11 = singUpSucceed.create();
alert11.show();
}
}
});
}
What did I do wrong? This problam is also in login method.
Thank you.
Here is my demo project for parse Sample Parse, you an use for refrence.

how can open alert dialog box in android

I want to open alert dialog box after successfully submitted data.
I am using following code but not work.
dialog = ProgressDialog.show(TanantDetails.this, "", "Please Wait...", true);
new Thread(new Runnable() {
public void run() {
String response;
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences sp=getSharedPreferences("login",MODE_WORLD_READABLE);
try {
Utility utility=new Utility();
//
new_url=url+mobile_no.getText().toString();
response = utility.getResponse(utility.urlEncode(new_url));
dialog.dismiss();
if (response.equals("Success"))
{
AlertDialog alertbox = new AlertDialog.Builder(getBaseContext())
//.setIcon(R.drawable.no)
.setTitle("Submit successfully")
.setMessage("“Police will verify documents between preferred timing")
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
// do something when the button is clicked
public void onClick(DialogInterface arg0, int arg1) {
TanantDetails.this.finish();
Intent i=new Intent(getApplicationContext(),MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(i);
}
})
.show();
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Toast.makeText(getApplicationContext(), response, Toast.LENGTH_LONG).show();
}
}).start();
}
toast show the message response success.
I am new to android
Simple Alert Dialog
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Alert")
.setTitle("Warning");
AlertDialog alert =builder.create();
alert.show();
If you want to add ok, cancel buttons then add
builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User clicked OK button
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User clicked cancel button
}
});
Try this code:
new AlertDialog.Builder(this)
.setTitle("Your title")
.setMessage("Your message")
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Your code
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
})
.show();
Your alert dialog needs to be displayed on the UI thread. The code you are running is on a separate thread. In most cases when you want to update a UI element while in a separate thread it is done by using runOnUiThread()
Please see the code below
if (response.equals("Success"))
{
runOnUiThread(new Runnable() {
#Override
public void run() {
AlertDialog alertbox = new AlertDialog.Builder(getBaseContext())
//.setIcon(R.drawable.no)
.setTitle("Submit successfully")
.setMessage("“Police will verify documents between preferred timing")
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
// do something when the button is clicked
public void onClick(DialogInterface arg0, int arg1) {
TanantDetails.this.finish();
Intent i=new Intent(getApplicationContext(),MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(i);
}
}).show();
}
});
}

change URI with variable

hi advances i need your help, please. i have URI code
Intent intent = new Intent(Intent.ACTION_VIEW ,Uri.parse("http://xxx/dev/android/ATMnet-Mobile_v1.1_vc2.apk"));
i wanna change the last URI with variable like this
Intent intent = new Intent(Intent.ACTION_VIEW ,Uri.parse("http://xxx/dev/android/ATMnet-Mobile_v1.1_vc"+stringText+".apk"));
so, the version code (vc) can modified by variable which i write
and this is my full code, anyone could correct my code?
URL textUrl;
String StringBuffer;
String stringText = "";
try {
textUrl = new URL(textSource);
BufferedReader bufferReader = new BufferedReader(new InputStreamReader(textUrl.openStream()));
while ((StringBuffer = bufferReader.readLine()) != null)
{
stringText += StringBuffer;
}
bufferReader.close();
//textServer.setText(stringText);
} catch (MalformedURLException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
//textServer.setText(e.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
//textServer.setText(e.toString());
}
PackageManager manager = getPackageManager();
PackageInfo info;
try {
info = manager.getPackageInfo(getPackageName(), 0);
int version = info.versionCode;
if(Integer.parseInt(stringText) != version)
{
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder.setTitle(""+stringText+" "+version+" is Available.");
alertDialogBuilder
.setMessage("Do you want to download?")
.setCancelable(false)
.setPositiveButton("Yes",new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog,int id)
{
Intent intent = new Intent(Intent.ACTION_VIEW ,Uri.parse("http://xxx/dev/android/ATMnet-Mobile_v1.1_vc2.apk"));
startActivity(intent);
}
})
.setNegativeButton("No",new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog,int id)
{
dialog.cancel();
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
} catch (NameNotFoundException e)
{
e.printStackTrace();
}
i hope anyone can help me :'(
There is no problem in changes. Concatination avaliable and it works fine.
Use
Uri.parse("something" + str + ".apk")
Good luck!

Android cannot bind to service (In App-Billing)

I'm trying to implement in app-billing in my application, but I have a little problem with it. I'm using the example from android developer's site and everytime I start the activity which will connect to the billing service it's showing me a dialog that I cannot connect to server and when I press learn more it's going to a web page which is explaining me to update my android market app, but it's already the latest one. And the other thing, before implementing the code on my application I create a test application where I can connect with the same code and I don't get problems. But in my application I can't do that. Is there any connection with the developer api key, which you can use only in one application or something like that. Because I'm using the same for test and real app.
And here is my code if you can see something which is not really like it should be :
public class StampiiStore extends Activity {
String servername;
int userId;
int storageID;
RPCCommunicator rpc;
String path;
Button envelope1, envelope2, envelope3;
private static final String TAG = "STAMPII";
/**
* The SharedPreferences key for recording whether we initialized the
* database. If false, then we perform a RestoreTransactions request
* to get all the purchases for this user.
*/
private static final String DB_INITIALIZED = "db_initialized";
private mStampiiPurchaseObserver mStampiiPurchaseObserver;
private Handler mHandler;
private BillingService mBillingService;
private TextView mLogTextView;
private Cursor mOwnedItemsCursor;
private PurchaseDatabase mPurchaseDatabase;
private Set<String> mOwnedItems = new HashSet<String>();
/**
* The developer payload that is sent with subsequent
* purchase requests.
*/
private static final int DIALOG_CANNOT_CONNECT_ID = 1;
private static final int DIALOG_BILLING_NOT_SUPPORTED_ID = 2;
#SuppressWarnings("static-access")
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.store);
SystemDatabaseHelper sysDbHelper = new SystemDatabaseHelper(this, null, 1);
sysDbHelper.initialize(this);
ImageView icon = (ImageView) findViewById (R.id.store_img);
final int collId = getIntent().getIntExtra("collection_id",0);
Log.e("collId","collId : "+collId);
// Getting all variables from SharedPreferences to build the right path to images
servername = rpc.getCurrentServerName(this);
Log.d("","Current Server Name : "+servername);
userId = rpc.getUserId(this);
Log.d("","User Id : "+userId);
storageID = rpc.getCurrentStoragePath(this);
Log.d("","storage ID : "+storageID);
//
TextView colltitle = (TextView) findViewById(R.id.collection_title);
TextView sTitle = (TextView) findViewById(R.id.store_collId);
TextView collInfo = (TextView) findViewById(R.id.store_coll_info);
envelope1 = (Button) findViewById(R.id.buyone);
envelope1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mBillingService.requestPurchase("android.test.purchased", "");
}
});
envelope2 = (Button) findViewById(R.id.buytwo);
envelope2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mBillingService.requestPurchase("android.test.canceled", "");
}
});
envelope3 = (Button) findViewById(R.id.buythree);
envelope3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mBillingService.requestPurchase("com.stampii.stampii.envelopesthree", "");
}
});
mHandler = new Handler();
mStampiiPurchaseObserver = new mStampiiPurchaseObserver(mHandler);
mBillingService = new BillingService();
mBillingService.setContext(this);
mPurchaseDatabase = new PurchaseDatabase(this);
setupWidgets();
// Check if billing is supported.
ResponseHandler.register(mStampiiPurchaseObserver);
if (!mBillingService.checkBillingSupported()) {
showDialog(DIALOG_CANNOT_CONNECT_ID);
}
Button back = (Button) findViewById(R.id.store_back_button);
back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
boolean isLoggedIn = settings.getBoolean("isLoggedIn", false);
ImageButton sync = (ImageButton) findViewById(R.id.sync_store);
if(isLoggedIn){
sync.setVisibility(View.VISIBLE);
} else if(!isLoggedIn){
sync.setVisibility(View.GONE);
}
sync.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(StampiiStore.this, Synchronization.class);
intent.putExtra("process", 2);
startActivity(intent);
}
});
String titleSql = "SELECT title FROM collection_lang WHERE collection_id= " + collId + " AND lang_code='en_US'";
Cursor title = sysDbHelper.executeSQLQuery(titleSql);
if(title.getCount()==0){
title.close();
} else if(title.getCount()>0){
for(title.move(0); title.moveToNext(); title.isAfterLast()){
String collectionTitle = title.getString(title.getColumnIndex("title"));
sTitle.setText(collectionTitle);
if (collectionTitle.length() > 20){
String newTitle = collectionTitle.substring(0, 20);
colltitle.setText(newTitle + "...");
} else {
colltitle.setText(collectionTitle);
}
}
}
title.close();
String infoSql = "SELECT DISTINCT c.total_cards AS cardsCount, " +
" c.cards_per_envelope AS cardsPerEnvelope " +
"FROM collections AS c, collection_lang AS cl " +
"WHERE c.collection_id = cl.collection_id AND c.collection_id=" + collId;
Cursor info = sysDbHelper.executeSQLQuery(infoSql);
if(info.getCount()==0){
info.close();
} else if (info.getCount()>0){
info.moveToFirst();
int cardsCount = info.getInt(info.getColumnIndex("cardsCount"));
int cardsPerEnvelope = info.getInt(info.getColumnIndex("cardsPerEnvelope"));
collInfo.setText(cardsCount+" Stampii\n"+cardsPerEnvelope+" cards per envelope");
}
String sqlite2 = "SELECT media_id FROM collection_media WHERE collection_id="+collId+" AND media_type_id="+3018;
Cursor bg = sysDbHelper.executeSQLQuery(sqlite2);
if (bg.getCount() == 0) {
bg.close();
} else if (bg.getCount() > 0) {
for (bg.move(0); bg.moveToNext(); bg.isAfterLast()) {
int objectId = Integer.parseInt(bg.getString(bg.getColumnIndex("media_id")));
String filename = "mediacollection-"+objectId+".png";
//if(storageID==1){
path = rpc.getPublicPathsInternal(servername, 3018, filename, StampiiStore.this);
/*} else if(storageID==2){
path = rpc.getPublicPathsExternal(servername, 3007, objectId);
}*/
}
}
bg.close();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inTempStorage = new byte[3*1024];
Bitmap ops = BitmapFactory.decodeFile(path, options);
BitmapDrawable bitmapDrawable = new BitmapDrawable(ops);
icon.setBackgroundDrawable(bitmapDrawable);
Button promoCode = (Button) findViewById(R.id.promo_code_btn);
promoCode.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
SharedPreferences isSelectedCode = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
String isSelected = isSelectedCode.getString("isSelected", "");
Log.i("isSelected", "isSelected" + isSelected);
EditText input = new EditText(StampiiStore.this);
input.setText(isSelected);
final int loggedOut = getIntent().getIntExtra("statement", 0);
if(loggedOut==0){
new AlertDialog.Builder(getParent())
.setTitle("Promotional Code")
.setView(input)
.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Log.d("AlertDialog", "Positive");
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Log.d("AlertDialog","Negative");
dialog.cancel();
}
}).show();
} else if (loggedOut==1){
new AlertDialog.Builder(Collections.parentActivity)
.setTitle("Promotional Code")
.setView(input)
.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Log.d("AlertDialog", "Positive");
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Log.d("AlertDialog","Negative");
dialog.cancel();
}
}).show();
}
}
});
Button savedCodes = (Button) findViewById(R.id.saved_codes_btn);
savedCodes.setOnClickListener(new OnClickListener(){
public void onClick(View v){
Intent previewMessage = new Intent(getParent(), SavedCodes.class);
TabGroupActivity parentActivity = (TabGroupActivity)getParent();
parentActivity.startChildActivity("Saved Codes", previewMessage);
}
});
}
/**
* Sets up the UI.
*/
private void setupWidgets() {
//TODO: If need any changes in the UI!
}
/**
* If the database has not been initialized, we send a
* RESTORE_TRANSACTIONS request to Android Market to get the list of purchased items
* for this user. This happens if the application has just been installed
* or the user wiped data. We do not want to do this on every startup, rather, we want to do
* only when the database needs to be initialized.
*/
private void restoreDatabase() {
SharedPreferences prefs = getPreferences(MODE_PRIVATE);
boolean initialized = prefs.getBoolean(DB_INITIALIZED, false);
if (!initialized) {
mBillingService.restoreTransactions();
Toast.makeText(this, "Restoring Transactions", Toast.LENGTH_LONG).show();
}
}
private void prependLogEntry(CharSequence cs) {
SpannableStringBuilder contents = new SpannableStringBuilder(cs);
contents.append('\n');
contents.append(mLogTextView.getText());
mLogTextView.setText(contents);
}
private void logProductActivity(String product, String activity) {
SpannableStringBuilder contents = new SpannableStringBuilder();
contents.append(Html.fromHtml("<b>" + product + "</b>: "));
contents.append(activity);
prependLogEntry(contents);
}
//PurchaseObserver
private class mStampiiPurchaseObserver extends PurchaseObserver {
public mStampiiPurchaseObserver(Handler handler) {
super(StampiiStore.this, handler);
}
#Override
public void onBillingSupported(boolean supported) {
if (Consts.DEBUG) {
Log.i(TAG, "supported: " + supported);
}
if (supported) {
restoreDatabase();
envelope1.setEnabled(true);
envelope2.setEnabled(true);
envelope3.setEnabled(true);
} else {
showDialog(DIALOG_BILLING_NOT_SUPPORTED_ID);
}
}
#Override
public void onPurchaseStateChange(PurchaseState purchaseState, String itemId,
int quantity, long purchaseTime, String developerPayload) {
if (Consts.DEBUG) {
Log.i(TAG, "onPurchaseStateChange() itemId: " + itemId + " " + purchaseState);
}
if (developerPayload == null) {
logProductActivity(itemId, purchaseState.toString());
} else {
logProductActivity(itemId, purchaseState + "\n\t" + developerPayload);
}
if (purchaseState == PurchaseState.PURCHASED) {
mOwnedItems.add(itemId);
}
mOwnedItemsCursor.requery();
}
#Override
public void onRequestPurchaseResponse(RequestPurchase request,
ResponseCode responseCode) {
if (Consts.DEBUG) {
Log.d(TAG, request.mProductId + ": " + responseCode);
}
if (responseCode == ResponseCode.RESULT_OK) {
if (Consts.DEBUG) {
Log.i(TAG, "purchase was successfully sent to server");
}
logProductActivity(request.mProductId, "sending purchase request");
} else if (responseCode == ResponseCode.RESULT_USER_CANCELED) {
if (Consts.DEBUG) {
Log.i(TAG, "user canceled purchase");
}
logProductActivity(request.mProductId, "dismissed purchase dialog");
} else {
if (Consts.DEBUG) {
Log.i(TAG, "purchase failed");
}
logProductActivity(request.mProductId, "request purchase returned " + responseCode);
}
}
#Override
public void onRestoreTransactionsResponse(RestoreTransactions request,
ResponseCode responseCode) {
if (responseCode == ResponseCode.RESULT_OK) {
if (Consts.DEBUG) {
Log.d(TAG, "completed RestoreTransactions request");
}
// Update the shared preferences so that we don't perform
// a RestoreTransactions again.
SharedPreferences prefs = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean(DB_INITIALIZED, true);
edit.commit();
} else {
if (Consts.DEBUG) {
Log.d(TAG, "RestoreTransactions error: " + responseCode);
}
}
}
}
/**
* Called when this activity becomes visible.
*/
#Override
protected void onStart() {
super.onStart();
ResponseHandler.register(mStampiiPurchaseObserver);
}
/**
* Called when this activity is no longer visible.
*/
#Override
protected void onStop() {
super.onStop();
ResponseHandler.unregister(mStampiiPurchaseObserver);
}
#Override
protected void onDestroy() {
super.onDestroy();
mPurchaseDatabase.close();
mBillingService.unbind();
}
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_CANNOT_CONNECT_ID:
return createDialog("Server cannot Connect",
"Server cannot connect");
case DIALOG_BILLING_NOT_SUPPORTED_ID:
return createDialog("Billing not supported",
"Billing not supported");
default:
return null;
}
}
/**
* Replaces the language and/or country of the device into the given string.
* The pattern "%lang%" will be replaced by the device's language code and
* the pattern "%region%" will be replaced with the device's country code.
*
* #param str the string to replace the language/country within
* #return a string containing the local language and region codes
*/
private String replaceLanguageAndRegion(String str) {
// Substitute language and or region if present in string
if (str.contains("%lang%") || str.contains("%region%")) {
Locale locale = Locale.getDefault();
str = str.replace("%lang%", locale.getLanguage().toLowerCase());
str = str.replace("%region%", locale.getCountry().toLowerCase());
}
return str;
}
private Dialog createDialog(String titleId, String messageId) {
String helpUrl = replaceLanguageAndRegion(getString(R.string.help_url));
if (Consts.DEBUG) {
Log.i(TAG, helpUrl);
}
final Uri helpUri = Uri.parse(helpUrl);
AlertDialog.Builder builder = null;
final int loggedOut = getIntent().getIntExtra("statement", 0);
if(loggedOut==0){
builder = new AlertDialog.Builder(getParent());
builder.setTitle(titleId)
.setIcon(android.R.drawable.stat_sys_warning)
.setMessage(messageId)
.setCancelable(false)
.setPositiveButton(android.R.string.ok, null)
.setNegativeButton("Learn More", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Intent.ACTION_VIEW, helpUri);
startActivity(intent);
}
});
} else if(loggedOut==1){
builder = new AlertDialog.Builder(Collections.parentActivity);
builder.setTitle(titleId)
.setIcon(android.R.drawable.stat_sys_warning)
.setMessage(messageId)
.setCancelable(false)
.setPositiveButton(android.R.string.ok, null)
.setNegativeButton("Learn More", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Intent.ACTION_VIEW, helpUri);
startActivity(intent);
}
});
}
return builder.create();
}
#Override
public void onRestart(){
super.onRestart();
Intent previewMessage = new Intent(StampiiStore.this, StampiiStore.class);
TabGroupActivity parentActivity = (TabGroupActivity)getParent();
parentActivity.startChildActivity("StampiiStore", previewMessage);
this.finish();
}
}
And here is how I'm declaring the service in manifest file :
<service android:name="BillingService" />
<receiver android:name="BillingReceiver">
<intent-filter>
<action android:name="com.android.vending.billing.IN_APP_NOTIFY" />
<action android:name="com.android.vending.billing.RESPONSE_CODE" />
<action android:name="com.android.vending.billing.PURCHASE_STATE_CHANGED" />
</intent-filter>
</receiver>
Any suggestions how to connect to the market?
I had the same issue and probably your mistake is the same as mine. I was using a TabHost in my activities and I find out that TabSpec cannot bind to services. So check this :
Using getApplicationContext().bindService instead of just bindService
on your activity solves the problem as it is using the higher level
application context.
Can't you debug through that code? Probably, mBillingService.checkBillingSupported() returns false, caused by failing BillingService.bindToMarketBillingService().
i was facing problem like that on my sony ericssion w8 2.1 android device
what i did are the following :
1) getApplicationContext().bindService (as android-droid said)
2) reset my mobile and downloaded apk for market 2.3.4 version and installed it
3) then open the market app on mobile and clicked accepted and when the app i quitted
4) rerunned the app it was working fine
note: before doing this i tested my app on other device using market version 3.x and it was working so i did all these things ...

Categories

Resources