I get Null Pointer Exception when Android OS kills my app - android

I have a simple weather app that uses fragments to display the current, hourly and daily weather. I have noticed that when I open a heavy app (game) and then I try to open the my app it crashes with the null pointer exception because a fragment (maybe all of the 3) is not attached to the fragment manager.
I have experienced this crash many times but with no luck finding a solution to the problem. I have including a if-else statement to check if the fragment is attached (see the log). Why might I be getting the NPE?
Here is my log:
Getting first location updates...
01-22 22:02:05.362 14082-14082/koemdzhiev.com.stormy V/MainActivity: Locality: Aberdeen, CountryName United Kingdom
01-22 22:02:05.749 14082-14115/koemdzhiev.com.stormy D/MainActivity: OnResponse_ scheduledFuture is CANCELED
01-22 22:02:05.757 14082-14082/koemdzhiev.com.stormy D/MainActivity: isSuccessful - run on UNI threth (update display)...
01-22 22:02:05.787 14082-14082/koemdzhiev.com.stormy D/MainActivity: mCurrent fragment is NOT attached!
01-22 22:02:05.788 14082-14082/koemdzhiev.com.stormy D/AndroidRuntime: Shutting down VM
01-22 22:02:05.789 14082-14082/koemdzhiev.com.stormy E/AndroidRuntime: FATAL EXCEPTION: main
Process: koemdzhiev.com.stormy, PID: 14082
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
at android.widget.Toast.<init>(Toast.java:103)
at android.widget.Toast.makeText(Toast.java:260)
at koemdzhiev.com.stormy.ui.Hourly_forecast_fragment.setUpHourlyFragment(Hourly_forecast_fragment.java:128)
at koemdzhiev.com.stormy.ui.MainActivity$3$3.run(MainActivity.java:247)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5294)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
The problematic method in MainActivity:
public void getForecast(double latitude, double longitude) {
//scedule no response from the server task...
mScheduledFuture = exec.schedule(mNotAbleToGetWeatherDataTask,12, TimeUnit.SECONDS);
Log.d(TAG, "getForecast initiated...");
String API_KEY = "API_KEY";
String forecast = "https://api.forecast.io/forecast/" + API_KEY + "/" + latitude + "," + longitude + "?units=si";
if (isNetworkAvailable()) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(forecast)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
runOnUiThread(new Runnable() {
#Override
public void run() {
toggleSwipeRefreshLayoutsOff();
}
});
//on response from the server cansel the noResponseFromServer task
//on response from the server cansel the noResponseFromServer task
Log.d(TAG,"OnFailure_ scheduledFuture is CANCELED");
mScheduledFuture.cancel(true);
alertUserAboutError();
}
//when the call to the Okhttp library finishes, than calls this method:
#Override
public void onResponse(Response response) throws IOException {
runOnUiThread(new Runnable() {
#Override
public void run() {
toggleSwipeRefreshLayoutsOff();
}
});
try {
String jsonData = response.body().string();
if (response.isSuccessful()) {
mForecast = parseForecastDetails(jsonData);
runOnUiThread(new Runnable() {
#Override
public void run() {
Log.d(TAG, "isSuccessful - run on UNI threth (update display)...");
if(mCurrent_forecast_fragment.isAdded()){
Log.d(TAG, "mCurrent fragment is attached!");
mCurrent_forecast_fragment.updateDisplay();
}else{
Toast.makeText(MainActivity.this, "mCurrent is not attached!", Toast.LENGTH_SHORT).show();
Log.d(TAG, "mCurrent fragment is NOT attached!");
adapter = null;
adapter = new ViewPagerAdapter(getSupportFragmentManager(), Titles, Numboftabs, mCurrent_forecast_fragment,
mHourly_forecast_fragment, mDaily_forecast_fragment);
}
mHourly_forecast_fragment.setUpHourlyFragment();
mDaily_forecast_fragment.setUpDailyFragment();
toggleSwipeRefreshLayoutsOff();
//set the isFirstTime to true so that the next refresh wont get location
isFirstTimeLaunchingTheApp = false;
}
});
} else {
alertUserAboutError();
}
} catch (IOException | JSONException e) {
Log.e(TAG, "Exception caught:", e);
}
//on response from the server cansel the noResponseFromServer task
Log.d(TAG,"OnResponse_ scheduledFuture is CANCELED");
mScheduledFuture.cancel(true);
}
});
} else {
toggleSwipeRefreshLayoutsOff();
alertForNoInternet();
Log.d(TAG, "Alert No Internet" + 220);
//is there is no internet cancel the noResponseFromServer task
Log.d(TAG, "No internet _ scheduledFuture is CANCELED");
mScheduledFuture.cancel(true);
}
}
This is mCurrent fragment code (line 247 is this code:
mHourly_forecast_fragment.setUpHourlyFragment (in main activity))
public class Current_forecast_fragment extends Fragment {
private static final String TAG = "MainActivity";
private MainActivity mActivity;
TextView mTimeLabel;
TextView mTemperatureLabel;
TextView mHumidityValue;
TextView mPrecipValue;
TextView mSummaryLabel;
TextView mLocationLabel;
TextView mWindSpeedValue;
TextView mFeelsLike;
ImageView mIconImageView;
ImageView mDegreeImageView;
public SwipeRefreshLayout mSwipeRefreshLayout;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivity = ((MainActivity) getActivity());
// Log.d(mActivity.getClass().getSimpleName(),"OnCreateFragment");
}
#Override
public void onResume() {
super.onResume();
Log.d(TAG, "OnResume - Current Fragment called");
mActivity = ((MainActivity) getActivity());
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.current_forefast_fragment, container, false);
mTimeLabel = (TextView)v.findViewById(R.id.timeLabel);
mTemperatureLabel = (TextView)v.findViewById(R.id.temperatureLabel);
mHumidityValue = (TextView)v.findViewById(R.id.humidityValue);
mPrecipValue = (TextView)v.findViewById(R.id.precipValue);
mSummaryLabel = (TextView)v.findViewById(R.id.summaryLabel);
mLocationLabel = (TextView)v.findViewById(R.id.locationLabel);
mWindSpeedValue = (TextView)v.findViewById(R.id.windSpeedValue);
mFeelsLike = (TextView)v.findViewById(R.id.feels_like_label);
mIconImageView = (ImageView)v.findViewById(R.id.iconImageView);
mDegreeImageView = (ImageView)v.findViewById(R.id.degreeImageView);
mSwipeRefreshLayout = (SwipeRefreshLayout)v.findViewById(R.id.current_swipe_refresh_layout);
mSwipeRefreshLayout.setColorSchemeResources(R.color.orange, R.color.blue, R.color.green);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
Log.d("TAG", "Swiping in current!");
//if there is internet and if the mSwipeRefreshLayout in the Hourly and daily fragments are not already running...
if (mActivity.isNetworkAvailable()) {
if (!mActivity.mHourly_forecast_fragment.mSwipeRefreshLayout.isRefreshing() && !mActivity.mDaily_forecast_fragment.mSwipeRefreshLayout.isRefreshing()) {
if (mActivity.isLocationServicesEnabled()) {
if (mActivity.latitude != 0.0 && mActivity.longitude != 0.0) {
mActivity.getForecast(mActivity.latitude, mActivity.longitude);
} else {
mActivity.getLocation();
}
}else{
mActivity.alertForNoLocationEnabled();
}
}else{
mSwipeRefreshLayout.setRefreshing(false);
Toast.makeText(mActivity, "currently refreshing...", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(mActivity, "No Internet Connection!", Toast.LENGTH_LONG).show();
mSwipeRefreshLayout.setRefreshing(false);
}
}
});
//Start the swipe refresh layout on start up is internet available
if(mActivity.isNetworkAvailable())
mSwipeRefreshLayout.post(new Runnable() {
#Override
public void run() {
mSwipeRefreshLayout.setRefreshing(true);
Log.d("TAG","running swiping...");
}
});
return v;
}
#Override
public void onDestroyView() {
super.onDestroyView();
Log.d(TAG, "OnDestroyView - Current Fragment called");
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "OnDestroy - Current Fragment called");
}
public void updateDisplay() {
if(mActivity != null) {
Current current = mActivity.mForecast.getCurrent();
//setting the current weather details to the ui
mTemperatureLabel.setText(current.getTemperature() + "");
mTimeLabel.setText("At " + current.getFormattedTime() + " it is");
mHumidityValue.setText(current.getHumidity() + "%");
mPrecipValue.setText(current.getPrecipChange() + "%");
mSummaryLabel.setText(current.getSummery());
mWindSpeedValue.setText(current.getWindSpeed() + "");
mFeelsLike.setText("Feels like: " + current.getFeelsLike());
mLocationLabel.setText(mActivity.locationName);
Drawable drawable = ContextCompat.getDrawable(mActivity, current.getIconId());
mIconImageView.setImageDrawable(drawable);
}else{
Toast.makeText(getActivity(),"Could not update data at this time! Please, try again.",Toast.LENGTH_LONG).show();
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
}
}
Line 128 in Hourly Activity:
public void setUpHourlyFragment(){
if (mActivity != null) {
// Toast.makeText(mActivity, getString(R.string.network_unavailable_message), Toast.LENGTH_LONG).show();
//set to null to reset the old one and set a new adapter bellow...
mListView.setAdapter(null);
Hour[] hourlyForecast = mActivity.mForecast.getHourlyForecast();
mHours = Arrays.copyOf(hourlyForecast, hourlyForecast.length, Hour[].class);
HourListAdapter adapter = new HourListAdapter(mActivity, mHours);
mListView.setEmptyView(mEmptyTextView);
mListView.setAdapter(adapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
Hour h = mHours[position];
String time = h.getHour();
String temperature = h.getTemperature()+"";
String summary = h.getSummary();
String message = String.format("At %s it will be %s and %s",time,temperature,summary);
Toast.makeText(mActivity, message, Toast.LENGTH_LONG).show();
//play animations
YoYo.with(Techniques.Shake).duration(200).playOn(view);
}
});
}else{
//LINE 128 bellow...
Toast.makeText(getActivity(),"Main Activity is null in Hourly Fragment",Toast.LENGTH_LONG).show();
}
}
}

Please use instance of mActivity instead of getActivity() inside Toast (Line : 128).
`Toast.makeText(getActivity(),"Main Activity is null in Hourly Fragment",Toast.LENGTH_LONG).show();}`
As for extra check, provide a null check before making Toast on mActivity.

Related

Trying to integrate the Sinch API for Voip getting exception

I am trying to integrate the Sinch API in android .
My VOIPClient. Java is like this
public class VOIPClient {
private static final String TAG = "VOIPClient";
private SinchClient mSinch;
private TTSHelper mTTS;
private Call mCurrentCall;
private BootService mContext;
private SinchClientBuilder mBuilder;
private NsdController mNsdController;
private final CallListener mCallListener = new CallListener() {
#Override
public void onCallProgressing(Call call) {
Log.d(TAG, "Call established at " + " Thusee");
}
#Override
public void onCallEstablished(Call call) {
Log.d(TAG, "Call established at " + call.getDetails().getEstablishedTime());
mTTS.speak("Call started", TTSHelper.UTTERANCE_VOIP_START);
JsonObject payload = new JsonObject();
payload.addProperty("Status", 0);
payload.addProperty("Call_status", 1);
if (mNsdController != null) {
mNsdController.sendCommand(20, payload);
}
}
#Override
public void onCallEnded(Call call) {
Log.d(TAG, "Call ended at " + call.getDetails().getEndedTime() + "caused by " + call.getDetails().getEndCause().toString());
mTTS.speak("Call ended", TTSHelper.UTTERANCE_VOIP_END);
mCurrentCall.hangup();
JsonObject payload = new JsonObject();
payload.addProperty("Status", 0);
payload.addProperty("Call_status", 1);
if (mNsdController != null) {
mNsdController.sendCommand(21, payload);
}
}
#Override
public void onShouldSendPushNotification(Call call, List<PushPair> list) {
}
};
public VOIPClient(BootService context) {
mContext = context;
mTTS = TTSHelper.getInstance(context);
mBuilder = Sinch.getSinchClientBuilder().context(mContext.getApplicationContext())
.applicationKey(CloudConfig.SINCH_APP_KEY)
.applicationSecret(CloudConfig.SINCH_APP_SECRET)
.environmentHost(CloudConfig.SINCH_ENVIRONMENT);
if (mNsdController != null)
mNsdController.initialize();
}
public void start() {
SharedPreferences prefs = mContext.getPreferences();
int userId = prefs.getInt(MerryClient.PREF_USER_ID, 0);
String mUserId;
if (userId > 0) {
mUserId = String.valueOf(userId);
mSinch = Sinch.getSinchClientBuilder().context(mContext.getApplicationContext()).userId(mUserId)
.applicationKey(CloudConfig.SINCH_APP_KEY)
.applicationSecret(CloudConfig.SINCH_APP_SECRET)
.environmentHost(CloudConfig.SINCH_ENVIRONMENT).build();
mSinch.setSupportCalling(true);
mSinch.setSupportManagedPush(false);
SinchClientListener sinchClientListener = new SinchClientListener() {
#Override
public void onClientStarted(SinchClient sinchClient) {
Log.d(TAG, "Sinch Client starts: " + sinchClient.getLocalUserId());
mTTS.speak("Call ready", TTSHelper.UTTERANCE_VOIP_READY);
}
#Override
public void onClientStopped(SinchClient sinchClient) {
Log.d(TAG, "Sinch Client stops");
}
#Override
public void onClientFailed(SinchClient sinchClient, SinchError sinchError) {
Log.e(TAG, String.format("Sinch Client error %d: %s", sinchError.getCode(), sinchError.getMessage()));
mSinch.terminate();
mTTS.speak("Voice Over IP failed", TTSHelper.UTTERANCE_VOIP_FAIL);
}
#Override
public void onRegistrationCredentialsRequired(SinchClient sinchClient, ClientRegistration clientRegistration) {
Log.d(TAG, "Sinch Client requires registration");
}
#Override
public void onLogMessage(int i, String s, String s1) {
Log.d(TAG, s1);
}
};
mSinch.addSinchClientListener(sinchClientListener);
mSinch.getCallClient().setRespectNativeCalls(false);
mSinch.getCallClient().addCallClientListener(new SinchCallClientListener());
mCurrentCall = null;
mSinch.startListeningOnActiveConnection();
mSinch.start();
}
}
public void tearDown() {
if (mSinch != null) {
mSinch.stopListeningOnActiveConnection();
mSinch.terminate();
mSinch = null;
}
}
public void restart() {
tearDown();
start();
}
public void initiateCall(final String targetUserName) {
new Thread(new Runnable() {
public void run() {
Looper.prepare();
if (targetUserName != null) {
try {
Call call = callUser(targetUserName);
call.addCallListener(mCallListener);
mCurrentCall = call;
} catch (Exception e) {
Log.e(TAG, "Initiate VOIP call failed", e);
}
}
Looper.loop();
}
}).start();
}
public void answerCall() {
if (mCurrentCall != null) {
mCurrentCall.answer();
}
}
public void hangUpCall() {
if (mCurrentCall != null) {
mCurrentCall.hangup();
}
}
private class SinchCallClientListener implements CallClientListener {
#Override
public void onIncomingCall(CallClient callClient, Call call) {
Log.d(TAG, "Incoming call");
mTTS.speak("Incoming call from " + call.getRemoteUserId(), TTSHelper.UTTERANCE_VOIP_INCOMING);
call.addCallListener(mCallListener);
mCurrentCall = call;
// For testing only
answerCall();
}
}
public Call callUser(String userId) {
if (mSinch != null && mSinch.isStarted()) {
start();
}
if (mSinch == null) {
return null;
}
return mSinch.getCallClient().callUser(userId);
}
class CallerThread implements Runnable {
public String mtargetUserName;
CallerThread(String targetUserName) {
this.mtargetUserName = targetUserName;
}
#Override
public void run() {
Looper.prepare();
if (mtargetUserName != null) {
try {
Call call = callUser(mtargetUserName);
call.addCallListener(mCallListener);
mCurrentCall = call;
} catch (Exception e) {
Log.e(TAG, "Initiate VOIP call failed", e);
mContext.getAlexa().start();
}
}
Looper.loop();
}
}
}
When I try to call to other device then I am getting these kind of exceptions
Initiate VOIP call failed
java.lang.IllegalStateException: SinchClient not started
at com.sinch.android.rtc.internal.client.calling.DefaultCallClient.throwUnlessStarted(Unknown Source)
at com.sinch.android.rtc.internal.client.calling.DefaultCallClient.call(Unknown Source)
at com.sinch.android.rtc.internal.client.calling.DefaultCallClient.callUser(Unknown Source)
at com.sinch.android.rtc.internal.client.calling.DefaultCallClient.callUser(Unknown Source)
at tw.com.test.cloud.VOIPClient.callUser(VOIPClient.java:272)
at tw.com.test.cloud.VOIPClient$CallerThread.run(VOIPClient.java:293)
at java.lang.Thread.run(Thread.java:818)
Also some times I am getting this exception
FATAL EXCEPTION: Thread-75
Process: tw.com.test.wear, PID: 1123
java.lang.IllegalThreadStateException: A Looper must be associated with this thread.
at com.sinch.android.rtc.internal.AndroidLooperCallbackHandler.<init>(Unknown Source)
at com.sinch.android.rtc.internal.client.InternalSinchClientFactory.createSinchClient(Unknown Source)
at com.sinch.android.rtc.DefaultSinchClientBuilder.build(Unknown Source)
at tw.com.test.cloud.VOIPClient.start(VOIPClient.java:109)
at tw.com.test.cloud.VOIPClient$2.onClientStopped(VOIPClient.java:124)
at com.sinch.android.rtc.internal.client.DefaultSinchClient.shutdown(Unknown Source)
at com.sinch.android.rtc.internal.client.DefaultSinchClient.terminate(Unknown Source)
at tw.com.test.cloud.VOIPClient.tearDown(VOIPClient.java:160)
at tw.com.test.nsd.NsdController.messageReceived(NsdController.java:570)
at tw.com.test.nsd.NsdConnection.run(NsdConnection.java:115)
at java.lang.Thread.run(Thread.java:818)
2 Days I tried my self, I can't able to solve this yet,
I am always getting these exception. Sometimes it will work for one time then I need to restart the app.
You have to start SinchClient sinchClient.start(); and take NOTE during production mode do not place in a plain text form your SINCH_APP_SECRET, because its a secret key, hackers will easily read or decompile your code.
public VOIPClient(BootService context) {
mContext = context;
mTTS = TTSHelper.getInstance(context);
mBuilder = Sinch.getSinchClientBuilder().context(mContext.getApplicationContext())
.applicationKey(CloudConfig.SINCH_APP_KEY)
.applicationSecret(CloudConfig.SINCH_APP_SECRET)
.environmentHost(CloudConfig.SINCH_ENVIRONMENT);
sinchClient.setSupportCalling(true);
sinchClient.start();
if (mNsdController != null)
mNsdController.initialize();
}

How to remove this update icon? Android Swiperefersh

CODE
public class YellowFragment extends Fragment implements FlowerAdapter.FlowerClickListener{
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_yellow, container, false);
swipeContainer_yellow = (SwipeRefreshLayout) view.findViewById(R.id.swipeContainer_yellow);
setRetainInstance(true);
mReferSharedPreference = new ReferSharedPreference(getContext());
mlat = mReferSharedPreference.getValue("Lat", "None");
mlon = mReferSharedPreference.getValue("Lon", "None");
mCoordinatesTextLinear = (TextView) view.findViewById(R.id.tv_coordinates_linear);
if(!mlat.equals("None")){
getLinearPosts();
}
else {
Toast.makeText(getContext(), "Choose your location", Toast.LENGTH_LONG).show();
}
swipeContainer_yellow.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
if(!mlat.equals("None")){
getLinearPosts();
}
else {
Toast.makeText(getContext(), "Choose your location", Toast.LENGTH_LONG).show();
}
}
});
configViews(view);
return view;
}
private void getLinearPosts() {
ReferSharedPreference preferenceCoordinates = new ReferSharedPreference(getContext());
String lat = preferenceCoordinates.getValue("Lat", "None");
String lon = preferenceCoordinates.getValue("Lon", "None");
mCoordinatesTextLinear.setText("Your Location :" + lat + " , " + lon);
mRestManager = new RestManager();
Call<List<Flower>> listCall = mRestManager.getmFlowerApiService(getActivity()).getAllFlowers(lat, lon);
listCall.enqueue(new Callback<List<Flower>>() {
#Override
public void onResponse(Call<List<Flower>> call, Response<List<Flower>> response) {
if (response.isSuccessful()) {
mFlowerAdapter.clear();
List<Flower> flowerList = response.body();
for(int i =0; i<flowerList.size(); i++) {
Flower flower = flowerList.get(i);
mFlowerAdapter.addFlower(flower);
}
swipeContainer_yellow.setRefreshing(false);
}
}
#Override
public void onFailure(Call<List<Flower>> call, Throwable t) {
}
});
}
In this code, when i swipe, if mlat is None, there is swipe updating icon and it's not disappear.
What i wanted is that if mlat has some value, do getLinearPosts();, but if mlat has None, show Toast "Choose your location".
but refershing icon do not disappear
like this
Question: How can i disappear this updating or refreshing icon when mlat is None?
After your task is completed, just call swipeContainer_yellow.setRefreshing(false) and it will hide that progressbar
As i can see you have already used it, but problem is you are assuming that your response will be perfect all the time. So instead of keeping it inside if (response.isSuccessful()), keep it outside if condition and also put it in onFailure()
listCall.enqueue(new Callback<List<Flower>>() {
#Override
public void onResponse(Call<List<Flower>> call, Response<List<Flower>> response) {
swipeContainer_yellow.setRefreshing(false);
if (response.isSuccessful()) {
mFlowerAdapter.clear();
List<Flower> flowerList = response.body();
for(int i =0; i<flowerList.size(); i++) {
Flower flower = flowerList.get(i);
mFlowerAdapter.addFlower(flower);
}
}
}
#Override
public void onFailure(Call<List<Flower>> call, Throwable t) {
swipeContainer_yellow.setRefreshing(false);
}
});

Getting occasional NullPointerExceptions when setRefreshing(boolean) on SwipeRefreshLayout

I have a simple app that consists of one main activity and 3 fragments with ViewPager and Sliding tab layout. In each of the fragments I have SwipeRefreshLayouts.
The problem is sometimes when Android OS decides to kill my app and it crashes with that exception. It does not happen every time, though. I assume that sometimes the fragments are not created when I call the setRefreshing method and that is what is causing the error. Anyone having a suggestion on how to avoid this NPE?
This is the log:
12-29 23:31:41.770 29982-29982/koemdzhiev.com.stormy E/AndroidRuntime: FATAL EXCEPTION: main
Process: koemdzhiev.com.stormy, PID: 29982
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.widget.SwipeRefreshLayout.setRefreshing(boolean)' on a null object reference
at koemdzhiev.com.stormy.ui.MainActivity.toggleSwipeRefreshLayoutsOff(MainActivity.java:268)
at koemdzhiev.com.stormy.ui.MainActivity$3$2.run(MainActivity.java:224)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5292)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
MainActivity onCreate:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//-----------MY CODE STARTS HERE-----------------
//check if the user previously has seen the whats new message...
sharedPref = getPreferences(Context.MODE_PRIVATE);
editor = sharedPref.edit();
if (sharedPref.getInt(getString(R.string.saved_if_whats_new_seen), 1) != 0){
WhatsNewDialogCreator dialogCreator = new WhatsNewDialogCreator(this, sharedPref);
dialogCreator.show();
}
request = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY)
.setSmallestDisplacement(800)
.setFastestInterval(5 * 60 * 1000)
.setInterval(60 * 60 * 1000);
locationProvider = new ReactiveLocationProvider(this);
//subscribe for background location updates...
if(isNetworkAvailable()) {
startBackgroundUpdates();
}
mainActivityLayout = (LinearLayout)findViewById(R.id.main_activity_layout);
changeWindowTopColor();
this.mCurrent_forecast_fragment = new Current_forecast_fragment();
this.mHourly_forecast_fragment = new Hourly_forecast_fragment();
this.mDaily_forecast_fragment = new Daily_forecast_fragment();
// Creating The ViewPagerAdapter and Passing Fragment Manager, Titles fot the Tabs and Number Of Tabs.
adapter = new ViewPagerAdapter(getSupportFragmentManager(), Titles, Numboftabs, mCurrent_forecast_fragment,
mHourly_forecast_fragment, mDaily_forecast_fragment);
// Assigning ViewPager View and setting the adapter
pager = (ViewPager) findViewById(R.id.pager);
pager.setOffscreenPageLimit(3);
pager.setAdapter(adapter);
// Assiging the Sliding Tab Layout View
tabs = (SlidingTabLayout) findViewById(R.id.tabs);
tabs.setDistributeEvenly(true); // To make the Tabs Fixed set this true, This makes the tabs Space Evenly in Available width
// Setting Custom Color for the Scroll bar indicator of the Tab View
tabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
#Override
public int getIndicatorColor(int position) {
return ContextCompat.getColor(MainActivity.this, R.color.tabsScrollColor);
}
});
// Setting the ViewPager For the SlidingTabsLayout
tabs.setViewPager(pager);
if(isFirstTimeLaunchingTheApp) {
Log.d(TAG, "onCreate getLocation");
getLocation();
}
}
ViewPagerAdapter:
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private Current_forecast_fragment mCurrent_forecast_fragment;
private Hourly_forecast_fragment mHourly_forecast_fragment;
private Daily_forecast_fragment mDaily_forecast_fragment;
CharSequence Titles[]; // This will Store the Titles of the Tabs which are Going to be passed when ViewPagerAdapter is created
int NumbOfTabs; // Store the number of tabs, this will also be passed when the ViewPagerAdapter is created
// Build a Constructor and assign the passed Values to appropriate values in the class
public ViewPagerAdapter(FragmentManager fm,CharSequence mTitles[], int mNumbOfTabsumb,Current_forecast_fragment current_fragment,
Hourly_forecast_fragment hourly_fragment,
Daily_forecast_fragment daily_fragment) {
super(fm);
this.mCurrent_forecast_fragment = current_fragment;
this.mHourly_forecast_fragment = hourly_fragment;
this.mDaily_forecast_fragment = daily_fragment;
this.Titles = mTitles;
this.NumbOfTabs = mNumbOfTabsumb;
}
//This method return the fragment for the every position in the View Pager
#Override
public Fragment getItem(int position) {
if(position == 0) // if the position is 0 we are returning the First tab
{
return this.mCurrent_forecast_fragment;
}
else if (position == 1) // As we are having 2 tabs if the position is now 0 it must be 1 so we are returning second tab
{
return this.mHourly_forecast_fragment;
}else {
return this.mDaily_forecast_fragment;
}
}
// This method return the titles for the Tabs in the Tab Strip
#Override
public CharSequence getPageTitle(int position) {
return Titles[position];
}
// This method return the Number of tabs for the tabs Strip
#Override
public int getCount() {
return NumbOfTabs;
}
}
getLocation Method:
public void getLocation() {
Log.d(TAG,"getLocation initiated...");
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
if (isNetworkAvailable()) {
//check if the if the location services are enabled
if( !isLocationServicesEnabled()) {
alertForNoLocationEnabled();
}else {
LocationRequest oneTimeOnStartRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setNumUpdates(1)
.setInterval(0);
onlyFirstTimeSubscription = locationProvider.getUpdatedLocation(oneTimeOnStartRequest)
.subscribe(new Action1<Location>() {
#Override
public void call(Location location) {
Log.d(TAG, "Getting first location updates...");
MainActivity.this.latitude = location.getLatitude();
MainActivity.this.longitude = location.getLongitude();
reverseGeocodeObservable = locationProvider
.getReverseGeocodeObservable(location.getLatitude(), location.getLongitude(), 1);
getLocationName();
//check, only on create get location calls getForecast...
if (isFirstTimeLaunchingTheApp) {
getForecast(latitude, longitude);
}
onlyFirstTimeSubscription.unsubscribe();
}
});
}
} else {
alertForNoInternet();
Log.d(TAG, "Alert No Internet" + 366);
}
}
getForecastmethod (this is the method where the NPE is thrown)
public void getForecast(double latitude, double longitude) {
//scedule no response from the server task...
mScheduledFuture = exec.schedule(mNotAbleToGetWeatherDataTask,12, TimeUnit.SECONDS);
Log.d(TAG, "getForecast initiated...");
String API_KEY = "API_KEY";
String forecast = "https://api.forecast.io/forecast/" + API_KEY + "/" + latitude + "," + longitude + "?units=auto";
if (isNetworkAvailable()) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(forecast)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
runOnUiThread(new Runnable() {
#Override
public void run() {
toggleSwipeRefreshLayoutsOff();
}
});
//on response from the server cansel the noResponseFromServer task
//on response from the server cansel the noResponseFromServer task
Log.d(TAG,"OnFailure_ scheduledFuture is CANCELED");
mScheduledFuture.cancel(true);
alertUserAboutError();
}
//when the call to the Okhttp library finishes, than calls this method:
#Override
public void onResponse(Response response) throws IOException {
runOnUiThread(new Runnable() {
#Override
public void run() {
toggleSwipeRefreshLayoutsOff();
}
});
try {
String jsonData = response.body().string();
if (response.isSuccessful()) {
mForecast = parseForecastDetails(jsonData);
runOnUiThread(new Runnable() {
#Override
public void run() {
Log.d(TAG, "isSuccessful - run on UNI threth (update display)...");
mCurrent_forecast_fragment.updateDisplay();
mHourly_forecast_fragment.setUpHourlyFragment();
mDaily_forecast_fragment.setUpDailyFragment();
toggleSwipeRefreshLayoutsOff();
//set the isFirstTime to true so that the next refresh wont get location
isFirstTimeLaunchingTheApp = false;
}
});
} else {
alertUserAboutError();
}
} catch (IOException | JSONException e) {
Log.e(TAG, "Exception caught:", e);
}
//on response from the server cansel the noResponseFromServer task
Log.d(TAG,"OnResponse_ scheduledFuture is CANCELED");
mScheduledFuture.cancel(true);
}
});
} else {
toggleSwipeRefreshLayoutsOff();
alertForNoInternet();
Log.d(TAG, "Alert No Internet" + 220);
//is there is no internet cancel the noResponseFromServer task
Log.d(TAG, "No internet _ scheduledFuture is CANCELED");
mScheduledFuture.cancel(true);
}
}
I have the same situation as yours when I use Fragment&ViewPager...
here is the way I figure it out:
if (swipeRefreshLayout != null) {
swipeRefreshLayout.setRefreshing(false);
}
Ps:
when I use SwipeRefreshLayout it an activity,this exception will not happen. Can someone provide better answers?

List ImageView repeating same image when shared

I have a listView that is supposed to accept a shared message and image where the image is placed within the ImageView. This feature works for just the first message, but once an image is shared, each message received after that initial one becomes a copy of that same image even though the blank image placeholder was already set, which is just a one pixel black png:
holder.sharedSpecial.setImageResource(R.drawable.image_share_empty_holder);
An example is below:
The green textbox is the recipient. They have recieved a shared image from the yellow textbox. The yellow textbox then simply sends a normal message and I have set another image as a placeholder for normal messages: holder.sharedSpecial.setImageResource(R.drawable.image_share_empty_holder);
The same previously shared image takes precedence. I have used notifyDataSetChanged() so as to allow for the updating the adapter so that it would recognize not to use the same image, but to no avail.
How can I reformulate this class so that the image shared is only displayed with the proper message and not copied into each subsequent message?
The ArrayAdapter class:
public class DiscussArrayAdapter extends ArrayAdapter<OneComment> {
class ViewHolder {
TextView countryName;
ImageView sharedSpecial;
LinearLayout wrapper;
}
private TextView countryName;
private ImageView sharedSpecial;
private MapView locationMap;
private GoogleMap map;
private List<OneComment> countries = new ArrayList<OneComment>();
private LinearLayout wrapper;
private JSONObject resultObject;
private JSONObject imageObject;
String getSharedSpecialURL = null;
String getSharedSpecialWithLocationURL = null;
String specialsActionURL = "http://" + Global.getIpAddress()
+ ":3000/getSharedSpecial/";
String specialsLocationActionURL = "http://" + Global.getIpAddress()
+ ":3000/getSharedSpecialWithLocation/";
String JSON = ".json";
#Override
public void add(OneComment object) {
countries.add(object);
super.add(object);
}
public DiscussArrayAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
}
public int getCount() {
return this.countries.size();
}
private OneComment comment = null;
public OneComment getItem(int index) {
return this.countries.get(index);
}
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
View row = convertView;
if (row == null) {
LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.message_list_item, parent, false);
holder = new ViewHolder();
holder.wrapper = (LinearLayout) row.findViewById(R.id.wrapper);
holder.countryName = (TextView) row.findViewById(R.id.comment);
holder.sharedSpecial = (ImageView) row.findViewById(R.id.sharedSpecial);
// Store the ViewHolder as a tag.
row.setTag(holder);
} else {
holder = (ViewHolder) row.getTag();
}
Log.v("COMMENTING","Comment is " + countries.get(position).comment);
//OneComment comment = getItem(position);
holder.countryName.setText(countries.get(position).comment);
// Initiating Volley
final RequestQueue requestQueue = VolleySingleton.getsInstance().getRequestQueue();
// Check if message has campaign or campaign/location attached
if (countries.get(position).campaign_id == "0" && countries.get(position).location_id == "0") {
holder.sharedSpecial.setImageResource(R.drawable.image_share_empty_holder);
Log.v("TESTING", "It is working");
} else if (countries.get(position).campaign_id != "0" && countries.get(position).location_id != "0") {
// If both were shared
getSharedSpecialWithLocationURL = specialsLocationActionURL + countries.get(position).campaign_id + "/" + countries.get(position).location_id + JSON;
// Test Campaign id = 41
// Location id = 104
// GET JSON data and parse
JsonObjectRequest getCampaignLocationData = new JsonObjectRequest(Request.Method.GET, getSharedSpecialWithLocationURL, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
// Parse the JSON:
try {
resultObject = response.getJSONObject("shared");
} catch (JSONException e) {
e.printStackTrace();
}
// Get and set image
Picasso.with(getContext()).load("http://" + Global.getIpAddress() + ":3000" + adImageURL).into(holder.sharedSpecial);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("Error.Response", error.toString());
}
}
);
requestQueue.add(getCampaignLocationData);
} else if (countries.get(position).campaign_id != "0" && countries.get(position).location_id == "0") {
// Just the campaign is shared
getSharedSpecialURL = specialsActionURL + countries.get(position).campaign_id + JSON;
// Test Campaign id = 41
// GET JSON data and parse
JsonObjectRequest getCampaignData = new JsonObjectRequest(Request.Method.GET, getSharedSpecialURL, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
// Parse the JSON:
try {
resultObject = response.getJSONObject("shared");
} catch (JSONException e) {
e.printStackTrace();
}
// Get and set image
Picasso.with(getContext()).load("http://" + Global.getIpAddress() + ":3000" + adImageURL).into(holder.sharedSpecial);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("Error.Response", error.toString());
}
}
);
requestQueue.add(getCampaignData);
// Location set to empty
}
// If left is true, then yellow, if not then set to green bubble
holder.countryName.setBackgroundResource(countries.get(position).left ? R.drawable.bubble_yellow : R.drawable.bubble_green);
holder.wrapper.setGravity(countries.get(position).left ? Gravity.LEFT : Gravity.RIGHT);
return row;
}
}
The messaging class that sends normal messages only but can receive image messages and set to the adapter:
public class GroupMessaging extends Activity {
private static final int MESSAGE_CANNOT_BE_SENT = 0;
public String username;
public String groupname;
private Button sendMessageButton;
private Manager imService;
private InfoOfGroup group = new InfoOfGroup();
private InfoOfGroupMessage groupMsg = new InfoOfGroupMessage();
private StorageManipulater localstoragehandler;
private Cursor dbCursor;
private com.example.feastapp.ChatBoxUi.DiscussArrayAdapter adapter;
private ListView lv;
private EditText editText1;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
imService = ((MessagingService.IMBinder) service).getService();
}
public void onServiceDisconnected(ComponentName className) {
imService = null;
Toast.makeText(GroupMessaging.this, R.string.local_service_stopped,
Toast.LENGTH_SHORT).show();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.message_activity);
lv = (ListView) findViewById(R.id.listView1);
adapter = new DiscussArrayAdapter(getApplicationContext(), R.layout.message_list_item);
lv.setAdapter(adapter);
editText1 = (EditText) findViewById(R.id.editText1);
sendMessageButton = (Button) findViewById(R.id.sendMessageButton);
Bundle extras = this.getIntent().getExtras();
group.userName = extras.getString(InfoOfGroupMessage.FROM_USER);
group.groupName = extras.getString(InfoOfGroup.GROUPNAME);
group.groupId = extras.getString(InfoOfGroup.GROUPID);
String msg = extras.getString(InfoOfGroupMessage.GROUP_MESSAGE_TEXT);
setTitle("Group: " + group.groupName);
// Retrieve the information
localstoragehandler = new StorageManipulater(this);
dbCursor = localstoragehandler.groupGet(group.groupName);
if (dbCursor.getCount() > 0) {
// Probably where the magic happens, and keeps pulling the same
// thing
int noOfScorer = 0;
dbCursor.moveToFirst();
while ((!dbCursor.isAfterLast())
&& noOfScorer < dbCursor.getCount()) {
noOfScorer++;
}
}
localstoragehandler.close();
if (msg != null) {
// Then friends username and message, not equal to null, recieved
adapter.add(new OneComment(true, group.groupId + ": " + msg, "0", "0"));
adapter.notifyDataSetChanged();
((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
.cancel((group.groupId + msg).hashCode());
}
// The send button
sendMessageButton.setOnClickListener(new OnClickListener() {
CharSequence message;
Handler handler = new Handler();
public void onClick(View arg0) {
message = editText1.getText();
if (message.length() > 0) {
// When general texting, the campaign and location will always be "0"
// Only through specials sharing is the user permitted to change the campaign and location to another value
adapter.add(new OneComment(false, imService.getUsername() + ": " + message.toString(), "0", "0"));
adapter.notifyDataSetChanged();
localstoragehandler.groupInsert(imService.getUsername(), group.groupName,
group.groupId, message.toString(), "0", "0");
// as msg sent, will blank out the text box so can write in
// again
editText1.setText("");
Thread thread = new Thread() {
public void run() {
try {
// JUST PUTTING "0" AS A PLACEHOLDER FOR CAMPAIGN AND LOCATION
// IN FUTURE WILL ACTUALLY ALLOW USER TO SHARE CAMPAIGNS
if (imService.sendGroupMessage(group.groupId,
group.groupName, message.toString(), "0", "0") == null) {
handler.post(new Runnable() {
public void run() {
Toast.makeText(
getApplicationContext(),
R.string.message_cannot_be_sent,
Toast.LENGTH_LONG).show();
// showDialog(MESSAGE_CANNOT_BE_SENT);
}
});
}
} catch (UnsupportedEncodingException e) {
Toast.makeText(getApplicationContext(),
R.string.message_cannot_be_sent,
Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
};
thread.start();
}
}
});
}
#Override
protected Dialog onCreateDialog(int id) {
int message = -1;
switch (id) {
case MESSAGE_CANNOT_BE_SENT:
message = R.string.message_cannot_be_sent;
break;
}
if (message == -1) {
return null;
} else {
return new AlertDialog.Builder(GroupMessaging.this)
.setMessage(message)
.setPositiveButton(R.string.OK,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
/* User clicked OK so do some stuff */
}
}).create();
}
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(groupMessageReceiver);
unbindService(mConnection);
ControllerOfGroup.setActiveGroup(null);
}
#Override
protected void onResume() {
super.onResume();
bindService(new Intent(GroupMessaging.this, MessagingService.class),
mConnection, Context.BIND_AUTO_CREATE);
IntentFilter i = new IntentFilter();
i.addAction(MessagingService.TAKE_GROUP_MESSAGE);
registerReceiver(groupMessageReceiver, i);
ControllerOfGroup.setActiveGroup(group.groupName);
}
// For receiving messages form other users...
public class GroupMessageReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extra = intent.getExtras();
//Log.i("GroupMessaging Receiver ", "received group message");
String username = extra.getString(InfoOfGroupMessage.FROM_USER);
String groupRId = extra.getString(InfoOfGroupMessage.TO_GROUP_ID);
String message = extra
.getString(InfoOfGroupMessage.GROUP_MESSAGE_TEXT);
// NEED TO PLACE INTO THE MESSAGE VIEW!!
String received_campaign_id = extra.getString(InfoOfGroupMessage.CAMPAIGN_SHARED);
String received_location_id = extra.getString(InfoOfGroupMessage.LOCATION_SHARED);
// NEED TO INTEGRATE THIS INTO LOGIC ABOVE, SO IT MAKES SENSE
if (username != null && message != null) {
if (group.groupId.equals(groupRId)) {
adapter.add(new OneComment(true, username + ": " + message, received_campaign_id, received_location_id));
localstoragehandler
.groupInsert(username, groupname, groupRId, message, received_campaign_id, received_location_id);
Toast.makeText(getApplicationContext(), "received_campaign: " + received_campaign_id +
" received_location:" + received_location_id, Toast.LENGTH_LONG).show();
received_campaign_id = "0";
received_location_id = "0";
} else {
if (message.length() > 15) {
message = message.substring(0, 15);
}
Toast.makeText(GroupMessaging.this,
username + " says '" + message + "'",
Toast.LENGTH_SHORT).show();
}
}
}
}
;
// Build receiver object to accept messages
public GroupMessageReceiver groupMessageReceiver = new GroupMessageReceiver();
#Override
protected void onDestroy() {
super.onDestroy();
if (localstoragehandler != null) {
localstoragehandler.close();
}
if (dbCursor != null) {
dbCursor.close();
}
}
}
I have gone through your code and this is common problem with listview that images starts repeating itself. In your case I think you have assigned image to Imageview every if and else if condition but if none of the condition satisfy it uses the previous image.
I would suggest to debug the getview method and put break points on the setImageResource. I use volley for these image loading and it has a method called defaultImage so that if no url is there the image is going to get the default one. So add that default case and see if it works.
If any of the above point is not clear feel free to comment.

android: How to wait for listener to complete before continuing?

I'm using the socialAuth plugin to connect a user to linkdin within my app. I have the connection set up correctly and retrieves data. However, I'm unsure how I can get my main activity to wait until the socialAuthListeners have fired and finished. I know a little about threading but I haven't used it with listeners before. Here's my code:
public class LinkdinAuth {
private static final String TAG = "TEST";
// SocialAuth Components
SocialAuthAdapter adapter;
ProgressDialog mDialog;
private Context context;
private boolean loggedIn = false;
private Bundle LinkdinData;
public LinkdinAuth(Context C){
this.context = C;
LinkdinData = new Bundle();
adapter = new SocialAuthAdapter(new ResponseListener());
}
public void adapterAuthorize(View v){
adapter.authorize(v.getContext(), Provider.LINKEDIN);
}
private final class ResponseListener implements DialogListener
{
public void onComplete(Bundle values) {
String providerName = values.getString(SocialAuthAdapter.PROVIDER);
Log.d("Main", "providername = " + providerName);
mDialog = new ProgressDialog(context);
mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
mDialog.setMessage("Loading...");
//Get profile information
adapter.getUserProfileAsync(new ProfileDataListener());
// get Job and Education information
mDialog.show();
adapter.getCareerAsync(new CareerListener());
loggedIn = true;
Log.d("Main", "LOGGED IN = " + loggedIn );
Toast.makeText(context, providerName + " connected", Toast.LENGTH_SHORT).show();
}
#Override
public void onBack() {
Log.d("Main", "Dialog Closed by pressing Back Key");
}
#Override
public void onCancel() {
Log.d("Main", "Cancelled");
}
#Override
public void onError(SocialAuthError e) {
Log.d("Main", "Error");
e.printStackTrace();
}
}
// To receive the profile response after authentication
private final class ProfileDataListener implements SocialAuthListener<Profile> {
#Override
public void onExecute(String provider, Profile t) {
Log.d("Sign Up", "Receiving Data");
mDialog.dismiss();
Profile profileMap = t;
LinkdinData.putString("Validated ID", profileMap.getValidatedId() );
LinkdinData.putString("First Name", profileMap.getFirstName());
LinkdinData.putString("Last Name", profileMap.getLastName());
LinkdinData.putString("Email", profileMap.getEmail());
LinkdinData.putString("Country", profileMap.getCountry());
LinkdinData.putString("Language", profileMap.getLanguage());
LinkdinData.putString("Location", profileMap.getLocation());
LinkdinData.putString("Profile Image URL", profileMap.getProfileImageURL());
}
#Override
public void onError(SocialAuthError arg0) {
// TODO Auto-generated method stub
}
}
private final class CareerListener implements SocialAuthListener<Career> {
#Override
public void onExecute(String provider, Career t) {
Log.d("Custom-UI", "Receiving Data");
mDialog.dismiss();
Career careerMap = t;
//get education
Log.d("Main", "Education:");
if(careerMap.getEducations() != null){
for(Education E: careerMap.getEducations()){
Log.d("Main", "School = " +E.getSchoolName() );
Log.d("Main", "Major = " + E.getFieldOfStudy() );
Log.d("Main", "Degree = " + E.getDegree() );
Log.d("Main", "Start Date = " + E.getStartDate() );
Log.d("Main", "End Date = " + E.getEndDate() );
}
}
Log.d("SignUp", "Career");
if(careerMap.getPositions() != null){
for(Position P: careerMap.getPositions()){
LinkdinData.putString("Company Name", P.getCompanyName() );
LinkdinData.putString("Job Title", P.getTitle() );
Log.d("Main", "Industry = " + P.getIndustry() );
Log.d("Main", "Start Date = " + P.getStartDate() );
Log.d("Main", "End Date = " + P.getEndDate() );
}
}
}
#Override
public void onError(SocialAuthError e) {
}
}
public boolean isLoggedIn(){
return loggedIn;
}
public Bundle getLinkdinData(){
return LinkdinData;
}
So, as you can see. I have 2 listeners that get data after authorization goes through. And my main activity makes creates an instance, calls the adapterAuthroizeMethod and then if the user logs in a flag is set. Then getLinkedData is called. However I would like it to wait until I know the listeners have fired before calling getlinkdinData. Here's what my Main Activity does after a button press:
L.adapterAuthorize(v);
loggedInWithLinkdin = L.isLoggedIn();
Bundle B = L.getLinkdinData();
Intent i = new Intent(getBaseContext(), UserRegistration.class);
i.putExtra("linkdin bundle", B);
//startActivity(i);
Any ideas?
thanks
Well, not a recommend solution but more of a hack.
Here is what you can do.
Wrap the aync call around this construct :
AtomicBoolean done = new AtomicBoolean(false);
Global ans; // the return value holder
try{
result = someAsyncCall(query, new Thread()); // this new thread is for listener callback
result.setResultListener(result -> {
// do something with result.
ans = result.getAns() ; // set global ans
done.set(true);
synchronized (done) {
done.notifyAll(); // notify the main thread which is waiting
}
});
}
catch (Exception e ) {
Log(e);
}
synchronized (done) {
while (done.get() == false) {
done.wait(); // wait here until the listener fires
}
}
return ans; // return global ans

Categories

Resources