Android System.Err for setVisibility(View.GONE)? - java

I've noticed a bug in a basic survey app I'm making to better learn android.
Occasionally I get a W/System.errīš• at MainActivity.surveyAvailable(MainActivity.java:40) that points to this line of code:
button.setVisibility(View.GONE);
I've used setVisibility many times before and never had any issues.
Here's the function, this gets called when the user first enters the app, and after they finish taking a survey to check the server and see if there is another survey available for the user:
public void surveyAvailable(boolean surveyIsAvailable) {
Log.d("MainActivity", "App survey is available? " + surveyIsAvailable );
Button button = (Button)findViewById(R.id.takeSurveyButton);
if (surveyIsAvailable) {
button.setVisibility(View.VISIBLE);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
App.getInstance().showSurvey();
}
});
} else {
Log.d("MainActivity", "We hit here");
button.setVisibility(View.GONE);
}
}
When a survey isn't available, the appropriate lines are logged - App survey is available? false and 'We hit here'. But then the button sometimes doesn't get set to View.GONE and I see the System.Err line. But sometimes it works fine and the button's visibility does change. Any idea how to fix that? Or how to get more information on what the System.Err actually means?
EDIT:
I found that by setting Button surveyButton; in my activity and then referencing the button as this.surveyButton seems to get the functionality to work more along the lines of what we'd expect (e.g. when we call button.setVisibility(View.GONE) the view is actually consistently GONE). But it still throws the System.Err line which has me hesitant that things are working correctly.
Edited Activity:
public class MainActivity extends ActionBarActivity implements SurveyListener {
Button surveyButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.surveyButton = (Button)findViewById(R.id.takeSurveyButton);
}
public void surveyAvailable(boolean surveyIsAvailable) {
Log.d("MainActivity", "App survey is available? " + surveyIsAvailable );
if (surveyIsAvailable) {
this.surveyButton.setVisibility(View.VISIBLE);
this.surveyButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
App.getInstance().showSurvey();
}
});
} else {
Log.d("MainActivity", "We hit here");
this.surveyButton.setVisibility(View.GONE);
}
}
}
The activity implements this class:
public abstract interface SurveyListener
{
public abstract void surveyAvailable(boolean surveyAvailable);
}
Main App class that checks for surveys and calls 'surveyAvailable()`:
public class App
{
private static App _instance;
private SurveyListener _eventsHandler;
private String _apiKey = "";
private String _appuserId = "";
private String _surveyUrl = "";
private Activity _parentContext;
private Boolean _surveyAvailable;
public static App initWithApiKeyAndListener(String apiKey, SurveyListener surveyEventsHandler) {
if (_instance == null)
{
_instance = new App();
_instance._parentContext = (Activity) surveyEventsHandler;
_instance.setSurveyListener(surveyEventsHandler);
_instance.setApiKey(apiKey);
String appuserId = PreferenceManager.getDefaultSharedPreferences((Activity) _instance._eventsHandler).getString(tag, "no_appuser");
if (appuserId == "no_appuser") {
_instance._surveyAvailable = true;
_instance.alertAvailability(true);
} else {
_instance.checkForCampaigns();
}
}
return _instance;
}
private void alertAvailability(boolean surveyAvailable) {
App.getInstance()._eventsHandler.surveyAvailable(surveyAvailable);
}
private void checkForCampaigns() {
new CampaignCheck().execute();
}
public static App getInstance()
{
if (_instance == null)
{
_instance = new App();
}
return _instance;
}
public void donePushed()
{
App.getInstance().checkForCampaigns();
}
private class CampaignCheck extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
Boolean surveysAvailable = false;
try {
surveysAvailable = new AppuserConnection().checkCampaigns();
App.getInstance()._surveyAvailable = surveysAvailable;
App.getInstance().alertAvailability(_surveyAvailable);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
}
}
}

You shouldn't modify the UI elements from a different thread. You are doing this by calling App.getInstance().alertAvailability(_surveyAvailable); on a background thread. Move this to the AsyncTask's onPostExecute.

Related

Object listener inside asyncTask and publish updates (Android)

I am pretty new at android developing(only 2 months)
I am trying to create an asyncTask which receives a user id and creates the user object, and after it finishes to replace fragment.
every thing went well, until I tried to add publish updates.
Inside my user object it creates days object when creating the user,
I want the asyncTast to change textView text according to the number of days created so far.
So I created an interface inside my User object which call dayCreated() function everytime day is created and pass to it the number of days so far.
Inside my asyncTask in doInBackground I tried to set the listener and call publishUpdates each time but it crashes.
Here is my AsyncTask code:
class CreateUserTask extends AsyncTask<Integer, Integer, User> {
private int uid = -1;
#Override
protected User doInBackground(Integer... params) {
uid = params[0];
try {
User user;
user = new User(MainActivity.this, uid);
user.setEventHandler(new User.EventHandler() {
#Override
public void dayCreated(int dayCounter) {
publishProgress(dayCounter);
}
});
return user;
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPreExecute() {
fragmentsReplace(loadingFragment, "Loading");
}
#Override
protected void onPostExecute(User userRecieved) {
if(userRecieved != null) {
fragmentsReplace(mainFragment, TAG_MAIN_FRAGMENT);
user = userRecieved;
login();
}
else{
fragmentsReplace(loginFragment, TAG_LOGIN_FRAGMENT);
}
}
#Override
protected void onProgressUpdate(Integer... values) {
loadingFragment.setDayCounter(values[0]);
}
}
And inside my User object this is how I call using interface:
int dayCounter = 0;
Cursor result = myDataBase.getDaysData(this.uid);
while (!result.isAfterLast()) {
try {
Calendar date = Calendar.getInstance();
date.setTimeInMillis(Long.parseLong(result.getString(result.getColumnIndex(DataBaseHelper.DB_DATE_COLUMN))));
DayOfWork day = new DayOfWork(this.uid, date, this.context);
this.daysOfWorkArray.add(day);
dayCounter++;
eventHandler.dayCreated(dayCounter++);
}catch (Exception e)
{
Log.e("error" , e.getMessage());
}
result.moveToNext();
And the eventHandler code:
EventHandler eventHandler = null;
public interface EventHandler{
void dayCreated(int dayCounter);
}
public void setEventHandler(EventHandler eventHandler){
this.eventHandler = eventHandler;
}
Does publishProgress() interact with anything in your UI? If so your issue is that you're calling it from a background thread in your async task. All UI interactions need to execute on the main/UI thread.

QuickBlox VideoChat demo OnOpponentVideoDataReceived not called

I have some trouble with the OnQBVideoChatListener in QuickBlox, the two methods onOpponentVideoDataReceive and onOpponentAudioDataReceive are never called. Here is how I implemented the cameraView and the opponentView. It's basically the same as the sample app given here. I have tried to run the sample Video chat app on my phone and tablet however the same issue occures and only the cameraView gets updated. The opponent view is always black. Is there anyone who has experienced the same trouble and have a solution ?
Thanks a bunch !
private void initViews() {
// Setup UI
opponentView = (OpponentGlSurfaceView) findViewById(R.id.opponentView);
cameraView = (CameraView) findViewById(R.id.cameraView);
cameraView.setCameraFrameProcess(true);
// Set VideoChat listener
cameraView.setQBVideoChatListener(qbVideoChatListener);
// Set Camera init callback
cameraView.setFPS(6);
cameraView.setOnCameraViewListener(new OnCameraViewListener() {
#Override
public void onCameraSupportedPreviewSizes(List<Camera.Size> supportedPreviewSizes) {
Camera.Size firstFrameSize = supportedPreviewSizes.get(0);
Camera.Size lastFrameSize = supportedPreviewSizes.get(supportedPreviewSizes.size() - 1);
cameraView.setFrameSize(firstFrameSize.width > lastFrameSize.width ? lastFrameSize : firstFrameSize);
}
});
// VideoChat settings
videoChatConfig = (VideoChatConfig) GlobalVar.getObject(tag);
try {
QBVideoChatController.getInstance().setQBVideoChatListener((QBUser)GlobalVar.getObject(GlobalVar.CURRENT_USER_KEY), qbVideoChatListener);
} catch (XMPPException e) {
e.printStackTrace();
}
}
OnQBVideoChatListener qbVideoChatListener = new OnQBVideoChatListener() {
#Override
public void onCameraDataReceive(byte[] videoData) {
if (videoChatConfig.getCallType() != CallType.VIDEO_AUDIO) {
//...
}
else{
QBVideoChatController.getInstance().sendVideo(videoData);
Log.i(tag,"videoData sent!"); // THIS IS EXECUTED
}
}
#Override
public void onMicrophoneDataReceive(byte[] audioData) {
QBVideoChatController.getInstance().sendAudio(audioData);
Log.i(tag,"AudioData sent!"); //SO IS THIS
}
#Override
public void onOpponentVideoDataReceive(byte[] videoData) {
Log.i(tag,"received img from opponent"); //NOT CALLED
opponentView.loadOpponentImage(videoData);
}
#Override
public void onOpponentAudioDataReceive(byte[] audioData) {
Log.i(tag,"received Audio from opponent"); //NOT CALLED
QBVideoChatController.getInstance().playAudio(audioData);
}
#Override
public void onProgress(boolean progress) {
}
#Override
public void onVideoChatStateChange(CallState callState, VideoChatConfig chat) {
//... STUFF
}
};

Avoiding threads restarting when changing activity

Right now, when I change the activity, my thread seams to go to sleep or something. And when I come back to the main activity, there are two threads running, doing the same things. I'm not sure if this is the case, but it seems like it's something equal.
...
public class MainActivity extends Activity {
public static double cowCount = 195;
public static double income = 0.100;
static boolean twiceCow = false, Threadrunning = false;
...
public void inc() {
new Thread(new income()).start();
}
class income implements Runnable {
#Override
public void run() {
for (int i = 0; i < 20;) {
final int value = i;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler.post(new Runnable() {
#Override
public void run() {
cowCount = cowCount + income;
refresh();
}
});
}
}
}
This is how my thread looks like.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler();
checkThread();
}
private void checkThread() {
if (Threadrunning == false)
inc();
Threadrunning = true;
}
public void inc() {
new Thread(new income()).start();
}
...
public void refresh () {
TextView myTextView = (TextView)findViewById(R.id.myText);
myTextView.setText("You Have " + String.valueOf((nf.format(cowCount)) + " Cows!"));
}
I don't really understand what I've done wrong.
Please review this post: http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html
Consider your activity re-start as the same thing as a config change.
This pattern, i.e. using a retained Fragment as a container for your thread, and proxying UI updates via callbacks to your activity, is a pattern that will work much better for you.
In your case you'd need only a single TaskCallback for your UI refresh(), e.g. onRefreshCowCount(int cows);

AsyncTask callback not calling

I am having a problem with getting the result from an asyncTask in a separate class. I have followed from a similar questions answer on here but I cant see where I have gone wrong.
My AsyncTask is in a separate class for easy calling, I needed to be able to have the notice that the asyntask had completed and then start the next activity.
I would welcome any help as I am not sure quite where I have gone wrong.
public class StartScreen extends Activity{
ProgressDialog pd;
CountDownTimer waitTimer;
public static final String APP_PREFERENCES = "AppPrefs";
SharedPreferences settings;
SharedPreferences.Editor prefEditor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_screen);
settings = getSharedPreferences(APP_PREFERENCES, MODE_PRIVATE);
// getPreferences();
// prefEditor = settings.edit();
waitTimer = new CountDownTimer(2000, 300) {
public void onTick(long millisUntilFinished) {
//called every 300 milliseconds, which could be used to
//send messages or some other action
}
public void onFinish() {
//After 2000 milliseconds (2 sec) finish current
//if you would like to execute something when time finishes
pd = ProgressDialog.show(StartScreen.this,"Title","Detail text",true,false,null);
getPreferences();
}
}.start();
}
private void getPreferences() {
String UserName = settings.getString("UserName", null);
if (UserName != null) {
// the key does not exist
Intent intent=new Intent(StartScreen.this,InitialPreferences.class);
startActivity(intent);
} else{
//if (UserName.equals(UserName)){
// handle the value
dataTask();
//pd.dismiss();
}
}
private void dataTask() {
// TODO Auto-generated method stub
new DATATask(this).execute(new FragmentCallback(){
#Override
public void onTaskDone() {
startMainAct();
}
});
}
private void startMainAct() {
Intent intent=new Intent(StartScreen.this,MainActivity.class);
startActivity(intent);
}
public interface FragmentCallback {
public void onTaskDone();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.start_screen, menu);
return true;
}
}
AsyncTask:
public class DATATask extends AsyncTask<Void, Void, ArrayList<String>> {
private FragmentCallback mFragmentCallback;
public void execute(FragmentCallback fragmentCallback) {
mFragmentCallback = fragmentCallback;
}
ArrayList<String> arr_data=new ArrayList<String>();
private Context context;
public DATATask(Context context)
{
this.context = context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected ArrayList<String> doInBackground(Void... params) {
Document docVts, docTide;
String shippingList, tideTimes;
try {
docVts = Jsoup.connect("https://vts.mhpa.co.uk/main_movelistb.asp").timeout(600000).get();
Elements tableRows = docVts.select("table.dynlist td:eq(0),td:eq(1),td:eq(3),td:eq(4),td:eq(7),td:eq(8)");
tableRows.size();
for(int i = 1; i < 80; i++){//only allows x results from vts list, from 1 not 0. 0 produces needless results
shippingList = tableRows.get(i).text().replaceAll(" | ", "") +"\n";
arr_data.add(shippingList);// add value to ArrayList
System.out.println(shippingList);
};
docTide = Jsoup.connect("http://www.mhpa.co.uk/search-tide-times/").timeout(600000).get();
Elements tideTimeOdd = docTide.select("div.tide_row.odd div:eq(0)");
Elements tideTimeEven = docTide.select("div.tide_row.even div:eq(0)");
Elements tideHightOdd = docTide.select("div.tide_row.odd div:eq(2)");
Elements tideHightEven = docTide.select("div.tide_row.even div:eq(2)");
Element firstTideTime = tideTimeOdd.first();
Element secondTideTime = tideTimeEven.first();
Element thirdTideTime = tideTimeOdd.get(1);
Element fourthTideTime = tideTimeEven.get(1);
Element firstTideHight = tideHightOdd.first();
Element secondTideHight = tideHightEven.first();
Element thirdTideHight = tideHightOdd.get(1);
Element fourthTideHight = tideHightEven.get(1);
System.out.println("first tide time: " + firstTideTime.text() + " " + firstTideHight.text());
System.out.println("second tide time: " + secondTideTime.text() + " " + secondTideHight.text() );
System.out.println("third tide time: " + thirdTideTime.text() + " " + thirdTideHight.text());
System.out.println("fourth tide time: " + fourthTideTime.text() + " " + fourthTideHight.text());
{
/*
Work with data - all is OK
*/
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return arr_data;//<< return ArrayList from here
}
#Override
protected void onPostExecute(ArrayList<String> result) {
mFragmentCallback.onTaskDone();
}
}
Thanks for any help.
You are not calling the correct AsyncTask.execute(). The correct execute will invoke the onPreExecute() then doInBackground() then onPostExecute().
new DATATask(this).execute(new FragmentCallback(){
#Override
public void onTaskDone() {
startMainAct();
}
});
}
will call this method (the wrong one):
public void execute(FragmentCallback fragmentCallback) {
mFragmentCallback = fragmentCallback;
}
What you want to do is change this method to - setFragmentCallBack(FragmentCallback);
Then in the OnPostExecute() add this: startMainAct();
instead of doing this:
#Override
public void onTaskDone() {
startMainAct();
}
After this is done, then call the new DATATask(this).execute();
which will invoke the preExecute(), doInbackground, and PostExecute()
What you are doing is adding the FragCallback to the DataTask and not invoking the correct execute function.
I hope this helps.
Actually you did not execute your AsyncTask. You should call "super.execute(Params... params);" in you overloaded execute(FragmentCallback) method.
In your Activity:
DataTask dataTask = new DataTask();
dataTask.execute();
In your AsyncTask class:
onPostExecute(){
//put your intent to start the activity or whatever you want to do when it finishes
}
I think it is much simpler than you are making it. Hope that helps. Also, see AsyncTask Android example
You didn't execute the AsyncTask. Calling DATATask.execute(FragmentCallback) will just assign the callback to your task. You need to call either AsyncTask#execute(Runnable), AsyncTask#execute(Params...) or AsyncTask#executeOnExecutor(Executor exec, Params... params).
Also, I would pass the callback to DATATask via the constructor or a setter, instead of creating a new overloaded execute(FragmentCallback) method. It can easily confuse people.

How to find out what AsyncTask was running?

In one of my Activities I do have up to six different AsyncTasks that may run on different events. All AsyncTasks handle orientation changes gracefully (at least I hope so). In onRetainNonConfigurationInstance() I do return the AsyncTask object of a currently running AsyncTask. Later, during onCreate(), I need to find out what AsyncTask object is returned from getLastNonConfigurationInstance().
I use the Activity context in all onPostExecute() methods to get the new activity (if there is a new one). I found this concept here on StackOverflow and did modify it a little bit because I don't like that "Trash running tasks on orientation change" paradigma. Hope this concept is correct.
In the code shown below you'll find two different AsyncTasks. During onRetainNonConfigurationInstance() I will return the currently running AsyncTask. My problem is within onCreate(). How to find out what object is returned? What AsyncTask was running when orientation change bumped in?
Both AsyncTasks are different in many areas (not shown here) so I didn't use an own extended AsyncTask base object.
Many thanks in advance.
public class MyActivity extends ListActivity {
// First AsyncTask
private class MyLoadAsyncTask extends AsyncTask<Void, Void, Cursor> {
private MyActivity context;
private MyProgressDialog dialog;
public MyLoadAsyncTask(MyActivity context) {
super();
this.context = context;
}
#Override
protected Cursor doInBackground(Void... voids) {
return MyApplication.getSqliteOpenHelper().fetchSoomething();
}
#Override
protected void onPostExecute(Cursor cursor) {
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
if (cursor != null) {
context.startManagingCursor(cursor);
context.adapter = new InternetradiosAdapter(context,
R.layout.row,
cursor,
new String[] { "text1",
"text2" },
new int[] { R.id.row_text1,
R.id.row_text2 } );
if (context.adapter != null) {
context.setListAdapter(context.adapter);
}
}
context.loadTask = null;
}
#Override
protected void onPreExecute () {
dialog = MyProgressDialog.show(context, null, null, true, false);
}
}
private class MyDeleteAsyncTask extends AsyncTask<Void, Void, Boolean> {
// Second AsyncTask
private MyActivity context;
private MyProgressDialog dialog;
private long id;
public MyDeleteAsyncTask(MyActivity context, long id) {
super();
this.context = context;
this.id = id;
}
#Override
protected Boolean doInBackground(Void... voids) {
return MyApplication.getSqliteOpenHelper().deleteSomething(id);
}
#Override
protected void onPostExecute(Boolean result) {
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
if (result) {
context.doRefresh();
}
context.deleteTask = null;
}
#Override
protected void onPreExecute () {
dialog = MyProgressDialog.show(context, null, null, true, false);
}
}
private MyDeleteAsyncTask deleteTask;
private MyLoadAsyncTask loadTask;
#Override
public void onCreate(Bundle bundle) {
// ...
// What Task is returned by getLastNonConfigurationInstance()?
// ...
// xxxTask = (MyXxxAsyncTask) getLastNonConfigurationInstance();
// ...
if (deleteTask != null) {
deleteTask.context = this;
deleteTask.dialog = MyProgressDialog.show(this, null, null, true, false);
} else if (loadTask != null) {
loadTask.context = this;
loadTask.dialog = MyProgressDialog.show(this, null, null, true, false);
} else {
loadTask = new MyLoadAsyncTask(this);
loadTask.execute();
}
}
#Override
public Object onRetainNonConfigurationInstance() {
if (deleteTask != null) {
if (deleteTask.dialog != null) {
deleteTask.dialog.dismiss();
deleteTask.dialog = null;
return deleteTask;
}
} else if (loadTask != null) {
if (loadTask.dialog != null) {
loadTask.dialog.dismiss();
loadTask.dialog = null;
return loadTask;
}
return null;
}
}
In your onCreate() add:
Object savedInstance = getLastNonConfigurationInstance();
if(savedInstance instanceof MyDeleteAsyncTask){
//it's a MyDeleteAsyncTask
}else if(savedInstance instanceof MyLoadAsyncTask){
//it's a MyLoadAsyncTask
}
I've found that the best way to deal with activities that have multiple running AsyncTasks inside of them is to actually return an object that contains all of the running ones and automatically reinitialize all of their contexts in onCreate(). E.g.
private class AsyncTaskList() {
List<ActivityTask> tasks; //interface all of your AsyncTasks implement
public void addTask() { /* add to list*/ }
public void completeTask { /* remove from list */ }
public void attachContext(Activity activity) {
for ( ActivityTask task : tasks) {
//You can also check the type here and do specific initialization for each AsyncTask
task.attachContext(activity);
}
}
}
public void onCreate(Bundle bundle) {
AsyncTaskList taskList = (AsyncTaskList) getLastNonConfigurationInstance();
if (taskList != null) {
taskList.attachContext(this);
}
...
}
Now you just need to add and remove the tasks when they start/finish.

Categories