I am trying to set up iAP for a Premium membership.
I've added my app and my signed apk to the developer console and then I started following this example: Implementing In-app Billing
I've noticed a tricky part that says:
Warning: Do not call the getSkuDetails method on the main thread. Calling this method triggers a network request which could block your main thread. Instead, create a separate thread and call the getSkuDetails method from inside that thread.
so this is the code I wrote:
public class class...
Bundle querySkus = new Bundle();
/** gestisce gli acquisti in app */
IInAppBillingService mService;
ServiceConnection mServiceConn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IInAppBillingService.Stub.asInterface(service);
}
#Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
};
and in my onCreate() method:
Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");
bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
ArrayList<String> skuList = new ArrayList<String>();
skuList.add("premiumUpgrade");
querySkus.putStringArrayList("chords_premium", skuList);
AsyncTask.execute(new Runnable() {
#Override
public void run() {
Bundle skuDetails = mService.getSkuDetails(3, getPackageName(), "inapp", querySkus);
}
});
now on Bundle skuDetails = mService.getSkuDetails(3, getPackageName(), "inapp", querySkus); I'm getting:
Unhandled Exception: android.os.RemoteException
First of all, how do I fix it?
I'm implementing this code in my main activity even though the button the should redirect to the buying dialog is in another activity. Am I doing it right? Do I need to pass it to the other Activity? if so, how? Is it better that I put the whole code that handles iAP inside the specific activity?
**EDIT: **
I've tried to catch the exception like this:
AsyncTask.execute(new Runnable() {
#Override
public void run() {
try {Bundle skuDetails = mService.getSkuDetails(3, getPackageName(), "inapp", querySkus); }
catch (RemoteException e) {e.printStackTrace();};
}
});
It won't work becuase I cannot set int response = skuDetails... (in the doc linked above)
Haven't tested your code.. but I think you can try this:
AsyncTask.execute(new Runnable() {
#Override
public void run() {
Bundle skuDetails = null;
try {
skuDetails = mService.getSkuDetails(3,
getPackageName(), "inapp", querySkus);
} catch (RemoteException e) {
e.printStackTrace();
}
int response = skuDetails.whateverYouWantToDoWithThis();
}
});
OR
AsyncTask.execute(new Runnable() {
#Override
public void run() throws RemoteException {
Bundle skuDetails = mService.getSkuDetails(3,
getPackageName(), "inapp", querySkus);
int response = skuDetails.whateverYouWantToDoWithThis();
}
});
Read more about throws vs try-catch here: try/catch versus throws Exception
Related
I am new to android studio and just want an app to do one thing: check if the bytewerk is open (domain is stats.bytewerk.org/status.txt just one word either open or closed) and display it on a widget. But I tried all kind of httpconections like volley or okhttp, but never got a result. I already added the uses permission in the manifest.
1:
public class StatusWidget<appWidgetId> extends AppWidgetProvider {
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) throws IOException {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.status_widget);
new GetNotePadFileFromServer().execute();
//views.setViewVisibility(R.id.bytewerk_online, 0);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
for (int appWidgetId : appWidgetIds) {
try {
updateAppWidget(context, appWidgetManager, appWidgetId);
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onEnabled(Context context) {
// Enter relevant functionality for when the first widget is created
}
#Override
public void onDisabled(Context context) {
// Enter relevant functionality for when the last widget is disabled
}
}public class GetNotePadFileFromServer extends AsyncTask<Void, Void, Void> {
String TextHolder;
protected Void doInBackground(Void... params) {
try {
URL url = new URL("http://stats.bytewerk.org/status.txt");
BufferedReader bufferReader = new BufferedReader(new InputStreamReader(url.openStream()));
TextHolder = "";
String TextHolder2 = "";
while ((TextHolder2 = bufferReader.readLine()) != null) {
TextHolder += TextHolder2;
}
bufferReader.close();
} catch (MalformedURLException malformedURLException) {
// TODO Auto-generated catch block
malformedURLException.printStackTrace();
TextHolder = malformedURLException.toString();
} catch (IOException iOException) {
// TODO Auto-generated catch block
iOException.printStackTrace();
TextHolder = iOException.toString();
}
return null;
}
#Override
protected void onPostExecute(Void finalTextHolder) {
textView.setText(TextHolder);
super.onPostExecute(finalTextHolder);
}
2:
final TextView textView = (TextView) findViewById(R.id.text);
// ...
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(this);
String url ="http://www.google.com";
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// Display the first 500 characters of the response string.
textView.setText("Response is: "+ response.substring(0,500));
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
textView.setText("That didn't work!");
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
And the other examples on the offical website
of course i already implemented
dependencies {
...
implementation 'com.android.volley:volley:1.1.1'
}
Add internet permission to your Manifest.xml and volley works, This line:
<uses-permission android:name="android.permission.INTERNET" />
before application tag.
Hope this helps.
this was my solution:
static void updateAppWidget(Context context, final AppWidgetManager appWidgetManager,
final int appWidgetId) {
final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.status_widget);
// ...
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(context);
String url ="http://stats.bytewerk.org/status.txt";
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
public void onResponse(String response) {
// Display the first 500 characters of the response string.
if (response.equals("open")) {
views.setViewVisibility(R.id.status_online, 1);
} else {
views.setViewVisibility(R.id.status_offline, 1);
}
//views.setTextViewText(R.id.text, "Yeah!" + response);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
views.setViewVisibility(R.id.status_nointernet, 1);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
});
queue.add(stringRequest);
I've implemented an action button in my android PhoneGap app Push Notification window that performs HTTP request to my server to handle server actions.
Probably we have an exception when we perform the HTTP request because it doesn't seem to work. (currently, we can't view the exception itself for reason I won't get into here)
We implemented by calling the HTTP request in a different thread because we saw answers here in Stackoverflow that you can't implement calling the HTTP request on the main thread.
Any help will be appreciated.
This is my BroadcastReceiver class:
public class ExpressPayRequest extends BroadcastReceiver{
#Override
public void onReceive(Context Context, Intent arg1) {
Context.startService(new Intent(Context, PostRequestService.class));
}
}
And the service looks like this:
public class PostRequestService extends Service{
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try{
URL url = new URL("http://someGETRequest");
HttpURLConnection client = (HttpURLConnection)url.openConnection();
int responseCode = client.getResponseCode();
}
catch(IOException e){
Log.e("LOGEntry", "error log: " + e.getMessage(),e);
}
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}
I have figured it out myself
if anyone interested the solution was creating a new thread instead of starting a new service
this is the code I used:
Thread thread = new Thread(){
public void run(){
try{
URL url = new URL("http://test");
HttpURLConnection client = (HttpURLConnection)url.openConnection();
client.connect();
int responseCode = client.getResponseCode();
} catch (IOException e) {
e.printStackTrace();
}
}
};
thread.start();
I'm retrieving some information from the server using REST. I make a Get call using AsyncTask. But I need to wait for the results... Is there any way to do it synchronously? So I can get the result.
Code:
private void sendStuff(Context context, String[] params) {
RESTGet restGet = new RESTGet(context);
restGet.setMessageLoading("Loading...");
try {
restGet.execute(params);
} catch (Exception e) {
e.printStackTrace();
}
restGet.stopMessageLoading();
Intent intent = new Intent(context, ShowPictures.class);
((Activity)context).startActivity(intent);
}
Thanks...
You can use get() to wait for the task to end and even get its result. But I would not recommend this, because it will freeze your app.
Example assuming that RESTGet extends AsyncTask:
private void sendStuff(Context context, String[] params) {
final int TIMEOUT = 2000;
RESTGet restGet = new RESTGet(context);
restGet.setMessageLoading("Loading...");
try {
restGet.execute(params).get(TIMEOUT, TimeUnit.MILLISECONDS);
} catch (Exception e) {
e.printStackTrace();
}
restGet.stopMessageLoading();
Intent intent = new Intent(context, ShowPictures.class);
((Activity)context).startActivity(intent);
}
Instead of using get, put your code in onPostExecute method, so it will be called after the task execution.
Ex:
private void sendStuff(Context context, String[] params) {
RESTGet restGet = new RESTGet(context) {
#Override
protected void onPostExecute(String feed) {
super.onPostExecute(feed);
this.stopMessageLoading();
Intent intent = new Intent(context, ShowPictures.class);
((Activity)context).startActivity(intent);
}
}.execute(params);
}
Hope it helps...
I want to receive a String from the Bluetooth server which is pc I have a java code for it but when ever I run my Android client Activity it shows me this exception
Activity com.waseem.mobileclient.bluetoot_app.MainActivity has leaked IntentReceiver com.waseem.mobileclient.bluetoot_app.MainActivity$1#410480f0 that was originally registered here. Are you missing a call to unregisterReceiver()?
android.app.IntentReceiverLeaked: Activity com.waseem.mobileclient.bluetoot_app.MainActivity has leaked IntentReceiver com.waseem.mobileclient.bluetoot_app.MainActivity$1#410480f0 that was originally registered here. Are you missing a call to unregisterReceiver()?
at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:792)
at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:593)
at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1111)
at android.app.ContextImpl.registerReceiver(ContextImpl.java:1098)
at android.app.ContextImpl.registerReceiver(ContextImpl.java:1092)
at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:365)
at com.waseem.mobileclient.bluetoot_app.MainActivity.onCreate(MainActivity.java:68)
at android.app.Activity.performCreate(Activity.java:5008)
I am unregistering in onPause() why I am getting this exception please help me out It has stuck me for a long time.
here is the client code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (myBluetoothAdapter == null) {
Log.e(TAG, "No Bluetooth Adapter available. Exiting...");
this.finish();
}
IntentFilter intent_filter=new IntentFilter(MESSAGE_RECEIVED_INTENT);
broad_receiver=new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(MESSAGE_RECEIVED_INTENT)) {
showInformation(intent.getExtras().getString("Message"), 5000);
getVibrator().vibrate(500);
}
else {
showInformation("Message unable to receive", 5000);
getVibrator().vibrate(500);
}
}
};
this.registerReceiver(broad_receiver,intent_filter);
Button start_server = (Button)findViewById(R.id.button_start);
start_server.setOnClickListener(this);
Button stop_server = (Button)findViewById(R.id.button_stop);
stop_server.setOnClickListener(this);
}
#Override
protected void onPause() {
this.unregisterReceiver(this.broad_receiver);
super.onPause();
server.cancel();
restoreBTDeviceName();
}
#Override
public void onClick(View v) {
Button btn = (Button) v;
if (btn.getId() == R.id.button_start) {
if (!myBluetoothAdapter.getName().startsWith(PREFIX))
myBluetoothAdapter.setName(PREFIX );
if (myBluetoothAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
requestBTDiscoverable();
server = new AcceptThread();
server.start();
btn.setEnabled(false);
((Button) this.findViewById(R.id.button_stop)).setEnabled(true);
}
} else if (btn.getId() == R.id.button_stop) {
server.cancel();
btn.setEnabled(false);
((Button) this.findViewById(R.id.button_start)).setEnabled(true);
restoreBTDeviceName();
}
}
/**
* Launches Discoverable Bluetooth Intent.
*/
public void requestBTDiscoverable() {
Intent i = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
i.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivityForResult(i, REQUEST);
int result = 0;
this.onActivityResult(REQUEST, result, i);
Log.i(TAG, "Bluetooth discoverability enabled");
}
/**
* Obtains the Vibrator service.
*
* #return Vibrator Object.
*/
private Vibrator getVibrator() {
return (Vibrator) getSystemService(VIBRATOR_SERVICE);
}
/**
* Removes the prefix from the device name if the prefix is present.
*/
private void restoreBTDeviceName() {
if (myBluetoothAdapter.getName().startsWith(PREFIX))
myBluetoothAdapter.setName(myBluetoothAdapter.getName().substring(PREFIX.length()));
}
/**
* Shows a information dialog.
*
* #param message String resource used to define the message.
* #param duration Dialog's TTL.
*/
private void showInformation(String message, long duration) {
final Dialog mDialog = new Dialog(this);
TextView txt = new TextView(this);
txt.setText(message);
mDialog.setContentView(txt);
mDialog.setTitle("Information");
mDialog.show();
(new Handler()).postDelayed(new Runnable() {
public void run() {
mDialog.dismiss();
}
},duration); // Close dialog after delay
}
/**
* ************************************* AcceptThread *************************************
*/
class AcceptThread extends Thread {
/**
* Tag that will appear in the log.
*/
private final String ACCEPT_TAG = AcceptThread.class.getName();
/**
* The bluetooth server socket.
*/
private final BluetoothServerSocket mServerSocket;
public AcceptThread() {
BluetoothServerSocket tmp = null;
try {
tmp = myBluetoothAdapter.listenUsingRfcommWithServiceRecord(ACCEPT_TAG, UUID.fromString(defaultUUID));
} catch (IOException e) {
e.printStackTrace();
}
mServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
while (true) {
try {
Log.i(ACCEPT_TAG, "Listening for a connection...");
socket = mServerSocket.accept();
Log.i(ACCEPT_TAG, "Connected to " + socket.getRemoteDevice().getName());
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
// Do work to manage the connection (in a separate thread)
try {
// Read the incoming string.
String buffer;
DataInputStream in = new DataInputStream(socket.getInputStream());
buffer = in.readUTF();
Intent i = new Intent(MESSAGE_RECEIVED_INTENT);
i.putExtra("Message", String.format("%sn From: %s", buffer, socket.getRemoteDevice().getName()));
getBaseContext().sendBroadcast(i);
} catch (IOException e) {
Log.e(ACCEPT_TAG, "Error obtaining InputStream from socket");
e.printStackTrace();
}
try {
mServerSocket.close();
} catch (IOException e) {
}
break;
}
}
}
/**
* Will cancel the listening socket, and cause the thread to finish
*/
public void cancel() {
try {
mServerSocket.close();
} catch (IOException e) {
}
}
}
The first line of LogCat says:
Are you missing a call to unregisterReceiver()?
It simply means that you need to check the API documentation of BroadcastReceiver for help, which says:
Note: If registering a receiver in your Activity.onResume() implementation, you should unregister it in Activity.onPause(). (You won't receive intents when paused, and this will cut down on unnecessary system overhead). Do not unregister in Activity.onSaveInstanceState(), because this won't be called if the user moves back in the history stack.
Been trying to use twitter4j to post a tweet for couple days now without luck, what i want to do is for a person to post their new top score on their timeline from the app at the end of a round. Here is my code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tweetr);
Button tweetr = (Button)findViewById(R.id.tweetr);
//create a new twitter configuration using user details
tweetTwitter = new TwitterFactory().getInstance();
tweetTwitter.setOAuthConsumer(TWIT_KEY, TWIT_SECRET);
//create a twitter instance
// tweetTwitter = new TwitterFactory(twitConf).getInstance();
tweetr.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dt.execute();
}
});
}
public class TweetTask extends AsyncTask<Object, Void, String> {
#Override
protected String doInBackground(Object... values) {
/* try {
//requestToken = tweetTwitter.getOAuthRequestToken(TWITTER_CALLBACK_URL);
} catch (TwitterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(requestToken.getAuthenticationURL())));
*/
try {
requestToken = tweetTwitter.getOAuthRequestToken(TWITTER_CALLBACK_URL);
String authUrl = requestToken.getAuthenticationURL();
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(authUrl)));
} catch (TwitterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
Log.d("URI", "DONE");
super.onPostExecute(result);
}
}
#Override
protected void onResume() {
super.onResume();
final Uri uri = getIntent().getData();
if(uri != null ){
Log.d("URI", uri.toString());
Thread th = new Thread(){
public void run(){
try {
String verifier = uri.getQueryParameter("oauth_verifier");
String oauthToken = uri.getQueryParameter("oauth_token");
RequestToken reqToken = tweetTwitter.getOAuthRequestToken(oauthToken,verifier);
AccessToken accessToken = tweetTwitter.getOAuthAccessToken(reqToken);
String token = accessToken.getToken(), secret = accessToken.getTokenSecret();
} catch (TwitterException ex) {
Log.e("Main.onNewIntent", "" + ex.getMessage());
}
}};
th.start();
}else
Log.d("URI", "FAILED");
}
}
This is my error print out
10-23 15:35:18.661: D/TWIT ER(2392): No authentication challenges foundRelevant discussions can be found on the Internet at:
refer to the javadoc of Twitter4J
In order to get access acquire AccessToken using xAuth, you must apply by sending an email to api#twitter.com — all other applications will receive an HTTP 401 error.