I try the same method of initial&update using in Thermostat object to SmokeCOAlarm object but not work.
Does anyone know how to initial&update SmokeCOAlarm object?
or Nest hasn't opened for access SmokeCOAlarm object?!
Following is my code:
public class COSmokeAlarm extends Activity implements
NestAPI.AuthenticationListener, Listener.SmokeCOAlarmListener, Listener.ThermostatListener {
private Listener mUpdateListener;
private NestAPI mNestApi;
private SmokeCOAlarm mSmokeCOAlarm;
private Thermostat mThermostat;
private AccessToken mToken;
TextView txvBattery;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_co_smoke_alarm);
txvBattery = (TextView)findViewById(R.id.txvBattery);
mNestApi = NestAPI.getInstance();//Initial NestAPI, connect Firebase
mToken = Settings.loadAuthToken(this);//Loade AccessToken
authenticate(mToken);
}
private void updateBatteryTextView() {
if (mSmokeCOAlarm != null) {
txvBattery.setText(mSmokeCOAlarm.getBatteryHealth());
}
}
private void authenticate(AccessToken token) {
Log.v("COSmokeAlarm", "Authenticating...");
NestAPI.getInstance().authenticate(token, this);
}
#Override
public void onAuthenticationSuccess() {
Log.v("COSmokeAlarm", "Authentication succeeded.");
fetchData();
}
#Override
public void onAuthenticationFailure(int errorCode) {
Log.v("COSmokeAlarm", "Authentication failed with error: " + errorCode);
}
private void fetchData() {
Log.v("COSmokeAlarm", "Fetching data...");
mUpdateListener = new Listener.Builder()
.setSmokeCOAlarmListener(this)
.setThermostatListener(this)
.build();
mNestApi.addUpdateListener(mUpdateListener);
Toast.makeText(COSmokeAlarm.this, "Success fetching data.", Toast.LENGTH_SHORT).show();
}
#Override
public void onSmokeCOAlarmUpdated(#NonNull SmokeCOAlarm smokeCOAlarm) {
Log.v("COSmokeAlarm", String.format("COSmoke Alarm (%s) updated.", smokeCOAlarm.getDeviceID()));
this.mSmokeCOAlarm = smokeCOAlarm;
updateBatteryTextView();
}
#Override
public void onThermostatUpdated(#NonNull Thermostat thermostat) {
Log.v("COSmokeAlarm", String.format("Thermostat (%s) updated.", thermostat.getDeviceID()));
mThermostat = thermostat;
}
}
Go to Nest account and add permission "Smoke+CO alarm read v4"
then we can access SmokeCOAlarm information.
Related
I am currently working on an Android Application, and i have a problem to handle a request and execute a function just after.
The fact is my Retrofit request is in a Controller, used by a Service, and i am calling the service function inside my Activity (am i clear?).
Clearly, i have to manage one user (get and refresh access token from a webservice) and i need to be able to call my refreshToken() function and execute some code after getting and parsing the response.
This is my code :
UserActivity
public class UserActivity extends AppCompatActivity {
private final static String TAG = "UserActivity";
private User user;
private TextView textViewAccessTokenShow, textViewExpiresInShow, textViewIGPShow, textViewRefreshTokenShow;
private LoginController loginController;
private Wso2Service wso2Service, wso2ServiceIS;
boolean mBounded;
private LoginService loginService;
private Intent mIntent;
//Connection to LoginService
ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceDisconnected(ComponentName name) {
Toast.makeText(UserActivity.this, "Service is disconnected", Toast.LENGTH_LONG).show();
mBounded = false;
loginService = null;
Log.e(TAG, "onServiceDisconnected: " );
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
Toast.makeText(UserActivity.this, "Service is connected", Toast.LENGTH_LONG).show();
mBounded = true;
LoginService.LocalBinder mLocalBinder = (LoginService.LocalBinder) service;
loginService = mLocalBinder.getServerInstance();
user = loginService.getUser();
refreshIHM();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user);
mIntent = new Intent(this, LoginService.class);
textViewAccessTokenShow = findViewById(R.id.textViewAccessTokenShow);
textViewRefreshTokenShow = findViewById(R.id.textViewRefreshTokenShow);
textViewExpiresInShow = findViewById(R.id.textViewExpiresInShow);
textViewIGPShow = findViewById(R.id.textViewIGPShow);
}
#Override
protected void onResume() { //Getting my user updated outside this activity and printing his informations
super.onResume();
Log.i(TAG, "onResume: ");
if(mBounded == false){
bindService(mIntent, mConnection, BIND_AUTO_CREATE);
} else {
user = loginService.getUser();
refreshIHM();
}
}
public void onClickRefreshToken(View view){
//Where i have to refresh my token, and after that executing refreshIHM()
refreshIHM();
}
public void refreshIHM(){
Log.d(TAG, "refreshIHM() called");
Log.i(TAG, "refreshIHM: "+user.toString());
textViewExpiresInShow.setVisibility(View.VISIBLE);
textViewAccessTokenShow.setVisibility(View.VISIBLE);
textViewRefreshTokenShow.setVisibility(View.VISIBLE);
textViewIGPShow.setVisibility(View.VISIBLE);
textViewAccessTokenShow.setText(user.getAccess_token());
textViewAccessTokenShow.invalidate();
textViewAccessTokenShow.requestLayout();
textViewRefreshTokenShow.setText(user.getRefresh_token());
textViewRefreshTokenShow.invalidate();
textViewRefreshTokenShow.requestLayout();
textViewExpiresInShow.setText(String.valueOf(user.getExpire_in()));
textViewExpiresInShow.invalidate();
textViewExpiresInShow.requestLayout();
textViewIGPShow.setText(user.getId_group_parent());
textViewIGPShow.invalidate();
textViewIGPShow.requestLayout();
}
}
LoginController, where i execute every functions about User data
public class LoginController {
public static final String TAG = "LOGINSERVICE";
private User usertemp;
private Wso2Service wso2Service, wso2ServiceIS;
public LoginController(){
this.wso2Service = new Retrofit.Builder()
.baseUrl(Wso2Service.APIMENDPOINT)
.addConverterFactory(ScalarsConverterFactory.create())
.build()
.create(Wso2Service.class);
this.wso2ServiceIS = new Retrofit.Builder()
.baseUrl(Wso2Service.ISENDPOINT)
.addConverterFactory(ScalarsConverterFactory.create())
.build()
.create(Wso2Service.class);
}
public User parseUserInfo(String request, User user) {
try {
JSONObject jo = new JSONObject(request);
user.setAccess_token(jo.getString("access_token"));
user.setRefresh_token(jo.getString("refresh_token"));
user.setScope(jo.getString("scope"));
user.setId_token(jo.getString("id_token"));
user.setToken_type(jo.getString("token_type"));
user.setExpire_in(jo.getInt("expires_in"));
return user;
} catch (Exception e){
Log.e(TAG, "getUserInfo: "+e.toString());
}
return null;
}
public User parseIdGroupParentInfo(String request, User user){
try {
Log.i(TAG, "parseIdGroupParentInfo: "+request);
JSONObject jo = new JSONObject(request);
user.setId_group_parent(jo.getString("id_group_parent"));
return user;
} catch (Exception e){
Log.e(TAG, "parseIdGroupParentInfo: "+e.toString());
}
return null;
}
public void refreshToken(User user){
this.usertemp = user;
Log.i(TAG, "refreshToken: ");
this.wso2Service.getTokensByRefresh("refresh_token",user.getRefresh_token(),"openid", ApiConstants.token).enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if(response.isSuccessful()) {
//On parse la réponse
usertemp.setLogin_request_responseJSON(response.body());
parseUserInfo(response.body(), usertemp);
Log.i(TAG, "onLoginReady: " + usertemp.toString());
wso2ServiceIS.getUserInfo("Bearer "+usertemp.getAccess_token()).enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
Log.i(TAG, "onResponse: "+response.code()+response.body());
usertemp = parseIdGroupParentInfo(response.body(),usertemp);
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Log.e(TAG, "onFailure: ",t );
}
});
} else {
Log.e(TAG, "onResponse: " );
Log.e(TAG, "onResponse: Code "+response.code()+" Body : "+response.body() );
}
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Log.e(TAG, "onFailure: ",t );
}
});
}
}
LoginService, what i call in every activities to use the same User everytime
public class LoginService extends Service {
public final String TAG = "LoginService";
private User user;
private LoginController loginController;
IBinder mBinder = new LocalBinder();
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public class LocalBinder extends Binder {
public LoginService getServerInstance() {
return LoginService.this;
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand: ");
this.user = (User)intent.getSerializableExtra("user");
Log.i(TAG, "onStartCommand: "+user.toString());
loginController = new LoginController();
return START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate: ");
}
#Override
public void onDestroy() {
Log.i(TAG, "onDestroy: ");
super.onDestroy();
}
public User getUser(){
Log.i(TAG, "getUser: ");
return this.user;
}
public void regenerateByRefreshToken(){
Log.d(TAG, "regenerateByRefreshToken: ");
loginController.refreshToken(user);
Log.d(TAG, "regenerateByRefreshToken: end");
}
}
Do you have any idea about how to make my RefroFit function handle its response and only after executing another function inside my UI ? Or inside my regenerateByRefreshToken() function ?
Thank you !
Do you have any idea about how to make my RefroFit function handle its
response and only after executing another function inside my UI ? Or
inside my regenerateByRefreshToken() function ?
As per the current implementation, You can achieve this using Callbacks. Create two callbacks to
Get the usertemp inside service from the controller after successful execution.
Second callback to send the user object back to activity from service
So follow below steps:
a) Create callback interface
// create new OnUserRefresh.java
public interface OnUserRefresh{
void onRefresh(User user);
void onError(Throwable t);
}
b) Modify the controller to receive the callback reference
public class LoginController {
// code...
public void refreshToken(User user, OnUserRefresh onUserRefresh){
this.usertemp = user;
Log.i(TAG, "refreshToken: ");
this.wso2Service.getTokensByRefresh("refresh_token",user.getRefresh_token(),"openid", ApiConstants.token).enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if(response.isSuccessful()) {
//On parse la réponse
usertemp.setLogin_request_responseJSON(response.body());
parseUserInfo(response.body(), usertemp);
Log.i(TAG, "onLoginReady: " + usertemp.toString());
wso2ServiceIS.getUserInfo("Bearer "+usertemp.getAccess_token()).enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
Log.i(TAG, "onResponse: "+response.code()+response.body());
usertemp = parseIdGroupParentInfo(response.body(),usertemp);
onUserRefresh.onRefresh(usertemp);
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Log.e(TAG, "onFailure: ",t );
onUserRefresh.onError(t);
}
});
} else {
Log.e(TAG, "onResponse: " );
Log.e(TAG, "onResponse: Code "+response.code()+" Body : "+response.body() );
}
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Log.e(TAG, "onFailure: ",t );
}
});
}
}
c) Pass callback object from service to controller
public class LoginService extends Service {
/*Add interface, to be used for data passing*/
public void regenerateByRefreshToken(OnUserRefresh onUserRefresh){
Log.d(TAG, "regenerateByRefreshToken: ");
loginController.refreshToken(user, new OnUserRefresh(){
#Override
void onRefresh(User user){
this.user = user;
onUserRefresh.onRefresh(user); // trigger onRefresh in client i.e. activity
}
#Override
void onError(Throwable t){
onUserRefresh.onError(t);
// log error etc
}
});
Log.d(TAG, "regenerateByRefreshToken: end");
}
}
d) Pass callback object from activity to service and implement UI updates method call
public class UserActivity extends AppCompatActivity {
public void onClickRefreshToken(View view){
//Where i have to refresh my token, and after that executing refreshIHM()
loginService.regenerateByRefreshToken(new OnUserRefresh(){
#Override
void onRefresh(User user){
this.user = user;
refreshIHM();
}
#Override
void onError(Throwable t){
// log error etc
}
});
}
}
Note: The initial user reference is always null as you are receiving it from intent in your service
this.user = (User)intent.getSerializableExtra("user");
but you are neither initialising any user object in UserActivity nor adding it in the mIntent object so you need to a user object with token and other required properties in activity for network calls.
You can optimize the flow with lambdas, Rxjava etc as well.
I'm writing a class with requests to rest API (Yandex disk). I use volley, but I do have some problems with getting a response from it. You can check the rest API here.
I use volley and I can get a response in the debugger, but not in my Activity.
Here is my Requests class
class Requests {
private String response_of_server, token;
private String url = "https://cloud-api.yandex.net/v1/disk";
private Context context;
Requests (String token, Context context) {
this.token = token;
this.context = context;
}
private void set_response_of_server(String response) {
this.response_of_server = response;
}
String get_response() {
return response_of_server;
}
void get_metadata_of_user() {
try {
/*Request*/
RequestQueue queue = Volley.newRequestQueue(this.context);
Response.ErrorListener error_listener = new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
};
Response.Listener<String> response_listener = new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
set_response_of_server(response);
}
};
StringRequest getRequest = new StringRequest(Request.Method.GET, url+"?fields=user", response_listener, error_listener) {
#Override
public Map<String, String> getHeaders() {
Map<String, String> params = new HashMap<>();
params.put("Host", "cloud-api.yandex.net");
params.put("Authorization", token);
return params;
}
};
queue.add(getRequest);
/*Request end*/
} catch (Exception e) {
e.printStackTrace();
}
}
}
And the MainActivity where I want my response.
public class MainActivity extends AppCompatActivity {
private final String ID_OF_APP = "Your token of app";
private final String URL_FOR_CODE_QUERY = "https://oauth.yandex.com/authorize?response_type=token&client_id=" + ID_OF_APP;
private String SAVED_TOKEN = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn_get_code = findViewById(R.id.btn_get_code); // send to get code page (yandex)
btn_get_code.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(URL_FOR_CODE_QUERY));
startActivity(i);
}
});
Button btn_sign_in = findViewById(R.id.btn_sign_in);
btn_sign_in.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EditText code_field = findViewById(R.id.code_field);
String token = code_field.getText().toString();
save_token(token);
try {
if(check_token()) {
//Toast.makeText(MainActivity.this, "You are successfully signed in", Toast.LENGTH_SHORT).show();
// TODO change activity
}
else {}
} catch (InterruptedException e) {
e.printStackTrace();
}
//Toast.makeText(MainActivity.this, "Something went wrong. Please, check your connection and try again later", Toast.LENGTH_SHORT).show();
}
});
}
private void save_token(String token) {
SharedPreferences sPref = getPreferences(MODE_PRIVATE);
SharedPreferences.Editor ed = sPref.edit();
ed.putString(SAVED_TOKEN, token);
ed.apply();
}
private String load_token() {
SharedPreferences sPref = getPreferences(MODE_PRIVATE);
return sPref.getString(SAVED_TOKEN, "");
}
private boolean check_token() throws InterruptedException {
String token = load_token();
String result;
Requests request = new Requests(token, this);
request.get_metadata_of_user();
result = request.get_response();
Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
return !(result.equals("-1"));
}
}
check_token() function at the moment should just make a toast with a response of the server. However, I cannot get the Toast or any response coming back from the server.
You have a Requests class which has the function to call the server API which is Asynchronous. Hence, you will not get the result immediately after calling the request.get_metadata_of_user(); in your check_token() function.
Hence I would like to suggest you modify your Request class like the following.
public class Requests {
private String response_of_server, token;
private String url = "https://cloud-api.yandex.net/v1/disk";
private Context context;
private HttpListener listener; // Add a listener to get the callback functionality
Requests (String token, Context context, HttpListener listener) {
this.token = token;
this.context = context;
this.listener = listener; // initialize the listener here
}
private void set_response_of_server(String response) {
this.response_of_server = response;
listener.onResponseReceived(response); // Send the response back to the calling class
}
String get_response() {
return response_of_server;
}
void get_metadata_of_user() {
try {
RequestQueue queue = Volley.newRequestQueue(this.context);
Response.ErrorListener error_listener = new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
};
Response.Listener<String> response_listener = new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
set_response_of_server(response);
}
};
StringRequest getRequest = new StringRequest(Request.Method.GET, url+"?fields=user", response_listener, error_listener) {
#Override
public Map<String, String> getHeaders() {
Map<String, String> params = new HashMap<>();
params.put("Host", "cloud-api.yandex.net");
params.put("Authorization", token);
return params;
}
};
queue.add(getRequest);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Now the HttpListener class might look like the following. Create HttpListener.java and add the following code to create this as an interface.
public interface HttpListener {
public void onResponseReceived();
}
Hence you need to implement this interface in your MainActivity like the following.
public class MainActivity extends AppCompatActivity implements HttpListener {
private final String ID_OF_APP = "Your token of app";
// I fixed this part too. Please change if that is not useful
private final String URL_FOR_CODE_QUERY = "https://oauth.yandex.com/authorize?response_type=" + SAVED_TOKEN + "&client_id=" + ID_OF_APP;
private String SAVED_TOKEN = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// ... I omitted some code
Button btn_sign_in = findViewById(R.id.btn_sign_in);
btn_sign_in.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EditText code_field = findViewById(R.id.code_field);
String token = code_field.getText().toString();
save_token(token);
try {
// if(check_token()) {
// The check_token function call is Async. This will not return immediately. Hence you might consider removing this if part. Simply just call the function and listen to the callback function when the response is received
// }
check_token(); // Simply call the function here
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
private void save_token(String token) {
SharedPreferences sPref = getPreferences(MODE_PRIVATE);
SharedPreferences.Editor ed = sPref.edit();
ed.putString(SAVED_TOKEN, token);
ed.apply();
}
private String load_token() {
SharedPreferences sPref = getPreferences(MODE_PRIVATE);
return sPref.getString(SAVED_TOKEN, "");
}
// I changed the return type as this is not returning anything.
private void check_token() throws InterruptedException {
String token = load_token();
String result;
Requests request = new Requests(token, this);
request.get_metadata_of_user();
// You will not get the response immediately here. So omit these codes.
// result = request.get_response();
// Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
// return !(result.equals("-1"));
}
#Override
public void onResponseReceived(String response) {
// Here is your response. Now you can use your response
// and can perform the next action here.
}
}
Please note that, the code is not tested. Please modify as per your requirement. I hope that helps you to understand the problem.
This question already has answers here:
NullPointerException addToRequestQueue(com.android.volley.Request, java.lang.String)' on a null object reference
(8 answers)
Closed 4 years ago.
This is a barcode scanning app. It crashes when I scanned the code. If anyone knows how to fix help me out.
It crashes after I scanned the code from the ScanActivity.java and pass the object to the TicketResultActivity.javato display the result.
error
java.lang.RuntimeException: Unable to start activity ComponentInfo{info.androidhive.movietickets/info.androidhive.movietickets.TicketResultActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void info.androidhive.movietickets.MyApplication.addToRequestQueue(com.android.volley.Request)' on a null object reference
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
// making toolbar transparent
transparentToolbar();
setContentView(R.layout.activity_main);
findViewById(R.id.btn_scan).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(MainActivity.this, ScanActivity.class));
}
});
}
private void transparentToolbar() {
if (Build.VERSION.SDK_INT >= 19 && Build.VERSION.SDK_INT < 21) {
setWindowFlag(this, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, true);
}
if (Build.VERSION.SDK_INT >= 19) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
if (Build.VERSION.SDK_INT >= 21) {
setWindowFlag(this, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, false);
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
}
private void setWindowFlag(Activity activity, final int bits, boolean on) {
Window win = activity.getWindow();
WindowManager.LayoutParams winParams = win.getAttributes();
if (on) {
winParams.flags |= bits;
} else {
winParams.flags &= ~bits;
}
win.setAttributes(winParams);
}
}
ScanActivity.java
public class ScanActivity extends AppCompatActivity implements BarcodeReader.BarcodeReaderListener{
BarcodeReader barcodeReader;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scan);
// get the barcode reader instance
barcodeReader = (BarcodeReader) getSupportFragmentManager().findFragmentById(R.id.barcode_scanner);
}
#Override
public void onScanned(Barcode barcode) {
// playing barcode reader beep sound
barcodeReader.playBeep();
// ticket details activity by passing barcode
Intent intent = new Intent(ScanActivity.this, TicketResultActivity.class);
intent.putExtra("code", barcode.displayValue);
startActivity(intent);
}
#Override
public void onScannedMultiple(List<Barcode> list) {
}
#Override
public void onBitmapScanned(SparseArray<Barcode> sparseArray) {
}
/*#Override
public void onCameraPermissionDenied() {
finish();
}*/
#Override
public void onScanError(String s) {
Toast.makeText(getApplicationContext(), "Error occurred while scanning " + s, Toast.LENGTH_SHORT).show();
}
}
TicketResultActivity.java
public class TicketResultActivity extends AppCompatActivity {
private static final String TAG = TicketResultActivity.class.getSimpleName();
// url to search barcode
private static final String URL = "https://api.androidhive.info/barcodes/search.php?code=";
private TextView txtName, txtDuration, txtDirector, txtGenre, txtRating, txtPrice, txtError;
private ImageView imgPoster;
private Button btnBuy;
private ProgressBar progressBar;
private TicketView ticketView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ticket_result);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
txtName = findViewById(R.id.name);
txtDirector = findViewById(R.id.director);
txtDuration = findViewById(R.id.duration);
txtPrice = findViewById(R.id.price);
txtRating = findViewById(R.id.rating);
imgPoster = findViewById(R.id.poster);
txtGenre = findViewById(R.id.genre);
btnBuy = findViewById(R.id.btn_buy);
imgPoster = findViewById(R.id.poster);
txtError = findViewById(R.id.txt_error);
ticketView = findViewById(R.id.layout_ticket);
progressBar = findViewById(R.id.progressBar);
String barcode = getIntent().getStringExtra("code");
// close the activity in case of empty barcode
if (TextUtils.isEmpty(barcode)) {
Toast.makeText(getApplicationContext(), "Barcode is empty!", Toast.LENGTH_LONG).show();
finish();
}
// search the barcode
searchBarcode(barcode);
}
/**
* Searches the barcode by making HTTP call
* Request was made using Volley network library but the library is
* not suggested in production, consider using Retrofit
*/
private void searchBarcode(String barcode) {
// making volley's json request
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET,
URL + barcode, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.e(TAG, "Ticket response: " + response.toString());
// check for success status
if (!response.has("error")) {
// received movie response
renderMovie(response);
} else {
// no movie found
showNoTicket();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Error: " + error.getMessage());
showNoTicket();
}
});
MyApplication.getInstance().addToRequestQueue(jsonObjReq);
}
private void showNoTicket() {
txtError.setVisibility(View.VISIBLE);
ticketView.setVisibility(View.GONE);
progressBar.setVisibility(View.GONE);
}
/**
* Rendering movie details on the ticket
*/
private void renderMovie(JSONObject response) {
try {
// converting json to movie object
Movie movie = new Gson().fromJson(response.toString(), Movie.class);
if (movie != null) {
txtName.setText(movie.getName());
txtDirector.setText(movie.getDirector());
txtDuration.setText(movie.getDuration());
txtGenre.setText(movie.getGenre());
txtRating.setText("" + movie.getRating());
txtPrice.setText(movie.getPrice());
Glide.with(this).load(movie.getPoster()).into(imgPoster);
if (movie.isReleased()) {
btnBuy.setText(getString(R.string.btn_buy_now));
btnBuy.setTextColor(ContextCompat.getColor(this, R.color.colorPrimary));
} else {
btnBuy.setText(getString(R.string.btn_coming_soon));
btnBuy.setTextColor(ContextCompat.getColor(this, R.color.btn_disabled));
}
ticketView.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
} else {
// movie not found
showNoTicket();
}
} catch (JsonSyntaxException e) {
Log.e(TAG, "JSON Exception: " + e.getMessage());
showNoTicket();
Toast.makeText(getApplicationContext(), "Error occurred. Check your LogCat for full report", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
// exception
showNoTicket();
Toast.makeText(getApplicationContext(), "Error occurred. Check your LogCat for full report", Toast.LENGTH_SHORT).show();
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
}
return super.onOptionsItemSelected(item);
}
private class Movie {
String name;
String director;
String poster;
String duration;
String genre;
String price;
float rating;
#SerializedName("released")
boolean isReleased;
public String getName() {
return name;
}
public String getDirector() {
return director;
}
public String getPoster() {
return poster;
}
public String getDuration() {
return duration;
}
public String getGenre() {
return genre;
}
public String getPrice() {
return price;
}
public float getRating() {
return rating;
}
public boolean isReleased() {
return isReleased;
}
}
}
MyApplication.java
public class MyApplication extends Application {
public static final String TAG = MyApplication.class
.getSimpleName();
private RequestQueue mRequestQueue;
private static MyApplication mInstance;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized MyApplication getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
// set the default tag if tag is empty
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
To initialize MyApplication properly you have to add the following in the AndroidManifest.xml
<application android:name="com.package.subpackage.MyApplication">
...
</application>
How can I call the method "loginprep" of the LoginActivityClass from the FingerPrintClass?
See in the code...I wrote in where I want to call the loginprep with: "//Here I need the method loginprep() from the LoginActivity class"
FingerprintHandler.java
public class FingerprintHandler extends FingerprintManager.AuthenticationCallback {
private Context context;
// Constructor
public FingerprintHandler(Context mContext) {
context = mContext;
}
public void startAuth(FingerprintManager manager, FingerprintManager.CryptoObject cryptoObject) {
CancellationSignal cancellationSignal = new CancellationSignal();
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
return;
}
manager.authenticate(cryptoObject, cancellationSignal, 0, this, null);
}
#Override
public void onAuthenticationError(int errMsgId, CharSequence errString) {
Toast.makeText((Activity)context, "Fingerprint Authentication error.", Toast.LENGTH_LONG).show();
}
#Override
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
Toast.makeText((Activity)context, "Fingerprint Authentication help.", Toast.LENGTH_LONG).show();
}
#Override
public void onAuthenticationFailed() {
Toast.makeText((Activity)context, "Fingerprint Authentication failed.", Toast.LENGTH_LONG).show();
}
#Override
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
//Here I need the method loginprep() from the LoginActivity class
}
}
LoginActivity.java
public class LoginActivity extends AppCompatActivity {
public void loginprep() {
SharedPreferences sharedPreferencesF = getSharedPreferences("loginDatasFinger", Context.MODE_PRIVATE);
String urn = sharedPreferencesF.getString("username", "");
String pwd = sharedPreferencesF.getString("password", "");
loginUser(urn, pwd);
}
private void launchHomeScreen() {
Intent homeActivity = new Intent (LoginActivity.this,HomeActivity.class);
LoginActivity.this.startActivity(homeActivity);
finish();
}
public void loginUser(final String urn, final String pwd){
pd = ProgressDialog.show(LoginActivity.this, "", "Loading...");
StringRequest stringRequest = new StringRequest(Request.Method.POST, LOGIN_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonResponse = new JSONObject(response);
System.out.println("JSON RESPONSE: " + jsonResponse.toString());
boolean success = jsonResponse.getBoolean("success");
if (success) {
launchHomeScreen();
pd.dismiss();
Toast.makeText(LoginActivity.this,"Welcome back " + urn,Toast.LENGTH_LONG).show();
SharedPreferences sharedPref = getSharedPreferences("loginDatas", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("username", urn);
editor.putString("password", pwd);
editor.apply();
}
else {
loginButton.setBackgroundColor(0x73000000);
Toast.makeText(LoginActivity.this,"Wrong Username or Password!",Toast.LENGTH_LONG).show();
pd.dismiss();
}
}
catch (JSONException e) {
loginButton.setBackgroundColor(0x73000000);
e.printStackTrace();
pd.dismiss();
Toast.makeText(LoginActivity.this,response,Toast.LENGTH_LONG).show();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
loginButton.setBackgroundColor(0x73000000);
pd.dismiss();
System.out.println("Error: " + error);
}
}){
#Override
protected Map<String,String> getParams(){
Map<String,String> params = new HashMap<>();
params.put(KEY_USERNAME,urn);
params.put(KEY_PASSWORD,pwd);
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
}
Following:
MainActivity mActivity = new MainActivity();
this is not the way Android is expecting you to create new instances of an activity, normally you wait the onCreate callback as described in the activity lifeCycle...
no following that approach you will need another way to communicate 2 different activities, what way must be taken depends on the specific arch of your application... the most commonly implemented could be using self defined interfaces and implement you custom callbacks...
You're writing a FingerPrint callback class, which means there is some onAuthenticationSucceeded method that is called when the "authentication succeeds."
How about you implement your own callback to pass back into the LoginActivity?
In other words, you'd
1) Write an interface
public interface LoginListener {
void onLoginSuccess();
void onLoginFailed();
}
2) Have the Activity implements LoginListener and have the Activity method of onLogin do your non-static stuff with the SharedPreferences,
public class LoginActivity extends AppCompatActivity
implements LoginListener {
public static final String KEY_USERNAME = "username";
public static final String KEY_PASS = "password";
private FingerprintHandler fingerprintHandler;
#Override
public void onLoginFailed() { }
#Override
public void onLoginSuccess() {
SharedPreferences sharedPrefs = getSharedPreferences("loginDatasFinger", Context.MODE_PRIVATE);
String urn = sharedPrefs.getString(KEY_USERNAME, "");
String pwd = sharedPrefs.getString(KEY_PASS, "");
loginUser(urn, pwd);
}
#Override
public void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.activity_login);
fingerprintHandler = new FingerprintHandler(this);
}
// public void loginUser(final String urn, final String pwd){ }
}
3) Expect to pass in a LoginListener as a parameter to that separate class.
public class FingerprintHandler extends FingerprintManager.AuthenticationCallback {
private final Context mContext;
private LoginListener mListener;
// Constructor
public FingerprintHandler(Context context) {
mContext = context;
if (context instanceof LoginListener) {
this.mListener = (LoginListener) context;
} else {
throw new ClassCastException("FingerprintHandler: context must implement LoginListener!");
}
}
4) And you do then can use your callback from the other callback.
#Override
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
if (mListener != null) {
mListener.onLoginSuccess();
}
}
I am trying to develop my own Android application using Android Studio 0.4.2 and the Twitter4J library. My idea is to use a WebView to load there the Twitter authentication page and get the AccessToken from there. I can get the oauth_token and oauth_verifier, but after that all the Twitter methods to get followers, post twits, whatever are not working.
This is my code:
public class TwitterLoginFragment extends Fragment {
private static String TWITTER_CONSUMER_KEY = "***";
private static String TWITTER_CONSUMER_SECRET = "***";
private static final String TWITTER_CALLBACK_URL = "http://www.hita.pro";
private static SharedPreferences sharedPreferences;
private Button btnTwitterLogin;
private Button btnTwitterLogOut;
private WebView wvTwitterLogin;
private IDs iDs;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
sharedPreferences = getActivity().getSharedPreferences("CONNECTION_INFO", Context.MODE_PRIVATE);
TwitterFactory.getSingleton().setOAuthConsumer(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET);
return inflater.inflate(R.layout.fragment_twitter_login, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstance) {
super.onActivityCreated(savedInstance);
wvTwitterLogin = (WebView) getView().findViewById(R.id.wvTwitterLogin);
wvTwitterLogin.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean("KEY_TWITTER_LOGIN", true);
editor.putString("OAUTH_TOKEN", url.substring(url.indexOf("oauth_token=") + 12, url.indexOf("&")));
editor.putString("OAUTH_VERIFIER", url.substring(url.indexOf("oauth_verifier=") + 15));
editor.commit();
TwitterFactory.getSingleton().setOAuthAccessToken(new AccessToken(sharedPreferences.getString("OAUTH_TOKEN", ""), sharedPreferences.getString("OAUTH_VERIFIER", "")));
new GetTwitterFollowers().execute();
return true;
}
});
btnTwitterLogin = (Button) getView().findViewById(R.id.btnTwitterLogin);
btnTwitterLogin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
loginToTwitter();
}
});
btnTwitterLogOut = (Button) getView().findViewById(R.id.btnTwitterLogOut);
btnTwitterLogOut.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
twitterLogOut();
}
});
}
public void loginToTwitter() {
if (!isTwitterLoggedInAlready()) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
wvTwitterLogin.loadUrl(TwitterFactory.getSingleton().getOAuthRequestToken(TWITTER_CALLBACK_URL).getAuthenticationURL());
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
goToTwitterLogin();
}
});
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getActivity(), getString(R.string.error_already_logged_twitter), Toast.LENGTH_LONG).show();
}
}
});
thread.start();
} else
Toast.makeText(getActivity(), getString(R.string.error_already_logged_twitter), Toast.LENGTH_LONG).show();
}
private void goToTwitterLogin() {
btnTwitterLogin.setVisibility(View.GONE);
btnTwitterLogOut.setVisibility(View.GONE);
wvTwitterLogin.setVisibility(View.VISIBLE);
}
private boolean isTwitterLoggedInAlready() {
return sharedPreferences.getBoolean("KEY_TWITTER_LOGIN", false);
}
private void twitterLogOut() {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean("KEY_TWITTER_LOGIN", false);
editor.commit();
}
private class GetTwitterFollowers extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... v) {
try {
iDs = TwitterFactory.getSingleton().getFollowersIDs(-1);
} catch (TwitterException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
iDs.getIDs();
}
}
}
When I call to TwitterFactory.getSingleton().getFollowersIDs(-1) after the user has singed in, I'm getting this exception:
java.io.IOException: No authentication challenges found
I'm desperated, I have spent one week trying to solve this problem but all the threads I have found in StackOverflow and other sites are not working. The system clock is OK, I have tried with ConfigurationBuilder and other solutions, but no luck. Can somebody help me?
Thanks a lot!
Have you tried to work with instance not singleton from TwitterFactory?
Uri uri = Uri.parse(url);
String token = uri.getQueryParameter("OAUTH_TOKEN");
String verifier = uri.getQueryParameter("OAUTH_VERIFIER");
Twitter twitter = TwitterFactory.getInstance(
new AccessToken(token,verifier);
twitter.getFollowers(-1);