I am working on Android. I want to extract comments from a web page using jsoup library. I am doing in this way. But could not do that. Can anyone help?
public void fun() {
Document doc = null;
try {
doc = Jsoup.connect("http://tribune.com.pk/story/1164751/federal-govt-dodged-chinese-govt-cpec/").timeout(10 * 1000).get();
} catch (IOException e) {
e.printStackTrace();
}
Elements pa = doc.getElementsByClass("span-12 last");
int count = 1;
for (Element iter : pa) {
System.out.println( iter.text());
count = count + 1;
}
}
You have 2 issues here:
Your program closes because the server expects to get a userAgent string and returns you a 403 error.
The comments are located under the "li-comment" class.
This code works for me:
Document doc = null;
try {
doc = Jsoup.connect("http://tribune.com.pk/story/1164751/federal-govt-dodged-chinese-govt-cpec/").timeout(10 * 1000)
.userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0")
.get();
} catch (IOException e) {
e.printStackTrace();
}
Elements el = doc.getElementsByClass("li-comment");
for (Element e : el) {
System.out.println(e.text());
System.out.println("-----------------");
}
You should also handle the case that li-comment is emtpy or does not exist, in case that there are no comments on the page.
on button click i used this..
public void fetchData(View v) {
Toast.makeText(getApplicationContext(),
"Data is fetching from The Hindu wait some time ",
Toast.LENGTH_LONG).show();
new Thread(new Runnable() {
#Override
public void run() {
try {
// get the Document object from the site. Enter the link of
// site you want to fetch
/*
* Document document = Jsoup.connect(
* "http://javalanguageprogramming.blogspot.in/") .get();
*/
Document document = Jsoup.connect(
"http://www.thehindu.com/").get();
title = document.text().toString();
// Get the title of blog using title tag
/* title = document.select("h1.title").text().toString(); */
// set the title of text view
// Get all the elements with h3 tag and has attribute
// a[href]
/*
* Elements elements = document.select("div.post-outer")
* .select("h3").select("a[href]"); int length =
* elements.size();
*/
Elements elements = document.select("div.fltrt")
.select("h3").select("a[href]");
int length = elements.size();
for (int i = 0; i < length; i++) {
// store each post heading in the string
posts += elements.get(i).text();
}
// Run this on ui thread because another thread cannot touch
// the views of main thread
runOnUiThread(new Runnable() {
#Override
public void run() {
// set both the text views
titleText.setText(title);
postText.setText(posts);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
Related
I am in the midst of developing a mobile application using Xamarin.Forms. The app connects to a BLE device which transmits 16 bytes of data every 100 ms. I am plotting the data with Syncfusion in a bar chart format.
I can connect to the device and receive data without issues. But after a very small amount of time, the app starts to significantly decrease in performance. Soon hereafter, it completely stalls. Obviously I am doing something wrong in handling the incoming data (unless it is a performance issue with the Syncfusion chart).
In a nutshell, this is the process I go through in the app
Pair to the device (outside of the app)
Connect to the device (in the app)
Set up the transmission
Process the incoming data via a Model called SpectrogramModel
Graph the data with Syncfusion in a View called DataPage, which is bound to a ViewModel called DataViewModel
Getting into the nitty-gritty of it all, after pairing and connecting to the device, the following method is called. Could it be the Device.BeginInvokeOnMainThread() call which eventually starts blocking the app? This method is called from a Connection class, which has a reference to the DataViewModel
private void UpdateSpectrogramChart(object sender, EventArgs e)
{
DebugHelper.Message(Type.Method, "UpdateSpectrogramChart");
_characteristic.ValueUpdated += (o, args) =>
{
var raw = args.Characteristic.Value;
for (int i = 0; i < raw.Length; i++)
{
Debug.WriteLine("Level[{0}] = {1}", i, raw[i]);
}
Xamarin.Forms.Device.BeginInvokeOnMainThread(() =>
{
DataPageViewModel.Levels.Clear();
for (int i = SpectrogramModel.FrequencyOffset; i < raw.Length; i++)
{
if (SettingsViewModel.IsViewRawData)
{
DataPageViewModel.Title = "Raw data";
DataPageViewModel
.Levels
.Add(
new SpectrogramModel(
raw[i],
1 + (i - SpectrogramModel.FrequencyOffset))
);
}
if (SettingsViewModel.IsViewProcessedData)
{
DataPageViewModel.Title = "Processed data";
DataPageViewModel
.Levels
.Add(
new SpectrogramModel(
raw[i],
1 + (i - SpectrogramModel.FrequencyOffset),
i));
}
}
});
};
}
The SpectrogramModel looks like this
public class SpectrogramModel
{
public SpectrogramModel(byte level, int frequency)
{
Level = level;
Frequency = frequency;
}
public SpectrogramModel(byte level, int frequency, int index) : this(level, frequency)
{
Level = ProcessRawLevel(level, index);
}
private double ProcessRawLevel(byte b, int index)
{
double multiplier = 0.75;
double val = b;
val *= multiplier;
return val;
}
public static readonly int FrequencyOffset = 4;
...
The DataPage looks like this
<chart:SfChart>
<chart:SfChart.Title>
<chart:ChartTitle
Text="{Binding Title}">
</chart:ChartTitle>
</chart:SfChart.Title>
<chart:SfChart.PrimaryAxis>
<chart:CategoryAxis>
</chart:CategoryAxis>
</chart:SfChart.PrimaryAxis>
<chart:SfChart.SecondaryAxis>
<chart:NumericalAxis
Minimum="20"
Maximum="100">
</chart:NumericalAxis>
</chart:SfChart.SecondaryAxis>
<chart:SfChart.Series>
<chart:ColumnSeries ItemsSource="{Binding Levels}" XBindingPath="Frequency" YBindingPath="Level"/>
</chart:SfChart.Series>
</chart:SfChart>
Finally, the DataViewModel which the DataPage is bound
public class DataViewModel : BaseViewModel
{
public DataViewModel()
{
Init();
}
private void Init()
{
Levels = new ObservableCollection<SpectrogramModel>();
for (int i = 0; i < 16; i++) Levels.Add(new SpectrogramModel(20, i));
}
private ObservableCollection<SpectrogramModel> _levels;
public ObservableCollection<SpectrogramModel> Levels
{
get { return _levels; ; }
set
{
_levels = value;
OnPropertyChanged();
}
}
private string _title;
public string Title
{
get { return _title; }
set
{
_title = value;
OnPropertyChanged();
}
}
}
It should be noted that the UpdateSpectrogramChart() is wrapped in a timer, which looks like this
public void InitTimers()
{
DebugHelper.Message(Type.Method, "InitTimers");
int SECOND = 1000 * 2;
SpectrogramChartTimer = new Timer();
SpectrogramChartTimer.Elapsed += new ElapsedEventHandler(UpdateSpectrogramChart);
SpectrogramChartTimer.Interval = SECOND;
}
I wrapped the call to the UpdateSpectrogramChart() method in a (clear) failed attempt to reduce the performance decrease.
For completeness sake, here is the method body of the method which sets up receiving from the BLE device
public async Task ReceiveFromGattCharacteristic(string service, string characteristic, string descriptor = null)
{
DebugHelper.Message(Type.Method, "ReceiveFromGattCharacteristic");
bleAdapter.DeviceConnected += async (s, e) =>
{
try
{
DebugHelper.Message(Type.Info, "bleAdapter.DeviceConected += async (s, e) ...");
string[] deviceInfo = { e.Device.Name, e.Device.Id.ToString() };
// Connect to service
try
{
DebugHelper.Message(Type.Info, "Connecting to service...");
_service = await e.Device.GetServiceAsync(Guid.Parse(service));
DebugHelper.Message(Type.Info, "OK");
}
catch (Exception)
{
DebugHelper.Error(ErrorType.GATT, "Could not connect to service");
}
// Connect to characteristic
try
{
DebugHelper.Message(Type.Info, "Connecting to characteristic...");
_characteristic = await _service.GetCharacteristicAsync(Guid.Parse(characteristic));
DebugHelper.Message(Type.Info, "OK");
}
catch (Exception)
{
DebugHelper.Error(ErrorType.GATT, "Could not connect to characteristic");
}
await ConfigureSpectrogram(UpdateFrequency.High, 0x1);
try
{
await _characteristic.StartUpdatesAsync();
}
catch
{
DebugHelper.Error(ErrorType.GATT, "Error starting UpdatesAsync");
}
_characteristic.ValueUpdated += (o, args) =>
{
var raw = args.Characteristic.Value;
for (int i = 4; i < raw.Length; i++)
{
Debug.WriteLine("Level[{0}] = {1}", i - 4, raw[i]);
}
};
}
catch (Exception)
{
DebugHelper.Error(ErrorType.GATT, "Error in ReceiveFromGattCharacteristic");
}
};
}
Well, I am not sure if this really qualifies as an answer but I seem to have solved the problem although I can't say for sure why this has solved it.
After fiddling with a BackgroundWorker, which introduced even more errors (probably because I am no expert on the usage of it), I revised the code and moved the update of the Model and the View directly into the ReceiveFromGattCharacteristic(), method instead of updating the Model and the View in a separate method, as follows:
public void ReceiveFromGattCharacteristic(string service, string characteristic, string descriptor = null)
{
DebugHelper.Message(Type.Method, "ReceiveFromGattCharacteristic");
bleAdapter.DeviceConnected += async (s, e) =>
{
try
{
DebugHelper.Message(Type.Info, "bleAdapter.DeviceConected += async (s, e) ...");
string[] deviceInfo = { e.Device.Name, e.Device.Id.ToString() };
// Connect to service
try
{
DebugHelper.Message(Type.Info, "Connecting to service...");
_service = await e.Device.GetServiceAsync(Guid.Parse(service));
DebugHelper.Message(Type.Info, "OK");
}
catch (Exception)
{
DebugHelper.Error(ErrorType.GATT, "Could not connect to service");
}
// Connect to characteristic
try
{
DebugHelper.Message(Type.Info, "Connecting to characteristic...");
_characteristic = await _service.GetCharacteristicAsync(Guid.Parse(characteristic));
DebugHelper.Message(Type.Info, "OK");
}
catch (Exception)
{
DebugHelper.Error(ErrorType.GATT, "Could not connect to characteristic");
}
await ConfigureSpectrogram(UpdateFrequency.High, 0x1);
try
{
await _characteristic.StartUpdatesAsync();
}
catch
{
DebugHelper.Error(ErrorType.GATT, "Error starting UpdatesAsync");
}
// ADDITION
_characteristic.ValueUpdated += (o, args) =>
{
var raw = args.Characteristic.Value;
Xamarin.Forms.Device.BeginInvokeOnMainThread(() =>
{
DataPageViewModel.Levels.Clear();
for (int i = Models.Spectrogram.FrequencyOffset; i < raw.Length; i++)
{
if (SettingsViewModel.IsViewRawData)
{
DataPageViewModel.Title = "Raw data";
DataPageViewModel
.Levels
.Add(
new Models.Spectrogram(
raw[i],
1 + (i - Models.Spectrogram.FrequencyOffset))
);
}
if (SettingsViewModel.IsViewProcessedData)
{
DataPageViewModel.Title = "Processed data";
DataPageViewModel
.Levels
.Add(
new Models.Spectrogram(
raw[i],
1 + (i - Models.Spectrogram.FrequencyOffset),
i));
}
}
});
};
}
// END OF ADDITION
catch (Exception)
{
DebugHelper.Error(ErrorType.GATT, "Error in ReceiveFromGattCharacteristic");
}
};
}
We would like to let you know that some of the SfChart configuration need to consider while using huge amount of data and increasing the performance.
Make use of SuspendSeriesNotification and ResumeSeriesNoification.
We can stop the chart from being updated for each modification in the items source collection. By using SuspendSeriesNotification and ResumeSeriesNotification methods.
Xamarin.Forms.Device.BeginInvokeOnMainThread(() =>
{
DataPageViewModel.Levels.Clear();
Chart.SuspendSeriesNotification();
for (int i = SpectrogramModel.FrequencyOffset; i < raw.Length; i++)
{
if (SettingsViewModel.IsViewRawData)
{
DataPageViewModel.Title = "Raw data";
DataPageViewModel
.Levels
.Add(
new SpectrogramModel(
raw[i],
1 + (i - SpectrogramModel.FrequencyOffset))
);
}
if (SettingsViewModel.IsViewProcessedData)
{
DataPageViewModel.Title = "Processed data";
DataPageViewModel
.Levels
.Add(
new SpectrogramModel(
raw[i],
1 + (i - SpectrogramModel.FrequencyOffset),
i));
}
}
Chart.ResumeSeriesNotification();
});
Avoid use of Category Axis.
We have figured that you are using Category axis with column series. We always suggested to use Numeric or datetime axis with fast line series to get better performance. If you really need the category axis and column series, please let us know how many data your chart will load or any reason to use of category axis.
Some of the tips to get better performance from SfChart, please read the below blog.
https://blog.syncfusion.com/post/7-tips-to-optimize-xamarin-charts-performance.aspx#comment-10677
Regards,
Bharathi.
I'm trying to extract the football fixtures from this Webpage. Right now I've this code for extracting the fixtures from the table of that webpage.
private class LoadFixtures extends AsyncTask<Void,Void,Void> {
String stringDT="",stringHome="",stringAway="";
String url = "http://www.bbc.com/sport/football/spanish-la-liga/fixtures";
String stringTime="";
#Override
protected Void doInBackground(Void... params) {
Document doc = null;
try {
doc = Jsoup.connect(url).timeout(0).get();
Elements matchDetails = doc.select("td.match-details");
Elements ele_hTeam = matchDetails.select("span.team-home.teams");
Elements ele_aTeam = doc.select("span.team-away.teams");
Elements ele_time = doc.select("td.kickoff");
int tsize = ele_hTeam.size();
for(int i=0;i<tsize;i++) {
stringTime+="\n\n"+ele_time.get(i).text();
stringHome+="\n\n"+ele_hTeam.get(i).text();
stringAway+="\n\n"+ele_aTeam.get(i).text();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
homeTeam.setText(stringHome);
awayTeam.setText(stringAway);
timeView.setText(stringTime);
super.onPostExecute(aVoid);
}
}
This code gives me the whole list of fixtures, but what i want to do is just extract the fixtures of specific date. For example, lets say i want to extract the fixtures only from Saturday 16th January 2016
The code below will do as you ask. I have simply supplied a String variable with the date you are looking up. The code below loops on each table on the page. Each table will contain x number of fixtures. If the tables caption contains the date you have provided it will enter this table and allow you to select the home team and the away team. Hope this helps!
String dateLookup= "16th January 2016";
String url = "http://www.bbc.com/sport/football/spanish-la-liga/fixtures";
try {
Document document = Jsoup.connect(url).timeout(0).get();
Elements tableElements = document.select("table.table-stats");
for (Element e : tableElements) {
if (e.select("caption").text().contains(dateLookup)) {
Elements matchElements = e.select("tr.preview");
for (Element match : matchElements) {
System.out.println("Home Team: " + match.select("span.team-home").text());
System.out.println("Away Team: " + match.select("span.team-away").text() + "\n");
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
I have list of web pages(over 100) with I have to vistit and collect data from.
I decided to save the html from all of them to one file, and then use Jsoup to find the interesting data.
But problem is to I do not know how to run 100 threads, and save the responses into one file, any ideas?
maybe it's not a masterpiece, but it works, and I wanted to make it as simple as possible.
ArrayList<String> links = new ArrayList<>();
Elements myDiv;
private void saveDetails() throws IOException {
if(repeat < links.size()){
repeat++;
textView.setText(String.valueOf(repeat));
saveFile(myDiv.toString());
myDiv = null;
getDetails(links.get(repeat));
}else {
textView.setText("finished");
}
}
private void getDetails(String urlStr) {
final String detailsUrl = urlStr;
new Thread() {
#Override
public void run() {
Message msg = Message.obtain();
try {
Document doc = Jsoup.connect(detailsUrl).get();
myDiv = doc.select(".exhibitor-contact");
} catch (IOException e1) {
e1.printStackTrace();
}
detailsHandler.sendMessage(msg);
}
}.start();
}
private Handler detailsHandler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
try {
saveDetails();
} catch (IOException e) {
e.printStackTrace();
}
}
};
You don't need to save all of them in a file and then process them. You can gather information one by one. It is my suggestion:
arrayList urls = {100 site-url}; //in correct syntax
Document doc = null;
for (String url : urls) {
doc = Jsoup.connect(url).get();
//now proccess doc.toString as you want(in regular expression for example)
//save your desired information
}
Hi I am very new to Android and I am having some issues with putting the username (retrieved by using the web services) into the Action bar.
The problem is that the username is not displayed and is shown as 'null' when I first enter the page that I want to show the username in. It is only displayed when the page is loaded the second time (i.e. it is only displayed when I go to another page and then come back to the page that I want to display the username in).
I would like the username to be displayed in the action bar even when the page is loaded the first time, but I have no idea what the problem is.
Can someone please help me to solve this issue?
Thank you very much in advance.
Here is my code:
In the 'menu', I have added in an item with android:actionViewClass="android.widget.TextView":
<item
android:id="#+id/viewusername"
android:orderInCategory="1"
android:title="#+id/viewusername"
android:showAsAction="always"
android:actionViewClass="android.widget.TextView"/>
To put the username inside the actionbar, I have used the onPrepareOptionsMenu method:
#Override
public boolean onPrepareOptionsMenu(Menu menu)
{
MenuItem menuItem = menu.findItem(R.id.viewusername);
TextView showusername1 = (TextView) menuItem.getActionView();
showusername1.setText(String.valueOf(username) );
return super.onPrepareOptionsMenu(menu);
}
This is the method that I used to retrieve the username from the web services (I have used an EventHandler):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_dashboard);
Button incident = (Button) findViewById(R.id.CreateNewIncidentButton);
SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", 0); // 0 - for private mode
Editor editor = pref.edit();
Bundle extras = getIntent().getExtras();
if (extras != null) {
name = extras.getString("ID");
}
incident.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Switching to Register screen
Intent i = new Intent(getApplicationContext(), CreateIncident.class);
startActivity(i);
}
});
Button request = (Button) findViewById(R.id.CreateNewRequestButton);
request.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Switching to Create new request screen
Intent i = new Intent(getApplicationContext(), CreateRequest.class);
startActivity(i);
}
});
Button queue = (Button) findViewById(R.id.ViewMyTicketsButton);
queue.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Switching to Register screen
Intent i = new Intent(getApplicationContext(), ViewMyTickets.class);
startActivity(i);
}
});
getUsersName();
}
public void getUsersName() {
methodName ="getUsersCombo";
VectorString getUsersCombo = new VectorString(); //creates a new instance of VectorString
String[] usersCom = { "combo_name"}; //array of values
for (String s : usersCom) { //adds strings to getTicketInfo
getUsersCombo.add(s);
}
EventHandlerDashboard handler2 = new EventHandlerDashboard(this);
USD_WebService usdw2 = new USD_WebService(handler2,"http://dsl-116040f.datacom.co.nz:8080/axis/services/USD_R11_WebService?WSDL",60);
SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", 0); // 0 - for private mode
Editor editor = pref.edit();
int usersSid = pref.getInt("sid",0);
String username = pref.getString("username","");
try {
//adds all the values to the web service call
usdw2.doSelectAsync(usersSid, "cnt", "userid="+"'"+username+"'", -1, getUsersCombo);
} catch (Exception e) {
e.printStackTrace();
}
}
public void receiveResults(String result7){
try {
DocumentBuilderFactory dbf =
DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(result7));
Document doc = db.parse(is);
NodeList nodes = doc.getElementsByTagName("UDSObject");
// iterate the employees
for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);
NodeList name = element.getElementsByTagName("AttrName");
Element line = (Element) name.item(0);
System.out.println("ID: " + getCharacterDataFromElement(line));
NodeList title = element.getElementsByTagName("AttrValue");
line = (Element) title.item(0);
System.out.println("ID Value: " + getCharacterDataFromElement(line));
userID = getCharacterDataFromElement(line);
username= "Welcome, "+userID;
}
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println("users comboname"+result7);
}
public static String getCharacterDataFromElement(Element e) {
Node child = e.getFirstChild();
if (child instanceof CharacterData) {
CharacterData cd = (CharacterData) child;
return cd.getData();
}
return "?";
}
Note: this method works perfectly fine when it is used in the TextView of the layout but it has issues when I try to use it in the action bar.
Update:
It works now:
#Override
public boolean onPrepareOptionsMenu(Menu menu)
{
MenuItem menuItem = menu.findItem(R.id.viewusername);
TextView showusername1 = (TextView) menuItem.getActionView();
showusername1.setText(usersname==null?"":String.valueOf(usersname) );
return super.onPrepareOptionsMenu(menu);
}
And
getUsersName();
}
public void getUsersName() {
methodName ="getUsersCombo";
VectorString getUsersCombo = new VectorString(); //creates a new instance of VectorString
String[] usersCom = { "combo_name"}; //array of values
for (String s : usersCom) { //adds strings to getTicketInfo
getUsersCombo.add(s);
}
EventHandlerDashboard handler2 = new EventHandlerDashboard(this);
USD_WebService usdw2 = new USD_WebService(handler2,"http://dsl-116040f.datacom.co.nz:8080/axis/services/USD_R11_WebService?WSDL",60);
SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", 0); // 0 - for private mode
Editor editor = pref.edit();
int usersSid = pref.getInt("sid",0);
username = pref.getString("username","");
try {
//adds all the values to the web service call
usdw2.doSelectAsync(usersSid, "cnt", "userid="+"'"+username+"'", -1, getUsersCombo);
} catch (Exception e) {
e.printStackTrace();
}
}
public void receiveResults(String result7){
try {
DocumentBuilderFactory dbf =
DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(result7));
Document doc = db.parse(is);
NodeList nodes = doc.getElementsByTagName("UDSObject");
// iterate the employees
for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);
NodeList name = element.getElementsByTagName("AttrName");
Element line = (Element) name.item(0);
System.out.println("ID: " + getCharacterDataFromElement(line));
NodeList title = element.getElementsByTagName("AttrValue");
line = (Element) title.item(0);
System.out.println("ID Value: " + getCharacterDataFromElement(line));
userID = getCharacterDataFromElement(line);
usersname = "Welcome, "+userID;
}
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println("users comboname"+result7);
invalidateOptionsMenu(); // This works on Android 3.x devices only
}
public static String getCharacterDataFromElement(Element e) {
Node child = e.getFirstChild();
if (child instanceof CharacterData) {
CharacterData cd = (CharacterData) child;
return cd.getData();
}
return "?";
}
Call invalidateOptionsMenu() once you retrieve your username to force calling onPrepareOptionsMenu()
Also when you're calling String username = pref.getString("username",""); you are creating a local variable. And on your onPrepareOptionsMenu you seem to be using a field instead. Remove "String" from your declaration so you use your field instead of your variable.
From what I've seen your username is loaded at getUsersName();. So it's safe to say that after this line the field username is populated with the real username. Call invalidateOptionsMenu(); to force the activity to create the optionsMenu again. This will call onPrepareOptionsMenu() again and will populate the TextView with the username.
I think it could be because you are making an async call the webserver to retrieve the data. This means that while that call gets handled in the async thread, the lifecycle of the app continues and onPrepareOptionsMenu gets called before the username variable gets populated. So, when onPrepareOptionsMenu is called, username is still "".
You could try making the async thread through a AsyncTask instead. AsyncTask will allow you to perform some operation on the UI thread after the data is returned from the web server on its onPostExecute method.
You can use onPostExecute to modify the action bar. You could be showing some sort of loader on the action bar for as long as the data is not returned from the webserver. When it is, then the 'onPostExecute' will update the acrion bar. This also allows you to catch any failure that you might encounter in fetching data from the webserver (low/no internet connection, disconnected server and what not) and advise your user that "you couldn't retrieve his username at the moment". You could do this by catching network exception or/and by putting a timer on the request.
Here are some links to guide you through this:
AsyncTask explained
AsyncTask example (Vogella)
When trying to add words to a database via php, only the first word of both strings gets added.
I send the text via this code:
public void sendTextToDB() {
valcom = editText1.getText().toString();
valnm = editText2.getText().toString();
t = new Thread() {
public void run() {
try {
url = new URL("http://10.0.2.2/HB/hikebuddy.php?function=setcomm&comment="+valcom+"&name="+valnm);
h = (HttpURLConnection)url.openConnection();
if( h.getResponseCode() == HttpURLConnection.HTTP_OK){
is = h.getInputStream();
}else{
is = h.getErrorStream();
}
h.disconnect();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("Test", "CONNECTION FAILED 1");
}
}
};
t.start();
}
When tested with spaces and commas etc. in a browser, the php function adds all text.
The strings also return the full value when inserted into a dialog.
How do I fix this?
Thank you.
You need to URL-encode valcom and valnm when putting them into the URL.
See java.net.URLEncoder.encode: http://developer.android.com/reference/java/net/URLEncoder.html
url = new URL("http://10.0.2.2/HB/hikebuddy.php?function=setcomm&comment="
+ URLEncoder.encode(valcom)
+ "&name="+ URLEncoder.encode(valnm));