Multiple Query Params with Asyncronous Call Retrofit - asynchronous

UPDATE:
I have learned what I am looking to do is to use the Async within Retrofit with multiple queries too. I have updated my code, but I cannot get the async with the queries.
I am using Retrofit to make my data calls to a movie database and need to change the sort order depending on user settings. I am not clear how I could add this functionality to my interface.
sort_by=highest_rating.desc
or
sort_by=popularity.desc
Interface:
public interface MovieDatabaseApiCient {
#GET("/3/discover/movie")
void getData(#Query("api_key") String apiKey, #Query("sort_by") String sortByValue, Callback<MovieDbModel> response);
}
UPDATED API INTERFACE:
public interface MovieDatabaseApiCient {
#GET("/3/discover/movie?sort_by=popularity.desc&api_key=xxxxxxx")
void getMoviesByPopularityDesc(Callback<MovieDbModel> response);
#GET("/3/discover/movie?sort_by=vote_average_desc&api_key=xxxxxxxx")
void getMoviesByVotingDesc(Callback<MovieDbModel> response);
}
UPDATED DATA CALL THAT WORKS:
private void makeDataCall(String sortPreference) {
final RestAdapter restadapter = new RestAdapter.Builder().setEndpoint(ENDPOINT_URL).build();
MovieDatabaseApiCient apiLocation = restadapter.create(MovieDatabaseApiCient.class);
if (sortPreference.equals(this.getString(R.string.sort_order_popularity)) ){
apiLocation.getMoviesByPopularityDesc (new Callback<MovieDbModel>() {
#Override
public void success(MovieDbModel movieModels, Response response) {
movieDbResultsList = movieModels.getResults();
MoviesGridViewAdapter adapter = new MoviesGridViewAdapter(getApplicationContext(), R.layout.movie_gridview_item, movieDbResultsList);
gridView.setAdapter(adapter);
}
#Override
public void failure(RetrofitError error) {
Log.d("ERROR", error.toString());
Toast.makeText(getApplicationContext(), "Error: " + error.toString(), Toast.LENGTH_SHORT).show();
}
});
} else {
apiLocation.getMoviesByVotingDesc( new Callback<MovieDbModel>() {
#Override
public void success(MovieDbModel movieModels, Response response) {
movieDbResultsList = movieModels.getResults();
MoviesGridViewAdapter adapter = new MoviesGridViewAdapter(getApplicationContext(), R.layout.movie_gridview_item, movieDbResultsList);
gridView.setAdapter(adapter);
}
#Override
public void failure(RetrofitError error) {
Log.d("ERROR", error.toString());
Toast.makeText(getApplicationContext(), "Error: " + error.toString(), Toast.LENGTH_SHORT).show();
}
});
}
}
My call for the data:
private void makeDataCall (String apiKey, String sortPreference) {
final RestAdapter restadapter = new RestAdapter.Builder().setEndpoint(ENDPOINT_URL).build();
MovieDatabaseApiCient apiLocation = restadapter.create(MovieDatabaseApiCient.class);
apiLocation.getData(apiKey, sortPreference, new Callback<MovieDbModel>){
#Override
public void success(MovieDbModel movieModels, Response response) {
movieDbResultsList = movieModels.getResults();
MoviesGridViewAdapter adapter = new MoviesGridViewAdapter(getApplicationContext(), R.layout.movie_gridview_item, movieDbResultsList);
gridView.setAdapter(adapter);
}
#Override
public void failure(RetrofitError error) {
Log.d("ERROR", error.toString());
Toast.makeText(getApplicationContext(), "Error: " + error.toString(), Toast.LENGTH_SHORT).show();
}
});
}
I found a way to do Synchronously, but not asynchronously.

From your question and comment, IHMO, you should import retrofit.Callback; instead of import com.squareup.okhttp.Callback;
My code as the following has no compile error:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// creating a RestAdapter using the custom client
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(API_URL_BASE)
.setLogLevel(RestAdapter.LogLevel.FULL)
.setClient(new OkClient(mOkHttpClient))
.build();
WebService webService = restAdapter.create(WebService.class);
retrofit.Callback<GetRoleData> callback = new Callback<GetRoleData>() {
#Override
public void success(GetRoleData getRoleData, retrofit.client.Response response) {
}
#Override
public void failure(RetrofitError error) {
}
};
webService.getData("api_key", "sort_by", callback);
}
Interface:
public interface WebService {
#GET("/3/discover/movie")
void getData(#Query("api_key") String apiKey, #Query("sort_by") String sortByValue, Callback<GetRoleData> response);
}
So, please check your code again

Related

How to fix apps containing an unsafe implementation of TrustManager and HostnameVerifier

After upload my apps in Google play Store, getting a mail from google that the app are using an unsafe implementation of the TrustManager and HostnameVerifier. How to fix this problem? Can someone give me a direction?
public class HttpsTrustManager implements X509TrustManager {
private static TrustManager[] trustManagers;
private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{};
#Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
#Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
public boolean isClientTrusted(X509Certificate[] chain) {
return true;
}
public boolean isServerTrusted(X509Certificate[] chain) {
return true;
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return _AcceptedIssuers;
}
public static void allowAllSSL() {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
SSLContext context = null;
if (trustManagers == null) {
trustManagers = new TrustManager[]{new HttpsTrustManager()};
}
try {
context = SSLContext.getInstance("TLS");
context.init(null, trustManagers, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
HttpsURLConnection.setDefaultSSLSocketFactory(context
.getSocketFactory());
}
}
I have tried the above code.

Post value to server when no internet connection android studio

I'm trying to send a value to the server when the connection doesn't exist, when it connects to the internet it runs fine and is saved to the server and sqlite. but the problem arises when switching state from offline to online. I send one value to the server when the connection is offline but when the state moves to online the value I sent earlier becomes multiple on the server while in the sqlite database only one value is stored.
this is my network state checker class
public class NetworkStateCheckerNama extends BroadcastReceiver {
//context and database helper object
private Context context;
private Database db;
ApiRequestData apiRequestData;
#Override
public void onReceive(Context context, Intent intent) {
this.context = context;
apiRequestData = ServiceGenerator.createBaseService(this.context, ApiRequestData.class);
db = new Database(context);
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
//if there is a network
if (activeNetwork != null) {
//if connected to wifi or mobile data plan
if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI || activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
//getting all the unsynced user
Cursor cursor2 = db.getUnsyncedNama();
if (cursor2.moveToFirst()) {
do {
//calling the method to save the unsynced name to MySQL
Nama(
cursor2.getString(cursor2.getColumnIndexOrThrow(Database.KOLOM_NAMA_COBA)),
cursor2.getString(cursor2.getColumnIndexOrThrow(Database.KOLOM_NIP_COBA))
);
} while (cursor2.moveToNext());
}
}
}
}
private void Nama(final String nama,final String nip) {
//Call call = retrofit.create(APIInterface.class).saveName(name);
Call call = apiRequestData.nama_query(nama,nip);
call.enqueue(new Callback<Responses>() {
#Override
public void onResponse(Call<Responses> call, Response<Responses> response) {
if (response.code() == 200){
db.updateNamaStatus(nip, MainActivity.NAME_SYNCED_WITH_SERVER);
//sending the broadcast to refresh the list
context.sendBroadcast(new Intent(MainActivity.DATA_SAVED_BROADCAST_MAIN));
}
}
#Override
public void onFailure(Call<Responses> call, Throwable t) {
}
});
}
this is my MainActivity Class
public class MainActivity extends AppCompatActivity {
Session session;
Button buttonLogout,buttonKirim;
TextView textViewNamaMain, textViewNipMain;
EditText editTextNamaMain;
Database database;
private AdapterNama mAdapter;
private RecyclerView listviewNama;
ApiRequestData apiRequestData;
//1 means data is synced and 0 means data is not synced
public static final int NAME_SYNCED_WITH_SERVER = 1;
public static final int NAME_NOT_SYNCED_WITH_SERVER = 0;
//a broadcast to know weather the data is synced or not
public static final String DATA_SAVED_BROADCAST_MAIN = "com.example.myapplication.datasave2";
ArrayList<Nama> namaArray;
ArrayList<User> users;
BroadcastReceiver broadcastReceiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
session = new Session(this);
buttonLogout = findViewById(R.id.buttonLogout);
buttonKirim = findViewById(R.id.buttonKirim);
textViewNipMain = findViewById(R.id.textViewNipMain);
textViewNamaMain = findViewById(R.id.textViewNamaMain);
editTextNamaMain = findViewById(R.id.editTextTextNamaMain);
String nip = getIntent().getStringExtra("nip");
listviewNama = findViewById(R.id.lv_nama);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
listviewNama.setLayoutManager(layoutManager);
listviewNama.setItemAnimator(new DefaultItemAnimator());
database = new Database(this);
namaArray = new ArrayList<>();
users = new ArrayList<>();
apiRequestData = ServiceGenerator.createBaseService(this, ApiRequestData.class);
textViewNipMain.setText(nip);
registerReceiver(new NetworkStateCheckerNama(), new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
loadDaftarNama(nip);
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//loading the names again
loadDaftarNama(nip);
}
};
registerReceiver(broadcastReceiver, new IntentFilter(DATA_SAVED_BROADCAST_MAIN));
if(!session.isUserLogin()){
logout();
}
buttonKirim.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SimpanKeServer();
}
});
buttonLogout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
logout();
}
});
users.clear();
Cursor cursor = database.getUsersWhereNip(nip);
if (cursor.moveToFirst()) {
do {
User user = new User(
cursor.getString(cursor.getColumnIndexOrThrow(Database.KOLOM_NIP)),
cursor.getString(cursor.getColumnIndexOrThrow(Database.KOLOM_NAMA)),
cursor.getString(cursor.getColumnIndexOrThrow(Database.KOLOM_PASSWORD)),
cursor.getInt(cursor.getColumnIndexOrThrow(Database.KOLOM_STATUS))
);
users.add(user);
textViewNamaMain.setText(user.getNama());
} while (cursor.moveToNext());
}
}
private void SimpanKeServer(){
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Saving Name...");
progressDialog.show();
String nama = editTextNamaMain.getText().toString();
String nip = textViewNipMain.getText().toString();
Call call = apiRequestData.nama_query(nama,nip);
call.enqueue(new Callback<Responses>() {
#Override
public void onResponse(Call<Responses> call, Response<Responses> response) {
progressDialog.dismiss();
if(response.code() == 200){
//if there is a success
//storing the name to sqlite with status synced
SaveNamaToLocal(nama,nip,NAME_SYNCED_WITH_SERVER);
Toast.makeText(MainActivity.this, "Berhasil", Toast.LENGTH_SHORT).show();
}else {
progressDialog.dismiss();
//if there is some error
//saving the name to sqlite with status unsynced
SaveNamaToLocal(nama,nip,NAME_NOT_SYNCED_WITH_SERVER);
Toast.makeText(MainActivity.this, "Gagal", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<Responses> call, Throwable t) {
progressDialog.dismiss();
SaveNamaToLocal(nama,nip,NAME_NOT_SYNCED_WITH_SERVER);
Toast.makeText(MainActivity.this, "Gagal", Toast.LENGTH_SHORT).show();
}
});
}
private void SaveNamaToLocal(String nama, String nip, int status){
database.Nama(nama,nip,status);
Nama namas = new Nama(nama,nip,status);
namaArray.add(namas);
refreshList();
}
private void loadDaftarNama(String nip) {
namaArray.clear();
Cursor cursor = database.getNama(nip);
if (cursor.moveToFirst()) {
do {
Nama nama = new Nama(
cursor.getString(cursor.getColumnIndexOrThrow(Database.KOLOM_NAMA_COBA)),
cursor.getString(cursor.getColumnIndexOrThrow(Database.KOLOM_NIP_COBA)),
cursor.getInt(cursor.getColumnIndexOrThrow(Database.KOLOM_STATUS_NAMA_COBA))
);
namaArray.add(nama);
} while (cursor.moveToNext());
}
mAdapter = new AdapterNama(this, namaArray);
listviewNama.setAdapter(mAdapter);
}
#SuppressLint("NotifyDataSetChanged")
private void refreshList() {
mAdapter.notifyDataSetChanged();
}
private void logout(){
session.updateUserLoginStatus(false);
finish();
startActivity(new Intent(MainActivity.this,LoginActivity.class));
}
}
this when online
enter image description here
enter image description here
this the problem when state internet switch from offline to online
enter image description here
enter image description here
Even in server send 3 same values
I'm sorry for my english and my question structure im new in programmer, and thank you for the answer

Meteor ddp notify specific client

I'm using meteor ddp (Distributed Data Protocol) to my application. Server code is written using meteor and Android client using java.
Server code
if (Meteor.isServer) {
Users = new Mongo.Collection('testUsers');
Meteor.publish('methodToListen', function(){
return Users.find();
});
}
Client code (https://github.com/delight-im/Android-DDP)
public class MainActivity extends AppCompatActivity implements MeteorCallback {
private Meteor mMeteor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Meteor.setLoggingEnabled(true);
mMeteor = new Meteor(this, "ws://192.168.137.1:3000/websocket");
mMeteor.addCallback(this);
mMeteor.connect();
}
#Override
public void onConnect(boolean signedInAutomatically) {
String subscriptionId = mMeteor.subscribe("methodToListen");
}
#Override
public void onDisconnect() {
}
#Override
public void onException(Exception e) {
}
#Override
public void onDataAdded(String collectionName, String documentID, String newValuesJson) {
Log.d("DATACHANGED", "Add " + collectionName + ", " + documentID + ", " + newValuesJson);
}
#Override
public void onDataChanged(String collectionName, String documentID, String updatedValuesJson, String removedValuesJson) {
}
#Override
public void onDataRemoved(String collectionName, String documentID) {
}
}
So now every client that connects to server see live database updates. Is it possible to send updates only for specific client? So for example when user sign in to system it gets unique id and based on that id is it possible to send updated data?
Updated I can get information about connected clients
Meteor.onConnection(function(connection) {
console.log(connection.id + ", " + connection.clientAddress);
});
So for example ip addresses could be id

facebook profile is null for the first time

The function onCurrentProfileChanged doesnt get called everytime I logout and login, but if I remove the profiletracker, the profile comes as null for the first time login.How do i resolve the issue?. I have pasted the code below.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferenceManager.setApplicationContext(getApplicationContext());
onregister();
SharedPreferenceManager.setPreference("notificationcount", 0);
FacebookSdk.sdkInitialize(this.getApplicationContext());
callbackManager = CallbackManager.Factory.create();
LoginManager.getInstance().registerCallback(callbackManager,
new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(final LoginResult loginResult) {
profileTracker = new ProfileTracker() {
#Override
protected void onCurrentProfileChanged(Profile oldProfile, Profile currentProfile) {
Profile.setCurrentProfile(currentProfile);
profileTracker.stopTracking();
GraphRequest request = GraphRequest.newMeRequest(
AccessToken.getCurrentAccessToken(),
new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(
JSONObject jsonObject,
GraphResponse response) {
try {
dismissProgressDialog();
final Profile profile = Profile.getCurrentProfile();
SharedPreferenceManager.setPreference("id", profile.getId());
email = jsonObject.getString("email");
gender = jsonObject.getString("gender");
if (mAuthTask == null) {
mAuthTask = new UserLoginTask(email, "", profile.getName(), "facebook", profile.getId(), AccessToken.getCurrentAccessToken().getToken(), gender, getRegistrationId(getApplicationContext()));
//Log.v("token", loginResult.getAccessToken().getToken());
mAuthTask.execute((Void) null);
}
} catch (JSONException exe) {
}
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "id,name,link,email,gender");
request.setParameters(parameters);
request.executeAsync();
}
};
profileTracker.startTracking();
}
#Override
public void onCancel() {
dismissProgressDialog();
LoginManager.getInstance().logOut();
}
#Override
public void onError(FacebookException exception) {
dismissProgressDialog();
LoginManager.getInstance().logOut();
}
});
Have you added this line in your code
LoginManager.getInstance().logInWithReadPermissions(this, Arrays.asList("public_profile,email"));
before call registerCallback?

Retrofit Observables and access to Response

I'm using Retrofit and RxJava but can't seem to do what I want.
Here's my declaration of my web service:
Observable<Response> rawRemoteDownload(#Header("Cookie") String token, #Path("programId") int programId);
The problem I have is the webservice is returning a 403 and a json payload with details.
Retrofit calls onError, only passing the Throwable so I can't check the response body.
Here's part of my test code
apiManager.rawRemoteDownloadRequest("token", 1).subscribe(new Observer<Response>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
// this is called and I've lost the response!
}
#Override
public void onNext(Response response) {
}
});
SOLUTION:
Thanks to Gomino, I went with this as a solution:
new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
if (throwable instanceof RetrofitError) {
Response response = ((RetrofitError) throwable).getResponse();
System.out.println(convertToString(response.getBody()));
}
}
where convertToString looks like:
private String convertToString(TypedInput body) {
byte[] bodyBytes = ((TypedByteArray) body).getBytes();
return new String(bodyBytes);
}
Check if the throwable is a RetrofitError:
#Override
public void onError(Throwable e) {
if (e instanceof RetrofitError) {
Response response = ((RetrofitError) e).getResponse();
}
}

Resources