I'm trying to follow the Nest SDK on github and the sample code. My fragment code is as follows -
/**
* A placeholder fragment containing a simple view.
*/
public class ThermoActivityFragment extends Fragment implements View.OnClickListener {
private static final String TAG = ThermoActivity.class.getSimpleName(); // for log
// Nest API instance holder
private NestAPI tNest;
private NestToken tToken;
private Thermostat tThermo;
private Structure tStruct;
// Save the ID's and secret
private static final String CLIENT_ID = Constants.CLIENT_ID;
private static final String CLIENT_SECRET = Constants.CLIENT_SECRET;
private static final String REDIRECT_URL = Constants.REDIRECT_URL;
private static final int AUTH_TOKEN_REQUEST_CODE = 111;
private static final int RESULT_OK = -1;
private static final String THERMOSTAT_KEY = "thermostat_key";
private static final String STRUCTURE_KEY = "structure_key";
private static final String DEG_F = "%d°F";
// Text View
private TextView tTempIncr;
private TextView tTempDecr;
private TextView tSetTemp;
public ThermoActivityFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_thermo, container, false);
tTempIncr = (TextView) view.findViewById(R.id.temp_incr);
tTempDecr = (TextView) view.findViewById(R.id.temp_decr);
tSetTemp = (TextView) view.findViewById(R.id.temp_value);
view.findViewById(R.id.temp_incr).setOnClickListener(this);
view.findViewById(R.id.temp_decr).setOnClickListener(this);
NestAPI.setAndroidContext(getContext());
tNest = NestAPI.getInstance();
tNest.setConfig(CLIENT_ID, CLIENT_SECRET, REDIRECT_URL);
// Auth flow
tToken = ThermoSettings.loadAuthToken(getContext());
if (tToken != null) {
authenticate(tToken);
} else {
tNest.launchAuthFlow(getActivity(), AUTH_TOKEN_REQUEST_CODE);
}
if (savedInstanceState != null) {
tThermo = savedInstanceState.getParcelable(THERMOSTAT_KEY);
tStruct = savedInstanceState.getParcelable(STRUCTURE_KEY);
//updateViews();
}
return view;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(THERMOSTAT_KEY, tThermo);
outState.putParcelable(STRUCTURE_KEY, tStruct);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (resultCode != RESULT_OK || requestCode != AUTH_TOKEN_REQUEST_CODE) {
Log.e(TAG, "Finished with no result.");
return;
}
tToken = NestAPI.getAccessTokenFromIntent(intent);
if (tToken != null) {
ThermoSettings.saveAuthToken(getContext(), tToken);
authenticate(tToken);
} else {
Log.e(TAG, "Unable to resolve access token from payload.");
}
}
#Override
public void onStop() {
Log.d(TAG, "onStop");
super.onStop();
tNest.removeAllListeners();
}
#Override
public void onClick(View v) {
if (tThermo == null || tStruct == null)
return;
String tThermoId = tThermo.getDeviceId();
long temp = tThermo.getTargetTemperatureF();
switch (v.getId()) {
case R.id.temp_incr:
System.out.println("Temp Incr");
++temp;
tSetTemp.setText(String.format(DEG_F, temp));
tNest.thermostats.setTargetTemperatureF(tThermoId, temp);
break;
case R.id.temp_decr:
--temp;
tSetTemp.setText(String.format(DEG_F, temp));
tNest.thermostats.setTargetTemperatureF(tThermoId, temp);
break;
}
}
/**
* Authenticate with the Nest API and start listening for updates.
*
* #param token the token used to authenticate.
*/
private void authenticate(NestToken token) {
//NestAPI nest = NestAPI.getInstance();
tNest.authWithToken(token, new NestListener.AuthListener() {
#Override
public void onAuthSuccess() {
Log.v(TAG, "Authentication succeeded.");
fetchData();
}
#Override
public void onAuthFailure(NestException exception) {
Log.e(TAG, "Authentication failed with error: " + exception.getMessage());
ThermoSettings.saveAuthToken(getActivity(), null);
tNest.launchAuthFlow(getActivity(), AUTH_TOKEN_REQUEST_CODE);
}
#Override
public void onAuthRevoked() {
Log.e(TAG, "Auth token was revoked!");
ThermoSettings.saveAuthToken(getActivity(), null);
tNest.launchAuthFlow(getActivity(), AUTH_TOKEN_REQUEST_CODE);
}
});
}
/**
* Setup global listener, start listening, and update view when update received.
*/
private void fetchData() {
tNest.addGlobalListener(new NestListener.GlobalListener() {
#Override
public void onUpdate(#NonNull GlobalUpdate update) {
tThermo = update.getThermostats().get(0);
//System.out.println(tThermo);
tStruct = update.getStructures().get(0);
//updateViews();
}
});
}
}
The Settings file where I save the token is as follows -
public class ThermoSettings {
private static final String TOKEN_KEY = "token";
private static final String EXPIRATION_KEY = "expiration";
public static void saveAuthToken(Context context, NestToken token) {
if (token == null) {
getPrefs(context).edit().remove(TOKEN_KEY).remove(EXPIRATION_KEY).commit();
return;
}
getPrefs(context).edit()
.putString(TOKEN_KEY, token.getToken())
.putLong(EXPIRATION_KEY, token.getExpiresIn())
.commit();
}
public static NestToken loadAuthToken(Context context) {
final SharedPreferences prefs = getPrefs(context);
final String token = prefs.getString(TOKEN_KEY, null);
final long expirationDate = prefs.getLong(EXPIRATION_KEY, -1);
if (token == null || expirationDate == -1) {
return null;
}
return new NestToken(token, expirationDate);
}
private static SharedPreferences getPrefs(Context context) {
return context.getSharedPreferences(NestToken.class.getSimpleName(), 0);
}
}
What I'm trying to do -
I'm using a button on the homepage to enter the Activity. When I press the button, I see the Nest Authorization webpage, When I click on Accept, I see my UI but don't see the 'Authentication Succeeded' message in the log.
Can someone tell me what I'm doing wrong?
I finally got it to work. Earlier I was trying to make it work from a fragment. After I deleted the fragment and moved the code to MainActivity, it started to work.
Related
I am currently attempting to have a custom dialog on a fragment to bring text back to the fragment. I have the dialog setup but when I click on the button to bring up the dialog I get this error.
java.lang.ClassCastException: com.example.android.app.MainActivity#4c01a76must implement StatusDialogListener
I then found this stack post talking about the issue
From reading the error and the stack post it seems that the issue is that I have to implement the dialog class onto the activity that is connected to the fragment.
So I implemented the listener into my main activity
public class MainActivity extends AppCompatActivity implements ... Status_Dialog.StatusDialogListner
After implementing it, I got the error below:
Class 'MainActivity' must either be declared abstract or implement abstract method 'applyText(String)' in 'StatusDialogListner
Which I fixed by adding the code below to the Activity:
#Override
public void applyText(String status) {
}
This allows the app to run and display the dialog with no errors.
The issue is now my adapter will not get the text from the dialog so I believe it is to do with the fact that I also have an applyText in my fragment and main activity when I ran the debugger applytext in the fragment was never called. I am lost at this point
Code
Dialog
public class Status_Dialog extends AppCompatDialogFragment {
private EditText editTextStatus;
private StatusDialogListner listner;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.layout_status_dialog, null);
editTextStatus = view.findViewById(R.id.new_status);
builder.setView(view)
.setTitle("Change Status")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
})
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
String status = editTextStatus.getText().toString();
listner.applyText(status);
}
});
return builder.create();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
listner = (StatusDialogListner) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + "must implement StatusDialogListener");
}
}
public interface StatusDialogListner {
void applyText(String status);
}
}
Fragment
public class profile_fragment extends Fragment implements Status_Dialog.StatusDialogListner {
private static final int GALLERY_PICK = 1;
private DatabaseReference mUserDatabase;
//Android Layout
private FirebaseUser mCurrentUser;
private CircleImageView mDisplayImage;
private TextView mName;
private TextView mStatus;
private Button mStatusBtn;
private Button mImageBtn;
private ProgressDialog mProgressDialog;
private StorageReference mImageStorage;
private FirebaseFirestore db = FirebaseFirestore.getInstance();
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListner;
private static final String KEY_NAME = "name";
private static final String KEY_STATUS = "status";
private static final String KEY_IMAGE = "image";
private static final String TAG = "user_profile";
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_profile_fragment, container, false);
mDisplayImage = view.findViewById(R.id.profile_picture);
mName = view.findViewById(R.id.profile_user_name);
mStatus = view.findViewById(R.id.profile_user_status);
mStatusBtn = view.findViewById(R.id.profile_change_status_btn);
mImageBtn = view.findViewById(R.id.profile_change_image_btn);
mImageStorage = FirebaseStorage.getInstance().getReference();
mCurrentUser = FirebaseAuth.getInstance().getCurrentUser();
final String current_uid = mCurrentUser.getUid();
DocumentReference mUsersDB = db.collection("Users").document(current_uid);
// FirebaseUser currentFirebaseUser = FirebaseAuth.getInstance().getCurrentUser() ;
// Toast.makeText(this, "ttt" + currentFirebaseUser.getUid(), Toast.LENGTH_SHORT).show();
mStatusBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
openDialog();
/*
String status_value = mStatus.getText().toString();
Intent status_intent = new Intent(getActivity(), change_status.class);
status_intent.putExtra("status_value", status_value);
startActivity(status_intent);
*/
}
});
mImageBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent galleryIntent = new Intent();
galleryIntent.setType("image/*");
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(galleryIntent, "Select Image"), GALLERY_PICK);
/*
CropImage.activity()
.setGuidelines(CropImageView.Guidelines.ON)
.start(SettingsActivity.this);
*/
}
});
mUsersDB.get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists()) {
String name = documentSnapshot.getString(KEY_NAME);
mName.setText(name);
String status = documentSnapshot.getString(KEY_STATUS);
mStatus.setText(status);
FirebaseUser currentFirebaseUser = FirebaseAuth.getInstance().getCurrentUser();
} else {
}
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
}
});
return view;
}
public void openDialog(){
Status_Dialog status_dialog = new Status_Dialog();
status_dialog.show(getActivity().getSupportFragmentManager(), "TEST?");
}
#Override
public void applyText(String status) {
mStatus.setText(status);
}
...
Problem is here:
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
listner = (StatusDialogListner) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + "must implement StatusDialogListener");
}
}
Note that listner is set during the onAttach and it is receiving the instance of Context. In other words, it is receiving the instance of the host activity (That's why you had to implement the interface in the MainActivity)
I think you can update your code as follows:
1) Remove this from the dialog. This way, your activity no longer must implement StatusDialogListener
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
listner = (StatusDialogListner) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + "must implement StatusDialogListener");
}
}
2) Update this on Dialog:
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
if(listner != null) { // ADD THIS NULL CHECK SINCE LISTNER MAY BE NULL
String status = editTextStatus.getText().toString();
listner.applyText(status);
}
}
});
3) Add this to the dialog:
public void setListener(StatusDialogListner newListener) {
this.listner = newListener;
}
4) Update this on the fragment:
public void openDialog(){
Status_Dialog status_dialog = new Status_Dialog();
status_dialog.setListener(this); // ADD THIS NEW LINE
status_dialog.show(getActivity().getSupportFragmentManager(), "TEST?");
}
5) Remove below code from MainActivity
// Remove the implementation of Status_Dialog.StatusDialogListner from MainActivity
// And remove the method below:
#Override
public void applyText(String status) {
}
I'm developing an app and in first activity it has card view layout. I'm retrieving data from a webservice and relevant data are showed in card view. It's working well. Now when a user clicks a particular card view I need to go for another activity. I'm getting relevant ID for that card view and passing it to the second activity. In second activity I need to show the content according to that unique Id. But I'm not getting any thing. This is what I tried.
Pojo class
public class PromoDetails {
String PromoId;
String PromoName;
String PromoImg;
String promoDetails;
String promoValidty;
public PromoDetails(String PromoId, String PromoName, String PromoImg , String promoDetails , String promoValidity) {
this.PromoId = PromoId;
this.PromoName = PromoName;
this.PromoImg = PromoImg;
this.promoDetails = promoDetails;
this.promoValidty = promoValidity;
}
public String getPromoId() {
return PromoId;
}
public void setPromoId(String promoId) {
PromoId = promoId;
}
public String getPromoName() {
return PromoName;
}
public void setPromoName(String promoName) {
PromoName = promoName;
}
public String getPromoImg() {
return PromoImg;
}
public void setPromoImg(String promoImg) {
PromoImg = promoImg;
}
public String getPromoDetails() {
return promoDetails;
}
public void setPromoDetails(String promoDetails) {
this.promoDetails = promoDetails;
}
public String getPromoValidty() {
return promoValidty;
}
public void setPromoValidty(String promoValidty) {
this.promoValidty = promoValidty;
}}
ApiInterface
public interface ApiInterface {
#POST("ap/promotions.php")
Call<List<Promotions>> getPromotions();
#GET("test.php/promotions/{PromoId}")
Call<List<PromoDetails>> getPromotDetails(#Path("PromoId") String PromoId) ;}
New Activity class
public class PromotionsInside extends Activity {
private ApiInterface apiInterface;
private List<PromoDetails> promoDetails;
TextView prDescription;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.promo_inside);
Bundle extras = getIntent().getExtras();
String promoId = "";
if (extras != null) {
promoId = extras.getString("PROMO_ID");
getPromotionUpdate(promoId);
}
}
private void getPromotionUpdate(String myPromoId) {
apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
Call<List<PromoDetails>> call = apiInterface.getPromotDetails(myPromoId);
call.enqueue(new Callback<List<PromoDetails>>() {
#Override
public void onResponse(Call<List<PromoDetails>> call, Response<List<PromoDetails>> response) {
promoDetails = response.body();
runOnUiThread(new Runnable() {
#Override
public void run() {
prDescription = (TextView)findViewById(R.id.promoDescriptionsss) ;
prDescription.setText(promoDetails.get(0).getPromoName());
}
});
}
#Override
public void onFailure(Call<List<PromoDetails>> call, Throwable t) {
}
});
}}
I have similar case. Try to use this to start second activity:
Intent intent = new Intent(this, PromotionsInside.class);
//Make sure that you put String id in intent
intent.putExtra("PROMO_ID", id);
startActivity(intent);
And this in second activity:
if (getIntent().hasExtra("PROMO_ID")) {
String id = getIntent().getStringExtra("PROMO_ID", null);
//next steps that you need
}
Hope it will help you
I am implementing an android fingerprint authentication. I want to know which user, who has registered in device before, is authenticating. Is there any information about the user, who has registered and is valid for the device, in the FingerprintManager.AuthenticationResult argument in onAuthenticationSucceeded method?!
I am using this sample.
this is my class, which is implementing FingerprintManager.AuthenticationCallback:
public class FingerprintUiHelper extends FingerprintManager.AuthenticationCallback {
private static final long ERROR_TIMEOUT_MILLIS = 1600;
private static final long SUCCESS_DELAY_MILLIS = 1300;
private final FingerprintManager mFingerprintManager;
private final ImageView mIcon;
private final TextView mErrorTextView;
private final Callback mCallback;
private CancellationSignal mCancellationSignal;
private boolean mSelfCancelled;
/**
* Constructor for {#link FingerprintUiHelper}.
*/
FingerprintUiHelper(FingerprintManager fingerprintManager,
ImageView icon, TextView errorTextView, Callback callback) {
mFingerprintManager = fingerprintManager;
mIcon = icon;
mErrorTextView = errorTextView;
mCallback = callback;
}
public boolean isFingerprintAuthAvailable() {
// The line below prevents the false positive inspection from Android Studio
// noinspection ResourceType
return mFingerprintManager.isHardwareDetected()
&& mFingerprintManager.hasEnrolledFingerprints();
}
public void startListening(FingerprintManager.CryptoObject cryptoObject) {
if (!isFingerprintAuthAvailable()) {
return;
}
mCancellationSignal = new CancellationSignal();
mSelfCancelled = false;
// The line below prevents the false positive inspection from Android Studio
// noinspection ResourceType
mFingerprintManager
.authenticate(cryptoObject, mCancellationSignal, 0 /* flags */, this, null);
mIcon.setImageResource(R.drawable.ic_fp_40px);
}
public void stopListening() {
if (mCancellationSignal != null) {
mSelfCancelled = true;
mCancellationSignal.cancel();
mCancellationSignal = null;
}
}
#Override
public void onAuthenticationError(int errMsgId, CharSequence errString) {
if (!mSelfCancelled) {
showError(errString);
mIcon.postDelayed(new Runnable() {
#Override
public void run() {
mCallback.onError();
}
}, ERROR_TIMEOUT_MILLIS);
}
}
#Override
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
showError(helpString);
}
#Override
public void onAuthenticationFailed() {
showError(mIcon.getResources().getString(
R.string.fingerprint_not_recognized));
}
#Override
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
mIcon.setImageResource(R.drawable.ic_fingerprint_success);
mErrorTextView.setTextColor(
mErrorTextView.getResources().getColor(R.color.success_color, null));
mErrorTextView.setText(
mErrorTextView.getResources().getString(R.string.fingerprint_success));
mIcon.postDelayed(new Runnable() {
#Override
public void run() {
mCallback.onAuthenticated();
}
}, SUCCESS_DELAY_MILLIS);
}
private void showError(CharSequence error) {
mIcon.setImageResource(R.drawable.ic_fingerprint_error);
mErrorTextView.setText(error);
mErrorTextView.setTextColor(
mErrorTextView.getResources().getColor(R.color.warning_color, null));
mErrorTextView.removeCallbacks(mResetErrorTextRunnable);
mErrorTextView.postDelayed(mResetErrorTextRunnable, ERROR_TIMEOUT_MILLIS);
}
private Runnable mResetErrorTextRunnable = new Runnable() {
#Override
public void run() {
mErrorTextView.setTextColor(
mErrorTextView.getResources().getColor(R.color.hint_color, null));
mErrorTextView.setText(
mErrorTextView.getResources().getString(R.string.fingerprint_hint));
mIcon.setImageResource(R.drawable.ic_fp_40px);
}
};
public interface Callback {
void onAuthenticated();
void onError();
}
}
Updated :
I have build a image cropping app its running fine, but now I want to save cropped image name as textbox value.
In short I am trying to set textbox value in object and get object value in java Class. I have tried several techniques, recently I am trying to get,set data by using interface technique and the image is saved as ".jpg"only.
I would love to know where am I going wronk?
Following is the code I have tried.
MainActivity
public class TestActivity extends AppCompatActivity implements CropHandler, View.OnClickListener {
public static final String TAG = "TestActivity";
ImageView mImageView;
EditText formnumber;
String formid;
CropParams mCropParams;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
mCropParams = new CropParams(this);
mImageView = (ImageView) findViewById(R.id.image);
formnumber =(EditText)findViewById(R.id.FormNumber);
findViewById(R.id.bt_crop_capture).setOnClickListener(this);
findViewById(R.id.bt_crop_gallery).setOnClickListener(this);
}
#Override
public void onClick(View v) {
mCropParams.refreshUri();
formid=formnumber.getText().toString();
// Intent i = new Intent(TestActivity.this, CropHelper.class);
// i.putExtra("Id",formid);
if(formid.matches(""))
{
Toast.makeText(getApplicationContext(),"Please Enter Application Id",Toast.LENGTH_SHORT).show();
}
else
{
switch (v.getId()) {
case R.id.bt_crop_capture: {
mCropParams.enable = true;
mCropParams.compress = false;
Intent intent = CropHelper.buildCameraIntent(mCropParams);
startActivityForResult(intent, CropHelper.REQUEST_CAMERA);
}
break;
case R.id.bt_crop_gallery: {
mCropParams.enable = true;
mCropParams.compress = false;
Intent intent = CropHelper.buildGalleryIntent(mCropParams);
startActivityForResult(intent, CropHelper.REQUEST_CROP);
}
break;
}
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
CropHelper.handleResult(this, requestCode, resultCode, data);
if (requestCode == 1) {
Log.e(TAG, "");
}
}
#Override
public void onTaskComplete(String response) {
onTaskComplete(this.formid);
}
}
CropHelper Class
public class CropHelper {
public static final String TAG = "CropHelper";
/**
* request code of Activities or Fragments
* You will have to change the values of the request codes below if they conflict with your own.
*/
public static final int REQUEST_CROP = 127;
public static final int REQUEST_CAMERA = 128;
public static final int REQUEST_PICK = 129;
public static String AppId;
public static final String CROP_CACHE_FOLDER = "PhotoCropper";
public static Uri generateUri() {
File cacheFolder = new File(Environment.getExternalStorageDirectory() + File.separator + CROP_CACHE_FOLDER);
if (!cacheFolder.exists()) {
try {
boolean result = cacheFolder.mkdir();
Log.d(TAG, "generateUri " + cacheFolder + " result: " + (result ? "succeeded" : "failed"));
} catch (Exception e) {
Log.e(TAG, "generateUri failed: " + cacheFolder, e);
}
}
// String name = String.format("image-%d.jpg", System.currentTimeMillis());
String name = String.format(AppId.toString()+".jpg",System.currentTimeMillis());
return Uri
.fromFile(cacheFolder)
.buildUpon()
.appendPath(name)
.build();
}
#Override
public void onTaskComplete(String response) {
AppId=response;
}
}
Interface
public interface CropHandler
{
void onPhotoCropped(Uri uri);
void onCompressed(Uri uri);
void onTaskComplete(String response);
void onCancel();
void onFailed(String message);
void handleIntent(Intent intent, int requestCode);
CropParams getCropParams();
}
Set formid to EditText value and get the return value in your CropHelper class.
public static String formid=null;
formid=formnumber.getText().toString();
Now create an object of your Activity in a class where you want to call formid value.
MainActivity my_objec= new MainActivity();
String id= my_objec.formid;
String name = String.format(""+id+".jpg",System.currentTimeMillis());
thats all you need to do.
Implement this with your class and get return back your value in interface
public interface onTaskComplete {
void onComplete(String response);
}
Normally what i do is create different class which holds/save all data and values which can used across differnt classes in app.
For example:
// your activity
private CropHelper cropHelper;
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CropHelper.REQUEST_CROP) {
cropHelper.onReceivedImageData(data.get...)
}
}
public interface DataCallBack {
public void OnReceivedImageData(Data data);
}
....
// your crop helper
public class CropHelper implements YourActivity.DataCallBack {
#Override
public void OnReceivedImageData(Data data) {
// doing anything with data
}
}
Best Approach for this is using interface try to do as :
Create Interface
public interface MyListener {
// you can define any parameter as per your requirement
public void callback(View view, String result);
}
public class MyActivity extends Activity implements MyListener {
#override
public void onCreate(){
MyButton m = new MyButton(this);
}
// method invoke when mybutton will click
#override
public void callback(View view, String result) {
// do your stuff here
}
}
public class MyButton {
MyListener ml;
// constructor
MyButton(MyListener ml) {
this.ml = ml;
}
public void MyLogicToIntimateOthere() {
ml.callback(this, "success");
}
}
for more Go to this link:
Using Interface
Pass data through arguments in constructor..,
For example.. Create Constructor in your class.
public class CropHelper {
private Context context;
private String msg;
public CropHelper(Context context, String msg) {
this.context = context;
this.msg = msg;
if (msg != null) {
showMsg(msg);
}
}
//Replace with your logic
void showMsg(String msg) {
//Perform your operation
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
}
}
And then simple call it from any Activity by Creating instance of that class..
Like..
new CropHelper(this, "Hello from Activity");
I don't have much experience with building well-designed object oriented systems, and this time I improvised, which lead to the system not working and not giving me any errors.
Basically in my android app, I have a user profile activity that calls a class that queries the remote database using the user ID, and returns values for user avatar and user name.
Until the class was nested inside the profile activity class it was alright, but I decided to move it out of there and change some other stuff and now when I go to My profile I do not see my avatar and I do not see my user name.
Here is the GetUserData class:
public class GetUserData extends Activity {
private String currentlyLoggedInUserString;
SharedPreferences sharedPrefs;
Editor editor;
int currentlyLoggedInUser;
private JSONParser jsonParser = new JSONParser();
private Configurationz configurationz = new Configurationz();
private ToastMaker toastMaker = new ToastMaker();
private static final String TAG_SUCCESS = "success";
private static final String TAG_USER_AVATAR = "user_avatar";
private static final String TAG_USER_NAME = "user_name";
private static final String TAG_USER_EMAIL = "user_email";
private static final String TAG_USER_SEX = "user_sex";
private static final String TAG_USER_DATE_REGISTERED = "user_date_registered";
private static final String TAG_USER_LAST_SEEN = "user_last_seen";
private static final String TAG_USER_PASSWORD = "user_password";
private static final String APP_SHARED_PREFS = "asdasd_preferences";
private String userName;
private String userEmail;
private String userSex;
private String userPassword;
private String userAvatar;
private String userDateRegistered;
private String userLastSeen;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserEmail() {
return userEmail;
}
public void setUserEmail(String userEmail) {
this.userEmail = userEmail;
}
public String getUserSex() {
return userSex;
}
public void setUserSex(String userSex) {
this.userSex = userSex;
}
public String getUserPassword() {
return userPassword;
}
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
public String getUserAvatar() {
return userAvatar;
}
public void setUserAvatar(String userAvatar) {
this.userAvatar = userAvatar;
}
public String getUserDateRegistered() {
return userDateRegistered;
}
public void setUserDateRegistered(String userDateRegistered) {
this.userDateRegistered = userDateRegistered;
}
public String getUserLastSeen() {
return userLastSeen;
}
public void setUserLastSeen(String userLastSeen) {
this.userLastSeen = userLastSeen;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sharedPrefs = getApplicationContext().getSharedPreferences(APP_SHARED_PREFS, Context.MODE_PRIVATE);
new GetUserDataGetter().execute();
}
public class GetUserDataGetter extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
int success;
try {
List<NameValuePair> parameters = new ArrayList<NameValuePair>();
// fix these shitty variables.
currentlyLoggedInUser = sharedPrefs.getInt("currentLoggedInUserId", 0);
currentlyLoggedInUserString = Integer.toString(currentlyLoggedInUser);
parameters.add(new BasicNameValuePair("user_id", currentlyLoggedInUserString));
final JSONObject json = jsonParser.makeHttpRequest(configurationz.URL_PHP_GET_USER_DATA, "POST", parameters);
success = json.getInt(TAG_SUCCESS);
if (success == 1) {
// user data found
setUserLastSeen(json.getString(TAG_USER_LAST_SEEN));
setUserDateRegistered(json.getString(TAG_USER_DATE_REGISTERED));
setUserAvatar(json.getString(TAG_USER_AVATAR));
setUserSex(json.getString(TAG_USER_SEX));
setUserPassword(json.getString(TAG_USER_PASSWORD));
setUserEmail(json.getString(TAG_USER_EMAIL));
setUserName(json.getString(TAG_USER_NAME));
//return json.getString(TAG_USER_AVATAR);
return null;
} else if (success == 2) {
//toast about not being able to connect to db;
runOnUiThread(new Runnable() {
public void run() {
//this might cause some SHIT!!!!!!!!!!!! TEST IT!!!
toastMaker.toast(getBaseContext(), configurationz.ERROR_MESSAGES_SIGNUP_DEVICE_UNABLE_TO_TAKE_PHOTOS, configurationz, Toast.LENGTH_LONG);
}
});
setUserLastSeen("");
setUserDateRegistered("");
setUserAvatar("");
setUserSex("");
setUserPassword("");
setUserEmail("");
setUserName("");
return null;
} else {
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
}
}
and here is the MyProfile class:
public class MyProfile extends ActionBarAndSlidingMenu {
private TableRow myProfileActionButtonsHolder;
private TextView tvUserName;
private ImageButton iUserAvatar;
private Bitmap iUserAvatarBitmap;
private String avatarPath;
private String userName;
private static final String APP_SHARED_PREFS = "asdasd_preferences";
SharedPreferences sharedPrefs;
Editor editor;
int currentlyLoggedInUser;
boolean userLoggedInState = false;
private GetUserData getUserData = new GetUserData();
public MyProfile() {
super(R.string.app_name);
}
// do a check here whether this is the user themselves or some other user
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sharedPrefs = getApplicationContext().getSharedPreferences(APP_SHARED_PREFS, Context.MODE_PRIVATE);
setContentView(R.layout.user_profile);
// check whether user is logged in, otherwise redirect them to
// login/signup page
userLoggedInState = sharedPrefs.getBoolean("userLoggedInState", false);
if (!userLoggedInState) {
// start intent to get them out of here.
// Research whether this step is necessary at all
}
// define the view components
myProfileActionButtonsHolder = (TableRow) findViewById(R.id.userProfileActionButtonsHolder);
// set avatar image
iUserAvatar = (ImageButton) findViewById(R.id.iUserAvatar);
avatarPath = getUserData.getUserAvatar();
if (avatarPath != "") {
iUserAvatarBitmap = BitmapFactory.decodeFile(avatarPath);
iUserAvatar.setImageBitmap(iUserAvatarBitmap);
} else {
iUserAvatar.setImageResource(R.drawable.avatar_default_male);
}
//set user display name
userName = getUserData.getUserName();
tvUserName = (TextView) findViewById(R.id.tvUserName);
tvUserName.setText(userName);
// create action buttons fragment with "edit" and "settings" buttons
getSupportFragmentManager().beginTransaction().replace(R.id.userProfileActionButtonsHolder, new MyProfileActionButtonsFragment()).commit();
}
}
First, you need to read up on programming in general and proper coding guidelines in particular, as this is a bit of a chaos. As soon as your project becomes more complex, this gets unreadable and undebuggable. Second, you should read up on how Android works.
Here's your problem in a nutshell:
An Activity is not just Android's own version of a class and you can't use it as such. An Activity represents a screen that is displayed to the user. No screen to display? No Activity.
Thus, your getUserData Activity should be a regular class and not extend activity.
Now, in MyProfile you just declare a member variable with
private GetUserData getUserData = new GetUserData();
This does nothing and it certainly never runs that class' onCreate. Thus, your task is never executed and all your fields return null.
Here's what to do in a nutshell:
Create a class UserDetails that has a constructor that takes the username, etc. plus the getters necessary to get these details. Add nothing else. This is what we call Java's version of a value object.
public class UserDetails {
private final String mUsername;
public UserDetails(String username) {
mUsername = username;
}
public String getUsername() {
return mUsername;
}
}
Create an interface called IOnUserDetailsReceivedListener with the method onUserDetailsReceived(UserDetails userDetails). The reason for this is that your download task will take some time. You need to get informed when it's done and that's what we use this interface for. This is called a listener pattern.
public interface IOnUserDetailsReceivedListener {
public void onUserDetailsReceived(UserDetails userDetails);
public void onUserDetailsError();
}
Create a class Downloader that contains your AsyncTask and that has a method retrieveUserDetails(); or something. In that method, run the async task to download. When you get the data from the server, fill it into a new UserDetails(...) object and then call listener.onUserDetailsReceived(userDetails).
public class UserDetailsDownloader {
private IOnUserDetailsReceivedListener mListener;
public UserDetailsDownloader(IOnUserDetailsReceivedListener listener) {
mListener = listener;
}
public void downloadUserDetails() {
//Execute the async task here. In it's onPostExecute, do mListener.onUserDetailsReceived(userDetails).
}
private class DownloaderTask extends AsyncTask<String, Integer, UserDetails> {
#Override
protected UserDetails doInBackground(String... params) {
//Download code
//In downloading there might go stuff wrong. If so, return null as an easy method without any error handling.
UserDetails userDetails = new UserDetails("downloadedUsername");
return userDetails;
}
#Override
protected void onPostExecute(UserDetails userDetails) {
if(userDetails == null) {
if(mListener != null) {
//Something went wrong. Tell the listener.
mListener.onUserDetailsError();
}
} else {
if(mListener != null) {
//Cool! Lets pass the userDetails to the activity.
mListener.onUserDetailsReceiver(userDetails);
}
}
}
}
}
Let your activity implements IOnUserDetailsReceivedListener.
public void UserActivity extends Activity implements IOnUserDetailsReceivedListener {
private UserDetailsDownloader mUserDetailsDownloader;
public void onCreate(...) {
mUserDetailsDownloader = new UserDetailsDownloader(this);
mUserDetailsDownloader.downloadUserDetails();
}
public void onUserDetailsReceived(UserDetails userDetails) {
//Yeeh we received user data.
}
public void onUserDetailsError() {
//Something went wrong. Tell the user?
}
}
When your task is done, it'll call your Activities onUserDetailsReceived method and pass you the UserDetails value object with which you can then do what you want.
I don't know if this is your only problem or not but too much for a comment. You shouldn't use runOnUiThread() in doInBackground()
runOnUiThread(new Runnable() {
public void run() {
//this might cause some SHIT!!!!!!!!!!!! TEST IT!!!
toastMaker.toast(getBaseContext(), configurationz.ERROR_MESSAGES_SIGNUP_DEVICE_UNABLE_TO_TAKE_PHOTOS, configurationz, Toast.LENGTH_LONG);
}
});
this is why AsyncTask has onPostExecute() and its other methods...they all run on the UI Thread except for doInBackground()
Instead of return null, returnsuccessand depending on that value, do what you need to inonPostExecute()`.
Edit
onPostExecute() gets its parameter from what doInBackground() returns which is the third param in your declaration public class GetUserDataGetter extends AsyncTask<String, String, String>. So you can change that param or return a String to onPostExecute() from doInBackground().
AsyncTask Docs