Restore purchases in In-app Billing (IAB Version 3) android - java

Google has upgraded to IAB3(In App Billing version 3).
First what a issue in example code.. super.onDestroy() is missed.
I implemented v3 with the help of http://developer.android.com/google/play/billing/billing_integrate.html
It is tested on phone, does not work in emulator.It stuck in emulator.
My issue is, I did not see the API for restoring transactions. How can I restore purchases with IAB3? Is it mService.getPurchases(apiVersion, packageName, type, continuationToken). Has anyone tested this?? Does this returns purchased items from locally stored items or does it restore purchased items?
Uninstalling application does not have continuationToken. Should it be null?
And What about when the purchase state changes??
Please help!
Thanks in advance.
EDIT :
Google has updated the In app billing library and solved the super.onDestroy() issue.
They have also added some additional features.

To make item consumable you have to sent a consume request and you have to do that in separate thread.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1111) {
int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
Logger.printMessage(TAG, "on activity result reponse"
+ responseCode, Logger.DEBUG);
if (resultCode == RESULT_OK && responseCode == 0) {
try {
JSONObject jo = new JSONObject(purchaseData);
String sku = jo.getString("productId");
String title = jo.getString("title");
addChipsToBalance(sku);
final String token = jo.getString("purchaseToken");
Toast.makeText(BuyChipsActivity.this,
"You have bought " + title + ". Enjoy the game!",
Toast.LENGTH_SHORT).show();
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
Logger.printMessage(TAG, "inside run", Logger.DEBUG);
try {
int response = mService.consumePurchase(3,
getPackageName(), token);
Logger.printMessage(TAG, "inside run response"
+ response, Logger.DEBUG);
} catch (RemoteException e) {
// TODO Auto-generated catch block
Logger.printMessage(TAG, "exception here 1",
Logger.DEBUG);
e.printStackTrace();
}
}
}).start();
// alert("You have bought the " + sku +
// ". Excellent choice, adventurer!");
} catch (JSONException e) {
// alert("Failed to parse purchase data.");
e.printStackTrace();
}
}
}
But sometimes consume request is not completed on google end so you may want to query the purchased item list and consume it with the purchase token. I did like this
private void showPreviousPurchases() {
Logger.printMessage(TAG, "previous purchases", Logger.DEBUG);
if (mService == null) {
Toast.makeText(this, "Something Went Wrong. Try later",
Toast.LENGTH_LONG).show();
return;
}
Bundle ownedItems = null;
;
try {
ownedItems = mService.getPurchases(3, getPackageName(), "inapp",
null);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (ownedItems == null) {
Logger.printMessage(TAG, "criical error ", Logger.DEBUG);
return;
}
int response = ownedItems.getInt("RESPONSE_CODE");
if (response == 0) {
ArrayList<String> ownedSkus = ownedItems
.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
ArrayList<String> purchaseDataList = ownedItems
.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
/* ArrayList<String> signatureList = ownedItems
.getStringArrayList("INAPP_DATA_SIGNATURE");
String continuationToken = ownedItems
.getString("INAPP_CONTINUATION_TOKEN");*/
for (int i = 0; i < purchaseDataList.size(); ++i) {
String purchaseData = purchaseDataList.get(i);
Logger.printMessage(TAG, "json = " + purchaseData,
Logger.DEBUG);
// String signature = signatureList.get(i);
String sku = ownedSkus.get(i);
addChipsAndMakeItConsumable(purchaseData);
// do something with this purchase information
// e.g. display the updated list of products owned by user
}
// if continuationToken != null, call getPurchases again
// and pass in the token to retrieve more items
}
}
private void addChipsAndMakeItConsumable(String purchaseData) {
try {
JSONObject jo = new JSONObject(purchaseData);
String sku = jo.getString("productId");
// String title = jo.getString("title");
addChipsToBalance(sku);
final String token = jo.getString("purchaseToken");
Logger.printMessage(TAG, "id = " + sku, Logger.DEBUG);
Logger.printMessage(TAG, "inside run", Logger.DEBUG);
try {
int response = mService.consumePurchase(3, getPackageName(),
token);
Logger.printMessage(TAG, "inside run response" + response,
Logger.DEBUG);
} catch (RemoteException e) {
// TODO Auto-generated catch block
Logger.printMessage(TAG, "exception here 1", Logger.DEBUG);
e.printStackTrace();
}
// alert("You have bought the " + sku +
// ". Excellent choice, adventurer!");
} catch (JSONException e) {
// alert("Failed to parse purchase data.");
e.printStackTrace();
}
}

In your IabHelper.java which is an example in your /android-sdk/extras/google/play_billing/samples/ put this code to get all the item that has been purchased by the user. This will return an JSON array of purchased data. You can also used Purchase.java to parse with, which is available also in the samples folder.
public ArrayList<String> getAllPurchases() throws RemoteException{
Bundle ownedItems = mService.getPurchases(3, mContext.getPackageName(),"inapp", null);
int response = getResponseCodeFromBundle(ownedItems);
logDebug("Owned items response: " + String.valueOf(response));
if (response != BILLING_RESPONSE_RESULT_OK) {
logDebug("getPurchases() failed: " + getResponseDesc(response));
}
if (!ownedItems.containsKey(RESPONSE_INAPP_ITEM_LIST)
|| !ownedItems.containsKey(RESPONSE_INAPP_PURCHASE_DATA_LIST)
|| !ownedItems.containsKey(RESPONSE_INAPP_SIGNATURE_LIST)) {
logError("Bundle returned from getPurchases() doesn't contain required fields.");
}
ArrayList<String> purchaseDataList = ownedItems.getStringArrayList(RESPONSE_INAPP_PURCHASE_DATA_LIST);
return purchaseDataList;
}
And into your Main activity
public class MainActivity extends Activity{
private IabHelper mHelper;
private String arrayString;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHelper = new IabHelper(this,"YOUR PUBLIC KEY" );
mHelper.enableDebugLogging(true);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) { // Oh noes, there was a problem.
Toast.makeText(this,"Problem setting up in-app billing: " + result,Toast.LENGTH_LONG).show();
return;
}
arrayString=mHelper.getAllPurchases().toString();
Log.d("Purchases: ",""+arrayString);
array = new JSONArray(arrayString);
for (int i = 0; i < array.length(); i++) {
JSONObject row = array.getJSONObject(i);
productId=row.getString("productId"); //this will get the product id's that has been purchased.
Log.e("To be restored:", " PRODUCT ID's "+productId);
}
});
}
}
I hope this will help you. ^_^ Thanks.

Related

Make recursive API call using Retrofit

I'm implementing pagination concept in my android application to store a very large
data in sqlite database.
I want to make a call to an API using retrofit.
The api will return a flag if we reach the end of the table. If yes I will store
result in local database if not make another (recursive call) until we reach the end of the table
Once I debugged it the api is called twice only while it should make another
call based on my logic.
The code reach the end of the OnResponse callback and it never get called again
public void getDataOffset (final int processType, final int offset) {
try {
progressDialog = ProgressDialog.show(activity, "Loading", "Upload ,
Please wait...", true);
String url = mUrl ;
Request request = new Request();
request.setEmployeeID(EmployID);
request.setOffset(offset);
IAPI iAPI = Global.getIAPI(url,420,420);
Call<RetrofitCallResponse.OffsetResponse> call = iAPI.GetDataOffset(request);
call.enqueue(new Callback<RetrofitCallResponse.OffsetResponse>() {
#Override
public void onResponse(Call<RetrofitCallResponse.OffsetResponse> call, Response<RetrofitCallResponse.OffsetResponse> response) {
if (response.isSuccessful() && response.body() != null) {
if (!response.body().HasError) {
if (response.body().DataList().size() <= 0) {
hasError = true;
errorMessage = "Empty.";
progressDialog.dismiss();
callback.onCallComplete(hasError,errorMessage);
}
mList.addAll(response.body().DataList());
if (response.body().IsEndOfTable) {
DBConnections dbConnections = new DBConnections(context, null);
boolean isInserted;
isInserted = dbConnections.insertOffset(mList,processType,context);
dbConnections.close();
if (!isInserted) {
hasError = true;
errorMessage = "Result couldn't be saved locally";
}
hasError = false;
progressDialog.dismiss();
callback.onCallComplete(hasError,errorMessage);
} else {
getDataOffset (processType , mList.size());
}
} else {
hasError = true;
errorMessage = response.body().ErrorMessage;
progressDialog.dismiss();
callback.onCallComplete(hasError,errorMessage);
}
} else {
progressDialog.dismiss();
hasError = true;
errorMessage = "Response Code : " + response.code() + " " + response.toString();
}
// progressDialog.dismiss();
// callback.onCallComplete(hasError,errorMessage);
}
#Override
public void onFailure(Call<RetrofitCallResponse.OffsetResponse> call, Throwable t) {
t.printStackTrace();
hasError = true;
errorMessage = t.toString();
progressDialog.dismiss();
callback.onCallComplete(hasError,errorMessage);
}
});
} catch (Exception e ) {
hasError = true;
errorMessage = e.toString();
callback.onCallComplete(hasError,errorMessage);
}
}

android parse - getting email ids from parse User class

I'm trying to get e-mail addresses from parse User class,
here I'm trying to get other users email id's when logging in a
user, logged in users email id is showing but other users email ids
are not showing always null
I try use master key also, still not working ,
below is my java code.
String objectId;
protected TextView txtv;
protected TextView txtv1;
protected ImageView txtv2;
protected ImageView txtv3;
protected TextView individualOrganization;
Button emailPerson;
Button callPerson;
Button callPersonTelephone;
ParseObject personObject;
String personEmail;
String personNumber;
String personNumberTelephone;
ParseQuery query;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_single_individual);
txtv =(TextView)findViewById(R.id.txt123);
txtv1 =(TextView)findViewById(R.id.coporateSector);
txtv2 =(ImageView)findViewById(R.id.txt12345);
txtv3 =(ImageView)findViewById(R.id.txt123456);
individualOrganization =(TextView) findViewById(R.id.individualOrganization);
Intent i =getIntent();
objectId = i.getStringExtra("objectId");
ParseQuery<ParseUser> query = ParseUser.getQuery();
//query.put("useMasterKey", true);
query.setLimit(2000);
query.include("email");
query.getInBackground(objectId, new GetCallback<ParseUser>() {
#Override
public void done(final ParseUser object, com.parse.ParseException e) {
if (e == null) {
personObject = object;
String username = object.getString("firstname");
txtv.setText(username + " " + object.getString("lastname"));
String position = object.getString("position");
txtv1.setText(position);
String organizationName = object.getString("organizationName");
individualOrganization.setText(organizationName);
URL url = null;
try {
url = new URL("" + object.getString("image"));
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
Glide.with(getApplicationContext())
.load(String.valueOf(url))
.into(txtv2);
try {
url = new URL("" + object.getString("image"));
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
Glide.with(getApplicationContext())
.load(String.valueOf(url))
.into(txtv3);
// try{
// JSONObject jsonObject = parseObjectToJson(object);
// Log.d("Object", jsonObject.toString());
// Log.d("Email", "+" + object.get("email"));
// personNumber = jsonObject.getString("telephone");
// //personEmail = jsonObject.getString("email");
// personEmail= object.getEmail();
//
// }catch (JSONException je){
// }catch (ParseException pe){
// } catch (com.parse.ParseException e1) {
// e1.printStackTrace();
// }
} else {
}
callPerson = (Button) findViewById(R.id.individualMobile) ;
personNumber = object.getString("mobile");
callPerson.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i=new Intent(Intent.ACTION_DIAL, Uri.parse("tel:"+personNumber));
startActivity(i);
}
});
if(personNumber==null || personNumber.equals("") || personNumber.equals(" ")){
callPerson.setClickable(false);
callPerson.setEnabled(false);
callPerson.setVisibility(View.GONE);
}
else{
callPerson.setEnabled(true);
callPerson.setClickable(true);
callPerson.setVisibility(View.VISIBLE);
}
callPersonTelephone = (Button) findViewById(R.id.individualTelephone);
personNumberTelephone = object.getString("telephone");
callPersonTelephone.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i=new Intent(Intent.ACTION_DIAL,Uri.parse("tel:"+personNumberTelephone));
startActivity(i);
}
});
if(personNumberTelephone==null || personNumberTelephone.equals("") || personNumberTelephone.equals(" ") || personNumberTelephone.equals("6855")){
callPersonTelephone.setClickable(false);
callPersonTelephone.setEnabled(false);
callPersonTelephone.setVisibility(View.GONE);
}
else{
callPersonTelephone.setEnabled(true);
callPersonTelephone.setClickable(true);
callPersonTelephone.setVisibility(View.VISIBLE);
}
emailPerson = (Button)findViewById(R.id.individualEmail);
object.put("useMasterKey", true);
personEmail= object.getString("email");
emailPerson.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(Intent.ACTION_SEND);
i.setData(Uri.parse("mailto:"));
i.setType("plain/text");
i.putExtra(Intent.EXTRA_EMAIL, new String[] {personEmail});
startActivity(i);
}
});
if(personEmail==null || personEmail.equals("") || personEmail.equals(" ")){
emailPerson.setClickable(false);
emailPerson.setEnabled(false);
emailPerson.setVisibility(View.GONE);
}
else{
emailPerson.setEnabled(true);
emailPerson.setClickable(true);
emailPerson.setVisibility(View.VISIBLE);
}
individualOrganization.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String organizationID = personObject.getString("organizationID");
if(organizationID == null || organizationID.equals("")){
Toast.makeText(SingleIndividual.this, "Sorry No Organization Available!", Toast.LENGTH_SHORT).show();
}else{
Intent i = new Intent(getApplicationContext(), SingleCorporate.class);
i.putExtra("objectId", organizationID);
i.putExtra("image", organizationID);
startActivity(i);
}
}
});
}
});
}
private JSONObject parseObjectToJson(ParseObject parseObject) throws ParseException, JSONException, com.parse.ParseException {
JSONObject jsonObject = new JSONObject();
parseObject.fetchIfNeeded();
Set<String> keys = parseObject.keySet();
for (String key : keys) {
Object objectValue = parseObject.get(key);
if (objectValue instanceof ParseObject) {
jsonObject.put(key, parseObjectToJson(parseObject.getParseObject(key)));
} else if (objectValue instanceof ParseRelation) {
} else {
jsonObject.put(key, objectValue.toString());
}
}
return jsonObject;
}
}
Master Key can only be used from your server code, not client code. Making your users public read is an option, albeit a very poor one. It would be a better idea to have a cloud code function in which you validate a user session, ensure they're able to access this information, and do the query from there, using the master key.

Android in-app billing handling google Server Response Codes

According to google Implementing In-app Billing documentation , that's google will sends the response code synchronously as an integer mapped to the RESPONSE_CODE key in the response Bundle
In-app Billing Reference
now that i have this code in my app
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1001) {
int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
if (resultCode == RESULT_OK) {
try {
JSONObject jo = new JSONObject(purchaseData);
String sku = jo.getString("productId");
alert("You have bought the " + sku + ". Excellent choice,
adventurer!");
}
catch (JSONException e) {
alert("Failed to parse purchase data.");
e.printStackTrace();
}
}
}
}
how i can handling google response codes , for example
if (responsecode == 7) do somthing
i tryed to make this
if(resultCode == RESULT_OK || resposeCode == 7) do somthing
and
if(resultCode == RESULT_OK || resultCode == 7) do somthing
but of course i'm here because nothing works for me
update :
public class Test extends Activity {
IInAppBillingService mService;
ServiceConnection mServiceConn = new ServiceConnection() {
#Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
#Override
public void onServiceConnected(ComponentName name,
IBinder service) {
mService = IInAppBillingService.Stub.asInterface(service);
}
};
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
Intent serviceIntent =
new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");
bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
Typeface font = Typeface.createFromAsset(getAssets(), "fontawesome-webfont.ttf");
b1 = (Button)findViewById(R.id.button1);
b2 = (Button)findViewById(R.id.button3);
b1.setTypeface(font);
b2.setTypeface(font);
b2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
buy(id);
}}
#Override
public void onDestroy() {
super.onDestroy();
if (mService != null) {
unbindService(mServiceConn);
}
}
public void buy(String id) {
try {
Bundle buyIntentBundle = mService.getBuyIntent(3, getPackageName(), selected, "inapp", "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");
PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
this.startIntentSenderForResult(pendingIntent.getIntentSender(), 1001, new Intent(), Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));
} catch (RemoteException e) {
e.printStackTrace();
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1001) {
int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
Toast.makeText(getApplication(), "request true", Toast.LENGTH_LONG).show();
if (resultCode == RESULT_OK) {
Toast.makeText(getApplication(), "result true ", Toast.LENGTH_LONG).show();
if (responseCode == 0){
Toast.makeText(getApplication(), " response = 0", Toast.LENGTH_LONG).show();
}
else if(responseCode == 7){
Toast.makeText(getApplication(), "response = 7 ", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getApplication(), "error", Toast.LENGTH_LONG).show();
}
}
}
}
}
logfile : it's give purchaser successful and downloaded item but next time i try buy same thing before buyintent start , it's crash and give this error
this code what give error next time
this.startIntentSenderForResult(pendingIntent.getIntentSender(), 1001, new Intent(), Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));
java.lang.NullPointerException
at com.app.inapp.bill.Test.buy(Test.java:258)
at com.app.inapp.bill.Test$3.onClick(Test.java:226)
at android.view.View.performClick(View.java:4651)
at android.view.View$PerformClick.run(View.java:19310)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5653)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
at dalvik.system.NativeStart.main(Native Method)
ok thx Sree Reddy Menon i find my solution :
look like google don't allow to start buyintent when you already have item and give nullpointerexption , so i used getPurchases() to find if user have the item or no , and call buy intent only if user don't have the item
example for anyone have same problem ,this my buy method right now
public void donate(String selected) {
try {
Bundle buyIntentBundle = mService.getBuyIntent(3, getPackageName(), selected, "inapp", "bGoa+Vlc/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");
PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
if(pendingIntent != null) {
this.startIntentSenderForResult(pendingIntent.getIntentSender(), 1001, new Intent(), Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));
}else{
try{
Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);
int response = ownedItems.getInt("RESPONSE_CODE");
if (response == 0) {
ArrayList<String> ownedSkus =
ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
ArrayList<String> purchaseDataList =
ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
ArrayList<String> signatureList =
ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
String continuationToken =
ownedItems.getString("INAPP_CONTINUATION_TOKEN");
for (int i = 0; i < purchaseDataList.size(); ++i) {
String purchaseData = purchaseDataList.get(i);
String signature = signatureList.get(i);
String sku = ownedSkus.get(i);
if (sku.equals(selected)){
Toast.makeText(getApplication(), "user have this item", Toast.LENGTH_LONG).show();
break;
}
}
// if continuationToken != null, call getPurchases again
// and pass in the token to retrieve more items
}}catch (RemoteException e)
{
e.printStackTrace();
}
}
} catch (RemoteException e) {
e.printStackTrace();
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
}}
// Billing response codes
public static final int BILLING_RESPONSE_RESULT_OK = 0;
public static final int BILLING_RESPONSE_RESULT_USER_CANCELED = 1;
public static final int BILLING_RESPONSE_RESULT_SERVICE_UNAVAILABLE = 2;
public static final int BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE = 3;
public static final int BILLING_RESPONSE_RESULT_ITEM_UNAVAILABLE = 4;
public static final int BILLING_RESPONSE_RESULT_DEVELOPER_ERROR = 5;
public static final int BILLING_RESPONSE_RESULT_ERROR = 6;
public static final int BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED = 7;
public static final int BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED = 8;
Handling the response
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1001) {
int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
if (responseCode == BILLING_RESPONSE_RESULT_OK) {
try {
JSONObject jo = new JSONObject(purchaseData);
String sku = jo.getString("productId");
alert("You have bought the " + sku + ". Excellent choice,
adventurer!");
}
catch (JSONException e) {
alert("Failed to parse purchase data.");
e.printStackTrace();
}
} else if (responseCode == BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED) {
alert("You have already bought the item");
} else if (resultCode == Activity.RESULT_CANCELED) {
alert("Purchase canceled ");
}
else{
alert("Unknown error");
}
}
}
add as your response codes on if else.

Printing multiple times via Bluetooth Printer in Android

I am trying to print multiple times base on inputted integer. I can print now once at a time but after trying to print multiple times the result is always printing only 1 times, and sometimes it is not printing.
MainActivity.java
//This is my global variable for printing
BluetoothAdapter mBTAdapter;
BluetoothSocket mBTSocket = null;
Dialog dialogProgress;
String BILL, TRANS_ID;
String PRINTER_MAC_ID;
final String ERROR_MESSAGE = "There has been an error in printing the bill.";
//The copyPrint is a String Var which will contain the inputted integer and it will convert into Int so it will become copyPrintIs.
int copyPrintIs = Integer.parseInt(copyPrint);
for(int x = 1; x <= copyPrintIs; x++){
printNow(thePrinted);
//Call the printNow and repeat calling on it base on inputted integer
//The thePrinted will contain String Text which will become the result of printing
}
and here is my code when the printNow function is called
public void printNow(String thePrintedvalue) {
try {
PRINTER_MAC_ID = "00:12:F3:19:4D:D8";
BILL = thePrintedvalue; //thePrintedvalue will be pass on BILL Var
mBTAdapter = BluetoothAdapter.getDefaultAdapter();
dialogProgress = new Dialog(Ticketing.this);
try {
if (mBTAdapter.isDiscovering())
mBTAdapter.cancelDiscovery();
else
mBTAdapter.startDiscovery();
} catch (Exception e) {
Toast.makeText(this, "A: " + e, Toast.LENGTH_LONG).show();
}
System.out.println("BT Searching status :"
+ mBTAdapter.isDiscovering());
if (mBTAdapter == null) {
Toast.makeText(this, "Device has no bluetooth capability",
Toast.LENGTH_LONG).show();
} else {
if (!mBTAdapter.isEnabled()) {
Intent i = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(i, 0);
}
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(
BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
}
} catch (Exception e) {
Toast.makeText(this, "B: " + e, Toast.LENGTH_LONG).show();
}
}
/********/
public void printBillToDevice(final String address) {
mBTAdapter.cancelDiscovery();
try { BluetoothDevice mdevice = mBTAdapter.getRemoteDevice(address);
Method m = mdevice.getClass().getMethod("createRfcommSocket",
new Class[] { int.class });
mBTSocket = (BluetoothSocket) m.invoke(mdevice, 1);
mBTSocket.connect();
OutputStream os = mBTSocket.getOutputStream();
os.flush();
os.write(BILL.getBytes());
System.out.println(BILL);
if (mBTAdapter != null)
mBTAdapter.cancelDiscovery();
mBTSocket.close();
setResult(RESULT_OK);
} catch (Exception e) {
Log.e("Class ", "My Exe ", e);
// Toast.makeText(BluetoothPrint.this, ERROR_MESSAGE,
// Toast.LENGTH_SHORT).show();
e.printStackTrace();
setResult(RESULT_CANCELED);
}
}
/********/
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
try {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
System.out.println("***" + device.getName() + " : "
+ device.getAddress());
if (device.getAddress().equalsIgnoreCase(PRINTER_MAC_ID)) {
mBTAdapter.cancelDiscovery();
dialogProgress.dismiss();
Toast.makeText(Ticketing.this,device.getName() + " Printing data", Toast.LENGTH_LONG).show();
printBillToDevice(PRINTER_MAC_ID);
}
}
} catch (Exception e) {
Log.e("Class ", "My Exe ", e);
}
}
};
All of the code above is inside on MainActivity.java.
I cant figure out where I need to put the loop so it will continue printing copies of paper.
Please help!
try this:
Remove the loop here.
for(int x = 1; x <= copyPrintIs; x++){
printNow(thePrinted);
//Call the printNow and repeat calling on it base on inputted integer
//The thePrinted will contain String Text which will become the result of printing
}
and then change this code
public void printBillToDevice(final String address) {
mBTAdapter.cancelDiscovery();
try { BluetoothDevice mdevice = mBTAdapter.getRemoteDevice(address);
Method m = mdevice.getClass().getMethod("createRfcommSocket",
new Class[] { int.class });
mBTSocket = (BluetoothSocket) m.invoke(mdevice, 1);
mBTSocket.connect();
OutputStream os = mBTSocket.getOutputStream();
os.flush();
os.write(BILL.getBytes());
System.out.println(BILL);
if (mBTAdapter != null)
mBTAdapter.cancelDiscovery();
mBTSocket.close();
setResult(RESULT_OK);
} catch (Exception e) {
Log.e("Class ", "My Exe ", e);
// Toast.makeText(BluetoothPrint.this, ERROR_MESSAGE,
// Toast.LENGTH_SHORT).show();
e.printStackTrace();
setResult(RESULT_CANCELED);
}
}
to this code
public void printBillToDevice(final String address) {
mBTAdapter.cancelDiscovery();
try { BluetoothDevice mdevice = mBTAdapter.getRemoteDevice(address);
Method m = mdevice.getClass().getMethod("createRfcommSocket",
new Class[] { int.class });
mBTSocket = (BluetoothSocket) m.invoke(mdevice, 1);
mBTSocket.connect();
//this will do the code
int copyPrintIs = Integer.parseInt(copyPrint);
for (int x = 1; x <= copyPrintIs; x++) {
OutputStream os = mBTSocket.getOutputStream();
os.flush();
os.write(BILL.getBytes());
System.out.println(BILL);
SystemClock.sleep(4000);//This will pause every 4 seconds after printing once and the continue and pause again
}
copyPrint = "1";//This will change the copyPrint back to 1 value
if (mBTAdapter != null)
mBTAdapter.cancelDiscovery();
mBTSocket.close();
setResult(RESULT_OK);
} catch (Exception e) {
Log.e("Class ", "My Exe ", e);
// Toast.makeText(BluetoothPrint.this, ERROR_MESSAGE,
// Toast.LENGTH_SHORT).show();
e.printStackTrace();
setResult(RESULT_CANCELED);
}
}

Android Java programming: need help creating an object variable

I'm trying to make an Android application that access RottenTomatoes.com and loads the API data of upcoming movies.
I can successfully obtain the API data, but when I try to parse the data I run into trouble.
Here's the block of code that isn't working:
public class MovieJSONParser {
static public class MovieParser{
static ArrayList<Movie> parseMovie(String jsonString) throws JSONException {
ArrayList<Movie> movies = new ArrayList<Movie>();
JSONObject moviesJSON = new JSONObject(jsonString);
JSONArray moviesArray = moviesJSON.getJSONArray("movies");
Log.d("app", "in MovieJSONParser");
for (int i = 0; i < moviesArray.length(); i++) {
JSONObject o = moviesArray.getJSONObject(i);
Log.d("app", o.toString());
Log.d("app", "Created a JSON object to put in Movies");
// THIS LINE ISN'T WORKING
Movie movie = new Movie(o);
Log.d("app", "after Movie declaration");
movies.add(movie);
}
Log.d("app", "end of MovieJSONParser");
return movies;
}
}
}
I know the line of code that I labeled as not working isn't working because the log comments are all appearing correctly up until the statement:
Movie movie = new Movie(o);
This line of code is trivial... a simple class object declaration... I have no idea why it's making the program crash... There is no actual error. The program runs.
Here is my Movie.class:
public class Movie extends Activity {
String url_posterThumbnail, title, year, mpaa_rating;
int critics_score;
public Movie(JSONObject o) throws JSONException {
Log.d("app", "in Movie");
this.title = o.getString("title");
this.year = o.getString("year");
this.mpaa_rating = o.getString("mpaa_rating");
this.critics_score = o.getInt("critics_score");
this.url_posterThumbnail = o.getString("thumbnail");
}
public String returnUrl_posterThumbnail() {
return url_posterThumbnail;
}
public void setUrl_posterThumbnail(String url_posterThumbnail) {
this.url_posterThumbnail = url_posterThumbnail;
}
public String returnTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String returnYear() {
return year;
}
public void setYear(String year) {
this.year = year;
}
public String returnMpaa_rating() {
return mpaa_rating;
}
public void setMpaa_rating(String mpaa_rating) {
this.mpaa_rating = mpaa_rating;
}
public int returnCritics_score() {
return critics_score;
}
public void setCritics_score(int critics_score) {
this.critics_score = critics_score;
}
#Override
public String toString() {
return "Movie [url_posterThumbnail=" + url_posterThumbnail + ", title="
+ title + ", year=" + year + ", mpaa_rating=" + mpaa_rating
+ ", critics_score=" + critics_score + "]";
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_movies);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.movies, menu);
return true;
}
}
Here's my MainActivity.class in case you need it:
public class MainActivity extends Activity {
String APIKEY = "vs6hcrs57h4wy74u3zgxhmrm";
String url_MY_FAVORITE_MOVIES = "";
String url_BOX_OFFICE_MOVIES = "http://api.rottentomatoes.com/api/public/v1.0/lists/movies/box_office.json?limit=3&country=us&apikey=p53b5bybwxpg7nfykwzezkzr";
String url_IN_THEATRES_MOVIES = "http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json?page_limit=3&page=1&country=us&apikey=p53b5bybwxpg7nfykwzezkzr";
String url_OPENING_MOVIES = "http://api.rottentomatoes.com/api/public/v1.0/lists/movies/opening.json?limit=3&country=us&apikey=p53b5bybwxpg7nfykwzezkzr";
String url_UPCOMING_MOVIES = "http://api.rottentomatoes.com/api/public/v1.0/lists/movies/upcoming.json?page_limit=3&page=1&country=us&apikey=p53b5bybwxpg7nfykwzezkzr";
ListView listview;
ArrayList<Movie> movies = new ArrayList<Movie>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("app", "Hi! In onCreate");
listview = (ListView) findViewById(R.id.listView1);
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_list_item_1);
listview.setAdapter(arrayAdapter);
arrayAdapter.add("My Favorite Movies");
arrayAdapter.add("Box Office Movies");
arrayAdapter.add("In Theatres Movies");
arrayAdapter.add("Opening Movies");
arrayAdapter.add("Upcoming Movies");
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int listViewPosition,
long arg3) {
Intent i = new Intent(getBaseContext(), MoviesDetails.class);
switch (listViewPosition) {
case 0:
try {
movies = new GetMoviesASYNCTASK(MainActivity.this).execute(url_MY_FAVORITE_MOVIES).get();
} catch (InterruptedException e1) {
e1.printStackTrace();
} catch (ExecutionException e1) {
e1.printStackTrace();
}
Log.d("app", "right before starting MoviesDetails activity");
i.putExtra("movies", movies);
startActivity(i);
break;
case 1:
try {
movies = new GetMoviesASYNCTASK(MainActivity.this).execute(url_BOX_OFFICE_MOVIES).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
Log.d("app", "right before starting MoviesDetails activity");
i.putExtra("movies", movies);
startActivity(i);
break;
case 2:
try {
movies = new GetMoviesASYNCTASK(MainActivity.this).execute(url_IN_THEATRES_MOVIES).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
Log.d("app", "right before starting MoviesDetails activity");
i.putExtra("movies", movies);
startActivity(i);
break;
case 3:
try {
movies = new GetMoviesASYNCTASK(MainActivity.this).execute(url_OPENING_MOVIES).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
Log.d("app", "right before starting MoviesDetails activity");
i.putExtra("movies", movies);
startActivity(i);
break;
case 4:
try {
movies = new GetMoviesASYNCTASK(MainActivity.this).execute(url_UPCOMING_MOVIES).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
Log.d("app", "right before starting MoviesDetails activity");
i.putExtra("movies", movies);
startActivity(i);
break;
default:
break;
}
Log.d("app", "end of file?");
}
});
}
#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;
}
}
Lastly, here's my GetMoviesASYNCTASK.class if you need it:
public class GetMoviesASYNCTASK extends AsyncTask<String, Void, ArrayList<Movie>> {
String url_string;
ProgressDialog pd;
MainActivity main;
public GetMoviesASYNCTASK(MainActivity main){
this.main = main;
}
#Override
protected ArrayList<Movie> doInBackground(String... params) {
url_string = params[0];
// pd = new ProgressDialog(main);
// pd.setCancelable(false);
// pd.setMessage("Loading Movies...!");
// pd.show();
Log.d("app", "begin asynctask");
try {
URL url = new URL(url_string);//Parse the string as an url
HttpURLConnection con = (HttpURLConnection) url.openConnection();
//create a http connection using that url
con.setRequestMethod("GET");//Use the get method
con.connect(); //Connect to http
int statusCode = con.getResponseCode();//Get the server's response
if (statusCode == HttpURLConnection.HTTP_OK) { //If server returns 200
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = reader.readLine();
while (line != null) {
sb.append(line);
line = reader.readLine();
}
Log.d("app", "String value of API stored");
ArrayList<Movie> movies = MovieJSONParser.MovieParser.parseMovie(sb.toString());
Log.d("app", "movies in ASYNCTASK initialized :)");
return movies;
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d("app", "asynctask didn't work");
return null;
}
// Override
protected void onPostExecute(ArrayList<Movie> result) {
//ArrayList<String> movieTitles = new ArrayList<String>();
super.onPostExecute(result);
Log.d("app", "exiting asynctask");
//pd.dismiss();
}
}
Am I missing something obvious?
Any help will be greatly appreciated!
critics_score is in ratings object but here you are trying to access that key directly. so it is throwing exception.
Better use optString() with some default value instead of getString(), as even if the key doesn't exist, will not end with exceptions..
Here is the working code :
JSONObject object = new JSONObject(result);
JSONArray records = object.getJSONArray("movies");
Log.d(LOG_TAG, "records" + records);
int len = records.length();
String albumart[] = new String[len];
for (int i = 0; i < len; i++) {
JSONObject record = (JSONObject) records.getJSONObject(i);
String extid = record.getString("id");
String accountName = record.optString("title", "No title");
JSONObject posters = record.getJSONObject("posters");
String albuart = posters.optString("detailed", null);
String critics = record.optString("critics_consensus", "No Critics");
String year = record.getString("year");
String rating = record.optString("mpaa_rating", "No rating");
JSONObject ratings = record.getJSONObject("ratings");
String rating = ratings.optString("critics_score", "");
if(rating.length() <= 0 ) {
rating = "0";
}
String audience_rating = ratings.optString("audience_rating", "");
if(audience_rating.length() <= 0 ) {
audience_rating = "0";
}
String duration = record.optString("runtime", "");
if(duration.length() <= 0 ) {
duration = "0"
}
}

Categories