Been on the same problem for too many hours, so I figured why not ask the stackoverflow community.
I have implemented twitter it works fine if the orientation is in portrait. If I would turn the phone in landscape during the async call it crashes. I have seen a few examples of this issue and have tried a few of them. locking the screen is not a solution.
I'll try to post a snippet of the code. maybe someone can give me a tip. Thanks
Logcat Error
12-03 16:43:01.650 18351-18351/com.example.admin.football E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at com.example.admin.football.fragments.TwitterFragment.onTaskFinished(TwitterFragment.java:94)
at com.example.admin.football.fragments.TwitterFragment$DownloadTwitterTask.onPostExecute(TwitterFragment.java:193)
at com.example.admin.football.fragments.TwitterFragment$DownloadTwitterTask.onPostExecute(TwitterFragment.java:171)
at android.os.AsyncTask.finish(AsyncTask.java:631)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4797)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
at dalvik.system.NativeStart.main(Native Method)
Java code:
public TwitterFragment()
{
}
#Override
public void onTaskStarted() {
isTaskRunning = true;
load(listView);
}
// converts a string of JSON data into a Twitter object
private Twitter jsonToTwitter(String result) {
Twitter twits = null;
if (result != null && result.length() > 0) {
try {
Gson gson = new Gson();
twits = gson.fromJson(result, Twitter.class);
} catch (IllegalStateException ex) {
// just eat the exception
}
}
return twits;
}
#Override
public void onTaskFinished(String result) {
if (spinner != null) {
final Twitter twits = jsonToTwitter(result);
if(twits!=null) {
// lets write the results to the console as well
for (Tweet tweet : twits) {
Log.i(LOG_TAG, tweet.getText());
}
cardArrayAdapter = new CardArrayAdapter(getActivity().getApplicationContext(), R.layout.list_item_card);
for (int i = 0; i < twits.size(); i++) {
String dt = twits.get(i).getDateCreated();
Card card = new Card(twits.get(i).getUser().getProfileImageUrl(), twits.get(i).getUser().getScreenName(), twits.get(i).toString(), dt.substring(0, 10));
cardArrayAdapter.add(card);
}
listView.setAdapter(cardArrayAdapter);
/*cardArrayAdapter.getFilter().filter(Hashtag, new Filter.FilterListener() {
#Override
public void onFilterComplete(int count) {
listView.setAdapter(cardArrayAdapter);
}
});*/
spinner.setVisibility(View.GONE);
}
spinner.setVisibility(View.GONE);
}
isTaskRunning = false;
}
#Override
public void onDetach() {
// All dialogs should be closed before leaving the activity in order to avoid
// the: Activity has leaked window com.android.internal.policy... exception
if (spinner != null) {
spinner.setVisibility(View.GONE);
}
super.onDetach();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// If we are returning here from a screen orientation
// and the AsyncTask is still working, re-create and display the
// progress dialog.
if (isTaskRunning) {
load(listView);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.fragment_twitter, container, false);
listView = (ListView) rootView.findViewById(R.id.card_listView);
spinner = (ProgressBar)rootView.findViewById(R.id.progressBar1);
spinner.setVisibility(View.GONE);
listView.addHeaderView(new View(getActivity()));
listView.addFooterView(new View(getActivity()));
// call method to download tweets
downloadTweets();
return rootView;
}
public void load(View view){
spinner.setVisibility(View.VISIBLE);
}
// download twitter timeline after first checking to see if there is a network connection
public void downloadTweets() {
ConnectivityManager connMgr = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
load(listView);
new DownloadTwitterTask(this).execute(ScreenName);
} else {
Log.v(LOG_TAG, "No network connection available.");
}
}
// Uses an AsyncTask to download a Twitter user's timeline
//TODO cancel this when view is changed!
public class DownloadTwitterTask extends AsyncTask<String, Void, String> {
private final TaskListener listener;
final static String CONSUMER_KEY = "";
final static String CONSUMER_SECRET = "";
final static String TwitterTokenURL = "https://api.twitter.com/oauth2/token";
final static String TwitterStreamURL = "https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=";
public DownloadTwitterTask(TaskListener listener) {
this.listener = listener;
}
#Override
protected String doInBackground(String... screenNames) {
String result = null;
if (screenNames.length > 0) {
result = getTwitterStream(screenNames[0]);
}
return result;
}
// onPostExecute convert the JSON results into a Twitter object (which is an Array list of tweets
#Override
protected void onPostExecute(String result) {
listener.onTaskFinished(result);
}
// convert a JSON authentication object into an Authenticated object
private Authenticated jsonToAuthenticated(String rawAuthorization) {
Authenticated auth = null;
if (rawAuthorization != null && rawAuthorization.length() > 0) {
try {
Gson gson = new Gson();
auth = gson.fromJson(rawAuthorization, Authenticated.class);
} catch (IllegalStateException ex) {
// just eat the exception
}
}
return auth;
}
Well even if somebody gave a solution i want to try to give a better one.
Using configChanges won't let your application to reload resources when the screen is rotated, this means that if you are using different layouts or other resources for landscapes and portaits they will be totally unuseful.
You should call your AsyncTask from a fragment and use the setRetainInstance(true) method, here you will find a good explanation on how to do it.
Add this line in your Activity entry in Manifest:
android:configChanges="layoutDirection|keyboardHidden|orientation|screenSize|screenLayout"
Related
I am fetching data from database. My views are updating only first time when I open the activity. Then when I again open the activity, my views are not updated.(Activity is starting again, hence onCreate() is called again & all settings are same). If I getText() after setting the text, I am getting proper values in log but nothing is displayed in view.
Here is my code snippet:
//My Call Back method
#Override
public void onRatingDataLoaded(ReviewJsonModel review) {
int ratingCount = 0, ownRating = 0;
String averageRating = "0";
if (review != null) {
ratingCount = review.review_count;
DecimalFormat format = new DecimalFormat("##.00");
averageRating = format.format(review.rating);
if (review.ownreviews != null) {
try {
ownRating = Integer.parseInt(review.ownreviews.rating);
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
} else {
// do something
}
mTotalRatingCount.setText(String.format(getResources().getString(R.string.review_count), ratingCount));
mAverageRating.setText(averageRating);
// Log.v("LoggingReview", mTotalRatingCount.getText().toString().trim);
myRating.setRating(ownRating);
}
//Here I am setting listner as well as loading data.
public void loadReviewData(RatingDataLoadListener listener, int destinationId) {
if (mDataLoadListener == null)
mDataLoadListener = listener;
new getReviews().execute(destinationId);
}
Next is my asyntask
private class getReviews extends AsyncTask<Integer, Void, ReviewJsonModel> {
#Override
protected ReviewJsonModel doInBackground(Integer... integers) {
Cursor appCursor = mRatingApi.getDestinationReview(integers[0]);
ReviewJsonModel mReviewData = new ReviewJsonModel();
if (appCursor != null && appCursor.getCount() > 0) {
appCursor.moveToFirst();
while (!appCursor.isAfterLast()) {
mReviewData = getDocument(appCursor);
appCursor.moveToNext();
}
appCursor.close();
}
return mReviewData;
}
#Override
protected void onPostExecute(ReviewJsonModel result) {
super.onPostExecute(result);
if (mDataLoadListener != null)
mDataLoadListener.onRatingDataLoaded(result);
}
}
Can't find cause of problem. Any help is appreciated.
Looks like there is callback issue, can you please try below
public void loadReviewData(RatingDataLoadListener listener, int destinationId) {
mDataLoadListener = listener;
new getReviews().execute(destinationId);
}
I am trying to execute connected test for P4, however I am reciing an "Null pointer exception error" for P4
Error message:
:00:02 PM null
java.lang.NullPointerException
at com.android.ddmlib.Client.read(Client.java:692)
at com.android.ddmlib.MonitorThread.processClientActivity(MonitorThread.java:304)
at com.android.ddmlib.MonitorThread.run(MonitorThread.java:256)
It is a standard test, verifying non-empty string in the Async task
Test function:
public void runCloudModuleTest() {
String joke = null;
JokesAsyncTask jokesAsyncTask = new JokesAsyncTask(getContext(), null);
jokesAsyncTask.execute();
try {
joke = jokesAsyncTask.get();
Log.d("CloudModuleTest", "Retrieved a non-empty string successfully: " + joke);
} catch (Exception e) {
e.printStackTrace();
}
assertNotNull(joke);
}
Can someone help me understand what the issue is?
AsyncTask: The Async task pulls data from google cloud engine
public class JokesAsyncTask extends AsyncTask, Void, String> {
private static JokeApi myApiService = null;
private Context mContext;
private String mResult;
private ProgressBar mProgressBar;
public JokesAsyncTask(Context context, ProgressBar progressBar) {
this.mContext = context;
this.mProgressBar = progressBar;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
if (mProgressBar != null) {
mProgressBar.setVisibility(View.VISIBLE);
}
}
#Override
protected String doInBackground(Pair<Context, String>... pairs) {
if (myApiService == null) {
JokeApi.Builder builder = new JokeApi.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
.setRootUrl("https://testandroiddevelopment.appspot.com/_ah/api/");
myApiService = builder.build();
}
try {
return myApiService.sendJoke(new JokeBean()).execute().getJoke();
} catch (IOException e) {
return e.getMessage();
}
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (mProgressBar != null) {
mProgressBar.setVisibility(View.GONE);
}
mResult = result;
startJokeDisplayActivity();
}
private void startJokeDisplayActivity() {
Intent intent = new Intent(mContext, JokeViewActivity.class);
intent.putExtra(JokeViewActivity.JOKE_KEY, mResult);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
}
}
I have referenced the variable and it is not an issue due due to the below post, however I did investigate and finally cleaned up and rebuild the project that helped resolved the issue
I have referenced the variable and it is not an issue due due to the post #AxelH, however I did investigate and finally cleaned up and rebuild the project that helped resolved the issue
I have called an async task from my button click.In the doInBackground I have called an API and It is returning me a Json object.I want to pass the Json object to another activity on the button click.How can I can get the return Json object value so that I can send it to other activity.
Thanks.
Create Interface
public interface Listener {
void success(BaseModel baseModel);
void fail(String message);
}
Create Base model class
public class BaseModel implements Serializable {
private static final long serialVersionUID = 1L;
}
Call below method inside your onClick mehtod.
protected void userLoginData(final String userName) {
// if you want to pass multiple data to server like string or json you can pass in this constructor
UserLoginLoader userLoginLoader = new UserLoginLoader(LoginActivity.this, userName, "1234567899", new Listener() {
#Override
public void success(BaseModel baseModel) {
// here you got response in object you can use in your activity
UserLoginModel userLoginModel = (UserLoginModel) baseModel;
// you can get data from user login model
}catch(Exception exception){
exception.printStackTrace();
Utils.showAlertDialog(LoginActivity.this, "Server is not responding! Try Later.");
}
}
#Override
public void fail(String message) {
}
});
userLoginLoader.execute();
}
:- User Login Loader class
public class UserLoginLoader extends AsyncTask<String, Void, Boolean> {
private Dialog dialog;
private Listener listner;
private String deviceId;
Activity activity;
String message;
String userName;
boolean checkLoginStatus;
public UserLoginLoader(Activity activity,String userName, String deviceId, Listener listener) {
this.listner = listener;
this.userName =userName;
this.activity = activity;
this.deviceId = deviceId;
}
#Override
protected Boolean doInBackground(String... arg0) {
//User login web service is only for making connection to your API return data into message string
message = new UserLoginWebService().getUserId(userName, deviceId);
if (message != "null" && !message.equals("false")) {
return true;
}
return false;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new Dialog(activity, R.style.CustomDialogTheme);
dialog.setContentView(R.layout.progress);
dialog.setCancelable(false);
dialog.show();
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
BaseModel baseModel = null;
if (!message.equals("null") && (!message.equals("false")) )
baseModel = parseData(message, result);
if (dialog.isShowing()) {
dialog.dismiss();
dialog.cancel();
dialog = null;
}
if (listner != null) {
if (result && baseModel != null)
listner.success(baseModel);
else
listner.fail("Server not responding! Try agian.");
} else
listner.fail("Server not responding! Try agian.");
}
//call parser for parsing data return data from the parser
private BaseModel parseData(String responseData, Boolean success) {
if (success == true && responseData != null
&& responseData.length() != 0) {
UserLoginParser loginParser = new UserLoginParser(responseData);
loginParser.parse();
return loginParser.getResult();
}
return null;
}
}
This is you Login parser class
public class UserLoginParser {
JSONObject jsonObject;
UserLoginModel userLoginModel;
/*stored data into json object*/
public UserLoginParser(String data) {
try {
jsonObject = new JSONObject(data);
} catch (JSONException e) {
Log.d("TAG MSG", e.getMessage());
e.printStackTrace();
}
}
public void parse() {
userLoginModel = new UserLoginModel();
try {
if (jsonObject != null) {
userLoginModel.setUser_name(jsonObject.getString("user_name")== null ? "": jsonObject.getString("user_name"));
userLoginModel.setUser_id(jsonObject.getString("user_id") == null ? "" : jsonObject.getString("user_id"));
userLoginModel.setFlag_type(jsonObject.getString("flag_type") == null ? "" : jsonObject.getString("flag_type"));
} else {
return;
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
/*return ship name list which is stored into model */
public UserLoginModel getResult() {
return userLoginModel;
}
}
Write a callback method in the Activity that takes in the argument that you wish to pass from AsyncTask to that Activity. Send reference to the Activity to AysncTask while creating it. From doInBackground() method make a call to this callback method with the data your API returns.
Code would be something like -
public class TestAsyncTask extends AsyncTask<Integer, Integer, String[]> {
Activity myActivity;
public TestAsyncTask(Activity activity) {
this.myActivity = activity;
}
#Override
protected String[] doInBackground(Integer... params) {
String data = yourApi();
myActivity.callback(data);
}
}
public class MyActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
new TestAsyncTask(this).execute(someId);
}
public void callback(String data) {
//process data
}
}
Just for the record you can directly get return value from doInBackground() method by calling get() on it.
String data = new TestAsyncTask(this).execute(someId).get();
But note this may block your UI thread as it will wait for the doInBackground() method to complete it's execution.
My program crashs after doInBackground and doesn't come to onPostExecute.
My activity code's related parts are like this:
public static class News {
private String title;
private String content;
private Bitmap image;
public News(String nTitle, String nContent, Bitmap nImage){
title = nTitle;
content = nContent;
image = nImage;
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_news);
final AsyncTask task = new DatabaseConnection(this, Method.GET_ALL_NEWS).execute();
try {
task.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public final void fillListView(List<News> news){
recentNews = news;
if(recentNews != null && !recentNews.isEmpty()){
((ListView)findViewById(R.id.lvNews)).setOnItemClickListener(this);
final int size = recentNews.size();
final String newsTitles[] = new String[size];
for(int i=0; i<size; ++i)
newsTitles[i] = recentNews.get(i).title;
((ListView)findViewById(R.id.lvNews)).setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, newsTitles));
}
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final News selectedNews = recentNews.get(position);
startActivity(new Intent(this, ANewsActivity.class)
.putExtra("title", selectedNews.title)
.putExtra("content", selectedNews.content)
.putExtra("image", BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher)));
}
My AsyncTask code's related parts are like this:
public DatabaseConnection(Context nContext, Method nMethod){
method = nMethod;
context = nContext;
}
#Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(context);
progressDialog.setMessage(context.getString(R.string.database_connection_wait_message));
progressDialog.setTitle(R.string.database_connection_wait_title);
progressDialog.show();
}
#SuppressWarnings("incomplete-switch")
#Override
protected Void doInBackground(String... params) {
if(method != Method.NONE){
open();
try{
switch(method){
case GET_ALL_NEWS:
final ResultSet rs = conn.createStatement().executeQuery("select baslik, metin, resim from haberler");
news = new ArrayList<News>();
while(rs.next())
news.add(new News(rs.getString(1), rs.getString(2), BitmapFactory.decodeStream(rs.getBlob(3).getBinaryStream())));
break;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
close();
}
}
return null;
}
#SuppressWarnings("incomplete-switch")
#Override
protected void onPostExecute(Void temp) {
if (progressDialog.isShowing()){
progressDialog.dismiss();
switch(method){
case GET_ALL_NEWS:
((NewsActivity)context).fillListView(news);
break;
}
method = Method.NONE;
}
}
I want UI thread waits until database operations finishes.
By the way there is no initialization problem at variables etc and database returns proper infos and my "news" variable is filled normally.
By the way again I realized it is WORKING on PHONE, STUCKS on EMULATOR interestingly (if I remove wait() method and its try-catch block on main thread code).
It's difficult to say what is crashing without the logcat output, but it would most likely be the main thread of the app because of the .wait() method you are calling in onCreate(). Your onCreate() cannot wait - it must initialize and exit, otherwise you are blocking the main thread of your app and defeating the purpose of the AsyncTask.
I am currently creating a project that needs to have a simple async task to take care of a thread running behind the scenes. The user needs to login. I am using another class called PVAndroid Client that supplies useful methods and has an XML serializer form packets for me. I am completely new to working with threads or doing anything with servers, so this may be completely wrong or somewhat right.
I get the data the user entered: the ip address and port, their username (I split this into first and last name), their region they selected. I encrypt their password, and attempt to connect to the tcp using ip address and port number. I am trying to work in the async task but am kind of confused on what I should do. Can anyone guide me in the right direction and help me out?
Thank you I really appreciate it.
private TcpClient myTcpClient = null;
private UdpClient udpClient;
private static final String USERNAME_SHARED_PREFS = "username";
private static final String PASSWORD_SHARED_PREFS = "password";
private static final String IP_ADDRESS_SHARED_PREFS = "ipAddressPref";
private static final String PORT_SHARED_PREFS = "portNumberPref";
private String encryptedNameLoginActivity, encryptPassLoginActivity;
private EditText userText, passText;
private String getIpAddressSharedPrefs, getPortNumberPrefs;
private String getUserNameValue;
private String getPasswordValue;
private String fName, lName;
private SharedPreferences settings;
private Editor myEditor;
private boolean getCheckedRemember;
private boolean resultCheck = false;
private int portNum;
private Button submitButton;
private String userMACVARIABLE = "";
private String regionSelected, gridSelected;
private Spinner regSpinner, gridSpinner;
PVDCAndroidClient client;
private int userNum;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
client = new PVDCAndroidClient();
}
#Override
protected void onStart() {
super.onStart();
// Take care of getting user's login information:
submitButton = (Button) findViewById(R.id.submitButton);
userText = (EditText) findViewById(R.id.nameTextBox);
passText = (EditText) findViewById(R.id.passwordTextBox);
regSpinner = (Spinner) findViewById(R.id.regionSpinner);
// grid selected as well? sometime?
regSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View v,
int position, long rowId) {
regionSelected = regSpinner.getItemAtPosition(position)
.toString();
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
submitButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
settings = PreferenceManager
.getDefaultSharedPreferences(AndroidClientCompnt.this);
getIpAddressSharedPrefs = settings.getString(
IP_ADDRESS_SHARED_PREFS, "");
portNum = Integer.parseInt(settings.getString(
PORT_SHARED_PREFS, ""));
if (getIpAddressSharedPrefs.length() != 0 && portNum != 0) {
if (userText.length() != 0 && passText.length() != 0) {
try {
try {
// encrypting the user's password.
encryptPassLoginActivity = Secure.encrypt(passText
.toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// first connect attempt.
myTcpClient = new TcpClient();
myTcpClient.connect(getIpAddressSharedPrefs,
portNum);
// here is where I want to call Async to do login
// or do whatever else.
UploadTask task = new UploadTask();
task.execute();
} catch (Exception e) {
Toast.makeText(getApplicationContext(),
"Could not connect.", Toast.LENGTH_LONG)
.show();
e.printStackTrace();
}
}
}
}
});
}
private class UploadTask extends AsyncTask<String, Integer, Void>
{
#Override
protected void onPreExecute() {
Toast.makeText(getApplicationContext(), "Loading...",
Toast.LENGTH_LONG).show();
}
#Override
protected Void doInBackground(String... names) {
resultCheck = myTcpClient.connect(getIpAddressSharedPrefs,
portNum);
if (resultCheck == true) {
while (myTcpClient.getUserNum() < 0) {
// num set? session? with proxy server?
}
String[] firstAndLast;
String spcDelmt = " ";
firstAndLast = userText.toString().split(spcDelmt);
fName = firstAndLast[0];
lName = firstAndLast[1];
// set up the tcp client to sent the information to the
// server.
client.login(fName, lName, encryptPassLoginActivity,regionSelected, 128, 128, 20);
} else {
Toast.makeText(getApplicationContext(),
"Connection not successful", Toast.LENGTH_LONG)
.show();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
Toast.makeText(getApplicationContext(), "Connected",
Toast.LENGTH_LONG).show();
}
}
}
First
#Override
protected Void doInBackground(String...params) {
new Thread (new Runnable() {
// ...
}
}
Never do this again. There is no need to create new Thread in doInBackground method which actually running on background Thread. So remove it.
The advice to you is tricky because you need to read about Threads, work with Connection etc. So the best advice to you is to read some tutorials, examples of basic applications and read references. So you can start here:
Android TCP Client and Server Communication Programming–Illustrated with Example
I cannot see, where you are yoursing your Task, but I see that you are doing something weired inside doInBackground()! There is absolutely NO reason, to create your own Thread inside it.
remove that, and you could just use your Task like this:
UploadTask task = new UploadTask();
task.execute("someString", "anotherString", "addAsManyStringsYouNeed");
The docs from AsyncTask are very helpfull, too.