Iam using easebuzz payment gateway and it was working fine two days ago, but now
I got stuck in payments and im getting an error but easebuzz is not showing any error its in the screen of Transaction is Processing...
after selecting payment option(ex: Bank) it will process the payment and next it is redirecting to Transaction processing page and it got stuck in there after waiting for long time still its not showing any response but only a error log in the terminal. it was working fine few days before i didnt changed any payment code.ihave Updated the flutter version but i dont thing flutter version cant do anything because My previous projects that built few months before also not working due to this issue in the easebuzz ,
error log
W/System.err(30454): org.json.JSONException: No value for error_status W/System.err(30454): at org.json.JSONObject.get(JSONObject.java:399) W/System.err(30454): at org.json.JSONObject.getString(JSONObject.java:560) W/System.err(30454): at com.easebuzz.payment.kit.PWEBankPageActivity$PWEPaymentStatus$1.run(PWEBankPageActivity.java:1016) W/System.err(30454): at android.os.Handler.handleCallback(Handler.java:883) W/System.err(30454): at android.os.Handler.dispatchMessage(Handler.java:100) W/System.err(30454): at android.os.Looper.loop(Looper.java:224) W/System.err(30454): at android.app.ActivityThread.main(ActivityThread.java:7590) W/System.err(30454): at java.lang.reflect.Method.invoke(Native Method) W/System.err(30454): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539) W/System.err(30454): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
This is the Javacode that is given by easebuzz
MainActivity.java
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "easebuzz";
MethodChannel.Result channel_result;
boolean start_payment = true;
#Override
public void configureFlutterEngine(#NonNull FlutterEngine flutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
start_payment = true;
new MethodChannel(getFlutterEngine().getDartExecutor().getBinaryMessenger(), CHANNEL).setMethodCallHandler(
new MethodChannel.MethodCallHandler() {
#Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
channel_result = result;
if (call.method.equals("payWithEasebuzz")) {
if (start_payment) {
start_payment = false;
startPayment(call.arguments);
}
}
}
});
}
private void startPayment(Object arguments) {
try {
System.out.print(":::::::::::::Payment started 0::::::::::::::");
Gson gson = new Gson();
System.out.print(":::::::::::::Payment started 1::::::::::::::");
JSONObject parameters = new JSONObject(gson.toJson(arguments));
System.out.print(":::::::::::::Payment started ::::::::::::::");
Intent intentProceed = new Intent(getBaseContext(), PWECouponsActivity.class);
intentProceed.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
intentProceed.putExtra("access_key", parameters.getString("access_key"));
intentProceed.putExtra("pay_mode", parameters.getString("pay_mode"));
startActivityForResult(intentProceed, PWEStaticDataModel.PWE_REQUEST_CODE);
} catch (Exception e) {
start_payment = true;
Map error_map = new HashMap<>();
Map error_desc_map = new HashMap<>();
String error_desc = "exception occured:" + e.getMessage();
error_desc_map.put("error", "Exception");
error_desc_map.put("error_msg", error_desc);
error_map.put("result", PWEStaticDataModel.TXN_FAILED_CODE);
error_map.put("payment_response", error_desc_map);
channel_result.success(error_map);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (data != null) {
if (requestCode == PWEStaticDataModel.PWE_REQUEST_CODE) {
start_payment = true;
JSONObject response = new JSONObject();
Map error_map = new HashMap<>();
if (data != null) {
String result = data.getStringExtra("result");
String payment_response = data.getStringExtra("payment_response");
System.out.print(":::::::::::::Payment response ::::::::::::::");
System.out.print(payment_response);
try {
JSONObject obj = new JSONObject(payment_response);
response.put("result", result);
response.put("payment_response", obj);
channel_result.success(JsonConverter.convertToMap(response));
} catch (Exception e) {
Map error_desc_map = new HashMap<>();
error_desc_map.put("error", result);
error_desc_map.put("error_msg", payment_response);
error_map.put("result", result);
error_map.put("payment_response", error_desc_map);
channel_result.success(error_map);
}
} else {
Map error_desc_map = new HashMap<>();
String error_desc = "Empty payment response";
error_desc_map.put("error", "Empty error");
error_desc_map.put("error_msg", error_desc);
error_map.put("result", "payment_failed");
error_map.put("payment_response", error_desc_map);
channel_result.success(error_map);
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
}
}
Related
I've been implementing for the first time in-app billing in my app and even if all the code is correct, it is not working!
I have a BillingManager.java
public class BillingManager implements PurchasesUpdatedListener {
private static final String TAG = "BillingManager";
private final BillingClient mBillingClient;
private final Activity mActivity;
String base64Key = "mykey";
private static Context myCxt;
private String mAdRemovalPrice;
private static final String ITEM_SKU_ADREMOVAL = "myskuid";
public int billingResult;
public BillingManager(Activity activity) {
mActivity = activity;
mBillingClient = BillingClient.newBuilder(mActivity).setListener(this).build();
mBillingClient.startConnection(new BillingClientStateListener() {
#Override
public void onBillingSetupFinished(#BillingClient.BillingResponse int billingResponse) {
if (billingResponse == BillingClient.BillingResponse.OK) {
Log.i(TAG, "onBillingSetupFinished() good response: " + billingResponse);
List skuList = new ArrayList<>();
skuList.add(ITEM_SKU_ADREMOVAL);
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
mBillingClient.querySkuDetailsAsync(params.build(),
new SkuDetailsResponseListener() {
#Override
public void onSkuDetailsResponse(int responseCode, List skuDetailsList) {
// Process the result.
if (responseCode == BillingClient.BillingResponse.OK
&& skuDetailsList != null) {
for (Object skuDetailsObject : skuDetailsList) {
SkuDetails skuDetails = (SkuDetails) skuDetailsObject;
String sku = skuDetails.getSku();
String price = skuDetails.getPrice();
if (ITEM_SKU_ADREMOVAL.equals(sku)) {
mAdRemovalPrice = price;
}
}
}
}
});
} else {
Log.w(TAG, "onBillingSetupFinished() error code: " + billingResponse);
}
}
#Override
public void onBillingServiceDisconnected() {
Log.w(TAG, "onBillingServiceDisconnected()");
}
});
}
#Override
public void onPurchasesUpdated(int responseCode, List<Purchase> purchases) {
if (responseCode == BillingClient.BillingResponse.OK
&& purchases != null) {
for(Purchase purchase: purchases) {
// When every a new purchase is made
// Here we verify our purchase
Log.i(TAG, "onPurchasesUpdated() ourchase ok response: " + responseCode);
if (!verifyValidSignature(purchase.getOriginalJson(), purchase.getSignature())) {
// Invalid purchase
// show error to user
myCxt = MainActivity.proContext;
Toast.makeText(myCxt, myCxt.getString(R.string.purchase_err), Toast.LENGTH_LONG).show();
Log.i(TAG, "Got a purchase: " + purchase + "; but signature is bad. Skipping...");
return;
} else {
// purchase is valid
// Perform actions
myCxt = MainActivity.proContext;
Toast.makeText(myCxt, myCxt.getString(R.string.purchase_done), Toast.LENGTH_LONG).show();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(myCxt);
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("isPro", true);
editor.apply();
}
}
} else if (responseCode == BillingClient.BillingResponse.USER_CANCELED) {
// Handle an error caused by a user cancelling the purchase flow.
Log.i(TAG, "onPurchasesUpdated() user canceled response: " + responseCode);
} else {
// Handle any other error codes.
Log.i(TAG, "onPurchasesUpdated() error response: " + responseCode);
}
}
public void startPurchaseFlow() {
BillingFlowParams flowParams = BillingFlowParams.newBuilder()
.setSku(ITEM_SKU_ADREMOVAL)
.setType(BillingClient.SkuType.INAPP)
.build();
mBillingClient.launchBillingFlow(mActivity, flowParams);
Log.i(TAG, "StartPurchaseFlow called");
}
private boolean verifyValidSignature(String signedData, String signature) {
try {
return Security.verifyPurchase(base64Key, signedData, signature);
} catch (IOException e) {
Log.e(TAG, "Got an exception trying to validate a purchase: " + e);
return false;
}
}
And then i call it like this in my App menu:
if (id == R.id.action_pro) {
BillingManager mbilling = new BillingManager(MainActivity.this);
mbilling.startPurchaseFlow();
return true;
}
Actually it turns out that if I read the logs in debugging mode seems that onPurchasesUpdated() method throws the error -1 as response code! So this means that the responsecode is -1 which according to Java documentation is a generic error in http protocol... Why am I getting this?
The code seems pretty good even if compared to others or to guides found online. Does anyone have any suggestions?
Please make sure your billing client is initialized before you start the purchaseflow.
response code -1 indicates billingclient disconnected
I want to receive sever data ONLY when connected to the internet. Everything works fine (fetching data, displaying data) also caching the data received is fine.
The Only issue I get is when the internet is on.
The data I get/displayed is from both the server and the cached one and I can't seem to find a way to display ONLY sever data when internet is on and cache when internet is OFF.
private void NotesView() {
StringRequest stringRequest=new StringRequest(Request.Method.POST, SERVER_URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONArray jsonArray=new JSONArray(response);
for (int i=0;i<jsonArray.length();i++){
//looping through the array
mAdapter.notifyDataSetChanged();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//errors
}
}){
//offline availability cache for 24 hours
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
try {
Cache.Entry cacheEntry = HttpHeaderParser.parseCacheHeaders(response);
if (cacheEntry == null) {
cacheEntry = new Cache.Entry();
}
final long cacheHitButRefreshed = 3 * 60 * 1000; // in 3 minutes cache will be hit, but also refreshed on background
final long cacheExpired = 24 * 60 * 60 * 1000; // in 24 hours this cache entry expires completely
long now = System.currentTimeMillis();
final long softExpire = now + cacheHitButRefreshed;
final long ttl = now + cacheExpired;
cacheEntry.data = response.data;
cacheEntry.softTtl = softExpire;
cacheEntry.ttl = ttl;
String headerValue;
headerValue = response.headers.get("Date");
if (headerValue != null) {
cacheEntry.serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue);
}
headerValue = response.headers.get("Last-Modified");
if (headerValue != null) {
cacheEntry.lastModified = HttpHeaderParser.parseDateAsEpoch(headerValue);
}
cacheEntry.responseHeaders = response.headers;
final String string = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
return Response.success(string, cacheEntry);
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
}
}
#Override
protected void deliverResponse(String response) {
super.deliverResponse(response);
}
#Override
protected VolleyError parseNetworkError(VolleyError volleyError) {
return super.parseNetworkError(volleyError);
}
#Override
public void deliverError(VolleyError error) {
super.deliverError(error);
}
//get current user id
#Override
protected Map<String, String> getParams() throws AuthFailureError {
User user=PreferenceManager.getInstance(getApplicationContext()).getUser();
int id=user.getId();
Map<String, String> params = new HashMap<String, String>();
params.put("id", String.valueOf(id));
return params;
}
};
MySingleton.getInstance(getApplicationContext()).addToRequestQueue(stringRequest);
}
When connected to the Internet I want to get server response only and not the cached data.
if(connected()) { stringRequest.setShouldCache(false);} just mAke your connected method which returns true if connected to internet..
EDIT: Figured it out -- see answer below
I'm attempting to generate registration tokens, store them in a server, and then use the tokens to send push notifications. At this point, I've successfully sent and stored registration tokens and am sending notifications from a web API, but they aren't arriving to my device. I was wondering if/what I should replace R.string.gcm_defaultSenderId with (i.e. the sender key from GCM?) I'm including my code for token registration as well as my notification listener below.
public class GCMRegistrationIntentService extends IntentService {
//Constants for success and errors
public static final String REGISTRATION_SUCCESS = "RegistrationSuccess";
public static final String REGISTRATION_ERROR = "RegistrationError";
private Context context;
private String sessionGUID = "";
private String userGUID = "";
//Class constructor
public GCMRegistrationIntentService() {
super("");
}
#Override
protected void onHandleIntent(Intent intent) {
context = getApplicationContext();
sessionGUID = RequestQueueSingleton.getInstance(context).getSessionGUID();
userGUID = RequestQueueSingleton.getInstance(context).getUserGUID();
//Registering gcm to the device
registerGCM();
}
//Registers the device to Google Cloud messaging and calls makeAPICall to send the registration
//token to the server
private void registerGCM() {
//Registration complete intent initially null
Intent registrationComplete;
//declare a token, try to find it with a successful registration
String token;
try {
//Creating an instanceid
InstanceID instanceID = InstanceID.getInstance(this);
//Getting the token from the instance id
token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
//Display the token, need to send to server
Log.w("GCMRegIntentService", "token:" + token);
String android_id = Settings.Secure.getString(context.getContentResolver(),
Settings.Secure.ANDROID_ID);
int osTypeCode = Constants.OST_ANDROID;
JSONObject parms = new JSONObject();
try {
parms.put("deviceID", android_id);
parms.put("OSTypeCode", osTypeCode);
parms.put("token", token);
} catch (JSONException e) {
e.printStackTrace();
}
Transporter oTransporter = new Transporter(Constants.TransporterSubjectUSER,
Constants.REGISTER_NOTIFICATION_TOKEN, "", parms, userGUID, sessionGUID);
oTransporter.makeAPICall(getApplicationContext(), "");
//on registration complete. creating intent with success
registrationComplete = new Intent(REGISTRATION_SUCCESS);
//Putting the token to the intent
registrationComplete.putExtra("token", token);
} catch (Exception e) {
//If any error occurred
Log.w("GCMRegIntentService", "Registration error");
registrationComplete = new Intent(REGISTRATION_ERROR);
}
//Sending the broadcast that registration is completed
LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
}
}
And the listener service:
public class GCMPushReceiverService extends GcmListenerService {
private static final String TAG = "GCMPushReceiverService";
//with every new message
#Override
public void onMessageReceived(String from, Bundle data){
System.out.println("WE'VE RECIEVED A MESSAGE");
String message = data.getString("message");
Log.d(TAG, "From: " + from);
Log.d(TAG, "Message: " + message);
sendNotification(message);
}
private void sendNotification(String message) {
Intent intent = new Intent(this, LogInPage.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
int requestCode = 0;
PendingIntent pendingIntent =
PendingIntent.getActivity(this, requestCode, intent, PendingIntent.FLAG_ONE_SHOT);
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder noBuilder = new NotificationCompat.Builder(this);
noBuilder.setContentTitle("title");
noBuilder.setContentText(message);
noBuilder.setContentIntent(pendingIntent);
noBuilder.setSound(sound);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, noBuilder.build()); //0 = ID of notification
}
}
Lastly, as it may be of some assistance, the information transporter/networking class:
public class Transporter {
private String subject;
private String request;
private String key;
private Date lastUpdateDate;
private boolean forceLoad = false;
private Date requestDate;
private Date responseDate;
private int status;
private String statusMsg = "";
private String tempKey = "";
private JSONObject additionalInfo = null;
private JSONObject parameters;
public static String sessionGUID = "";
public static String userGUID = "";
public static String SERVER = Constants.qa_api;
//transporter object to interact with the server, containing information about the request
//made by the user
public Transporter(String pSubject, String pRequest, String pKey,
JSONObject parms, String userGUID, String sessionGUID)
{
subject = pSubject;
request = pRequest;
key = pKey;
parameters = parms;
setUserGUID(userGUID);
setSessionGUID(sessionGUID);
}
//implements an API call for a given transporter, takes 2 arguments:
//the application context (call getApplicationContext() whenever it's called)
//and a String that represents the field that we are trying to update (if there is one)
//i.e. if we are calling getUserFromSession(), we want the user guid so jsonID = "userGUID"
public void makeAPICall(final Context context, final String jsonID) {
RequestQueue mRequestQueue =
RequestQueueSingleton.getInstance(context).getRequestQueue();
String targetURL = getServerURL() + "/Transporter.aspx";
StringRequest postRequest = new StringRequest(Request.Method.POST, targetURL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
String parseXML= parseXML(response);
System.out.println("response: " + parseXML);
JSONObject lastResponseContent = null;
try {
lastResponseContent = new JSONObject(parseXML);
} catch (JSONException e) {
e.printStackTrace();
}
try {
if (lastResponseContent != null && !jsonID.equals("")) {
String info = lastResponseContent.getString(jsonID);
if (jsonID.equals("userGUID")) {
userGUID = info;
RequestQueueSingleton.getInstance(context).setUserGUID(userGUID);
}
}
//put other things in here to pull whatever info
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
}) {
#Override
public byte[] getBody() throws AuthFailureError {
String body = getXML(subject,
request, "",
sessionGUID, userGUID, null, parameters);
return body.getBytes();
}
};
postRequest.setTag("POST");
mRequestQueue.add(postRequest);
}
you need to send a post to the url "https://android.googleapis.com/gcm/send":
private void sendGCM() {
StringRequest strReq = new StringRequest(Request.Method.POST,
"https://android.googleapis.com/gcm/send", new Response.Listener<String>() {
#Override
public void onResponse(String response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
NetworkResponse networkResponse = error.networkResponse;
Log.e(TAG, "Volley error: " + error.getMessage() + ", code: " + networkResponse);
Toast.makeText(getApplicationContext(), "Volley error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
params.put("data", "message that you send");
params.put("to", "token gcm");
Log.e(TAG, "params: " + params.toString());
return params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String,String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
headers.put("Authorization", "key="google key");
return headers;
}
};
}
So the Volley calls are non-sequential so the first call (to get a userGUID) didn't return before the second call (to register for notifications), so while the token registration was "successful," there was no corresponding user information so it didn't know how/where to send the push notification. To resolve, I made a special case in the makeAPICall class which created another StringRequest which first basically did the normal getUserFromSession but then recursively called MakeAPICall with the new userGUID information. To avoid an infinite loop, I used an if else statement: (if userGUID == null || userGUID.equals("")) then I did the recursive call, so when the first call returned that conditional was always false and it would only make one recursive call. This answer may be a rambling a bit, but the key take away is using onResponse to make another Volley call for sequential requests. See: Volley - serial requests instead of parallel? and Does Volley library handles all the request sequentially
I want to use Twitter Rest Api without using twitter4j. Fabric is fine but i couldn't find a method like gettingUserFollowers(). I don't know why it has. Anyway I want to call my user followers ids using this service. https://dev.twitter.com/rest/reference/get/followers/ids
I have looked a tutorial from fabric website(http://docs.fabric.io/android/twitter/access-rest-api.html#tweets). There is a class for getting a custom service. But i couldn't understan how i can call it sending parameter.I changed it as following
import com.twitter.sdk.android.core.TwitterApiClient;
import com.twitter.sdk.android.core.TwitterSession;
import retrofit.http.GET;
import retrofit.http.Query;
public class MyTwitterApiClient extends TwitterApiClient {
public MyTwitterApiClient(TwitterSession session) {
super(session);
}
public CustomService getCustomService() {
return getService(CustomService.class);
}
interface CustomService {
#GET("/1.1/followers/ids.json")
void show(#Query("user_id") long id);
}
}
I think when i send an id ,service brings followers ids.
MyTwitterApiClient aa = new MyTwitterApiClient(session);
aa.getCustomService().show(userId);
But app is stopped.What is my wrong ?
LogCat is
5897-15897/com.tumymedia.tumer.lylafortwitter E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.tumymedia.tumer.lylafortwitter, PID: 15897
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=140, result=-1, data=Intent { (has extras) }} to activity {com.tumymedia.tumer.lylafortwitter/com.tumymedia.tumer.lylafortwitter.MainActivity}: java.lang.IllegalArgumentException: CustomService.show: Must have either a return type or Callback as last argument.
at android.app.ActivityThread.deliverResults(ActivityThread.java:4058)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4101)
at android.app.ActivityThread.access$1400(ActivityThread.java:177)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1497)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5942)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
Caused by: java.lang.IllegalArgumentException: CustomService.show: Must have either a return type or Callback as last argument.
at retrofit.RestMethodInfo.methodError(RestMethodInfo.java:123)
at retrofit.RestMethodInfo.parseResponseType(RestMethodInfo.java:285)
at retrofit.RestMethodInfo.<init>(RestMethodInfo.java:113)
at retrofit.RestAdapter.getMethodInfo(RestAdapter.java:213)
at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:236)
at java.lang.reflect.Proxy.invoke(Proxy.java:397)
at com.tumymedia.tumer.lylafortwitter.$Proxy16.show(Unknown Source)
at com.tumymedia.tumer.lylafortwitter.MainActivity$1.success(MainActivity.java:55)
at com.twitter.sdk.android.core.identity.TwitterAuthClient$CallbackWrapper.success(TwitterAuthClient.java:230)
at com.twitter.sdk.android.core.Callback.success(Callback.java:40)
at com.twitter.sdk.android.core.identity.AuthHandler.handleOnActivityResult(AuthHandler.java:91)
at com.twitter.sdk.android.core.identity.TwitterAuthClient.onActivityResult(TwitterAuthClient.java:161)
at com.twitter.sdk.android.core.identity.TwitterLoginButton.onActivityResult(TwitterLoginButton.java:131)
at com.tumymedia.tumer.lylafortwitter.MainActivity.onActivityResult(MainActivity.java:96)
at android.app.Activity.dispatchActivityResult(Activity.java:6543)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4054)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4101)
at android.app.ActivityThread.access$1400(ActivityThread.java:177)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1497)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5942)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
Actually Fabric uses retrofit to make REST Api calls and as mentioned
in Fabric documentation, for getting ids of followers we need to pass
user_id as parameter and retrieve list in response.
MyTwitterApiClient.java
import com.twitter.sdk.android.core.Callback;
import com.twitter.sdk.android.core.TwitterApiClient;
import com.twitter.sdk.android.core.TwitterSession;
import retrofit.client.Response;
import retrofit.http.GET;
import retrofit.http.Query;
public class MyTwitterApiClient extends TwitterApiClient {
public MyTwitterApiClient(TwitterSession session) {
super(session);
}
/**
* Provide CustomService with defined endpoints
*/
public CustomService getCustomService() {
return getService(CustomService.class);
}
}
// example users/show service endpoint
interface CustomService {
#GET("/1.1/followers/ids.json")
void list(#Query("user_id") long id, Callback<Response> cb);
}
Now in MainActivity we will authenticate the user and then by getting
the session we will retrieve the list of all followers corresponding
to a userid.
MainActivity.java
public class MainActivity extends AppCompatActivity {
// Note: Your consumer key and secret should be obfuscated in your source code before shipping.
private static final String TWITTER_KEY = "YOUR_TWITTER_KEY";
private static final String TWITTER_SECRET = "YOUR_TWITTER_SECRET";
TwitterLoginButton loginButton;
SharedPreferences shared;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TwitterAuthConfig authConfig = new TwitterAuthConfig(TWITTER_KEY, TWITTER_SECRET);
Fabric.with(this, new Twitter(authConfig), new Crashlytics());
setContentView(R.layout.activity_main);
shared = getSharedPreferences("demotwitter", Context.MODE_PRIVATE);
loginButton = (TwitterLoginButton) findViewById(R.id.login_button);
loginButton.setCallback(new Callback<TwitterSession>() {
#Override
public void success(Result<TwitterSession> result) {
// Do something with result, which provides a TwitterSession for making API calls
TwitterSession session = Twitter.getSessionManager()
.getActiveSession();
TwitterAuthToken authToken = session.getAuthToken();
String token = authToken.token;
String secret = authToken.secret;
//Here we get all the details of user's twitter account
System.out.println(result.data.getUserName()
+ result.data.getUserId());
Twitter.getApiClient(session).getAccountService()
.verifyCredentials(true, false, new Callback<User>() {
#Override
public void success(Result<User> userResult) {
User user = userResult.data;
//Here we get image url which can be used to set as image wherever required.
System.out.println(user.profileImageUrl+" "+user.email+""+user.followersCount);
}
#Override
public void failure(TwitterException e) {
}
});
shared.edit().putString("tweetToken", token).commit();
shared.edit().putString("tweetSecret", secret).commit();
TwitterAuthClient authClient = new TwitterAuthClient();
authClient.requestEmail(session, new Callback<String>() {
#Override
public void success(Result<String> result) {
// Do something with the result, which provides the
// email address
System.out.println(result.toString());
Log.d("Result", result.toString());
Toast.makeText(getApplicationContext(), result.data,
Toast.LENGTH_LONG).show();
}
#Override
public void failure(TwitterException exception) {
// Do something on failure
System.out.println(exception.getMessage());
}
});
MyTwitterApiClient apiclients=new MyTwitterApiClient(session);
apiclients.getCustomService().list(result.data.getUserId(), new Callback<Response>() {
#Override
public void failure(TwitterException arg0) {
// TODO Auto-generated method stub
}
#Override
public void success(Result<Response> arg0) {
// TODO Auto-generated method stub
BufferedReader reader = null;
StringBuilder sb = new StringBuilder();
try {
reader = new BufferedReader(new InputStreamReader(arg0.response.getBody().in()));
String line;
try {
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
String result = sb.toString();
System.out.println("Response is>>>>>>>>>"+result);
try {
JSONObject obj=new JSONObject(result);
JSONArray ids=obj.getJSONArray("ids");
//This is where we get ids of followers
for(int i=0;i<ids.length();i++){
System.out.println("Id of user "+(i+1)+" is "+ids.get(i));
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
#Override
public void failure(TwitterException exception) {
// Do something on failure
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Pass the activity result to the login button.
loginButton.onActivityResult(requestCode, resultCode, data);
}
}
In Retrofit 2.0,
Interface ->
public interface FollowersService {
#GET("/1.1/followers/list.json")
Call<ResponseBody> list(#Query("screen_name") String userId);
}
Call to method ->
FollowersService followersService = followersTwitterApiClient.getFollowersService();
Call<ResponseBody> call = followersService.list(userId);
call.enqueue(followerCallback);
Custom Api client ->
public class FollowersTwitterApiClient extends TwitterApiClient {
public FollowersTwitterApiClient(TwitterSession twitterSession){
super(twitterSession);
}
public FollowersService getFollowersService(){
return getService(FollowersService.class);
}
}
You need to authenticate to Twitter in order to be able to call the API and get results. I don't see that happening in this code. (Maybe you are doing it outside this code?)
Details on Twitter authentication at https://dev.twitter.com/oauth
I'm using this code for sending data to server , but when i want to parser response data on volley onResponse method , my UI freezing .
JsonObjectRequest req = new JsonObjectRequest(Method.GET, url, null, new Response.Listener<JSONObject>()
{
#Override
public void onResponse(JSONObject response)
{
parseFromJsonObject(response);
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error)
{
}
});
RequestHelper.getInstance().addToRequestQueue(req, this);
And it's parser method
public boolean parseFromJsonObject(JSONObject response)
{
boolean validResponse = super.isValidResponse(response);
try
{
if(response.has("keywords"))
{
JSONObject keywords = response.getJSONObject("keywords");
Iterator<?> langIterator = keywords.keys();
ArrayList<LanguagesStorage> languagesStorageArray = new ArrayList<LanguagesStorage>();
while(langIterator.hasNext())
{
String lang = (String) langIterator.next();
JSONObject langValues = keywords.getJSONObject(lang);
Iterator<?> valueIterator = langValues.keys();
while(valueIterator.hasNext())
{
String key = (String) valueIterator.next();
String value = (String) langValues.getString(key);
LanguagesStorage languagesStorage = new LanguagesStorage();
languagesStorage.setKey(key);
languagesStorage.setLang(lang);
languagesStorage.setValue(value);
languagesStorageArray.add(languagesStorage);
}
}
if(languagesStorageArray.size() > 0)
{
LanguageAdapter languageAdapter = new LanguageAdapter();
languageAdapter.insert(languagesStorageArray, true);
}
}
return lastParsingStatus = true;
}
catch (JSONException e)
{
RLog.error("Parsing error in keyword Parser " + e);
return lastParsingStatus = false;
}
}
What is the issue ? Why my UI thread freezing?
Volley onResponce work inside the UI thread
I recommend you to do parsing inside a separate thread.
In your parseFromJsonObject method, try to create a new Thread and inside that thread execute your parsing data.