I have the following code inside my MainActivity.java file:
public class MainActivity extends AppCompatActivity {
private static String nodeAddress = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Search For The NodeMCU On The Connected Network
UPnPDiscovery.discoveryDevices(this, new UPnPDiscovery.OnDiscoveryListener() {
#Override
public void OnStart() {
Log.d("UPnP Discovery", "Started Device Discovery");
}
#Override
public void OnFoundNewDevice(UPnPDevice device) {
Log.d("UPnP Discovery", "Found UPnP Device " + device.getManufacturer());
try {
if (device.getManufacturer().equals("Nobody")) {
MainActivity.nodeAddress = device.getHostAddress();
}
} catch (Exception ex) {
Log.e("ERROR", ex.getLocalizedMessage());
}
}
#Override
public void OnFinish(HashSet<UPnPDevice> devices) {
Log.d("UPnP Discovery", "Finished Searching");
TextView tv = (TextView) findViewById(R.id.connectionStatus);
tv.setText(MainActivity.nodeAddress);
}
#Override
public void OnError(Exception e) {
Log.d("UPnP Discovery", "Error While Searching For Devices");
}
});
Log.d("IoT Project", "Value of nodeAddress = " + MainActivity.nodeAddress);
// Channel 1 Event Listeners
final Button ch1OFF = findViewById(R.id.channel1Off);
final Button ch1ON = findViewById(R.id.channel1On);
final Button ch1SENSOR = findViewById(R.id.channel1Sensor);
// Channel 2 Event Listeners
final Button ch2OFF = findViewById(R.id.channel2Off);
final Button ch2ON = findViewById(R.id.channel2On);
final Button ch2SENSOR = findViewById(R.id.channel2Sensor);
// Setting Up OkHTTP To Send Requests Over The Network
OkHttpClient client = new OkHttpClient();
String ch1OffUrl = "http://" + MainActivity.nodeAddress +"/alwaysOFFOne";
String ch2OffUrl = "http://" + MainActivity.nodeAddress +"/alwaysOFFTwo";
String ch1OnUrl = "http://" + MainActivity.nodeAddress +"/alwaysONOne";
String ch2OnUrl = "http://" + MainActivity.nodeAddress +"/alwaysONTwo";
String ch1SensorUrl = "http://" + MainActivity.nodeAddress +"/sensorModeOne";
String ch2SensorUrl = "http://" + MainActivity.nodeAddress +"/sensorModeTwo";
// Setting Event Listeners For Channel 1
ch1OFF.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Log.d("IoT Project", "Sending Request To " + ch1OffUrl);
// Building The OkHTTP Request Instance
Request request = new Request.Builder()
.url(ch1OffUrl)
.build();
// Making The HTTP Call Using The Client Instance
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
String myResponse = response.body().string();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
TextView tv = (TextView) findViewById(R.id.connectionStatus);
tv.setText("Channel 1 OFF");
}
});
}
}
});
}
});
}
}
I am trying to create a variable called nodeAddress outside of the UPnP Discovery inner class, and assign it a value inside the inner class so I can use it outside aswell, like in the onclick events.
However the assignment is only scoped to the inner class, outside of the inner class it stays as null and never works!
It seems that happens, because you're trying to get the value in MainActivity, before setting it in OnFoundNewDevice.
In other word, the OnFoundNewDevice is getting called, sometime after this log message that you have in your activity:
Log.d("IoT Project", "Value of nodeAddress = " + MainActivity.nodeAddress);
after the OnFoundNewDevice gets called, you can use the nodeAddress value on your ClickListeners.
Related
I'm quite a noob to the android and java world so I'm not quite sure what I'm doing wrong here. I have an Artist and Song class like this:
Artist.java
public class Artist {
private int ID;
private String Name;
private String Bio;
private int YearFormed;
#Override
public String toString()
{
return Name;
} }
Song.java
public class Song {
private int ID;
private String Name;
private String Length;
private String Genre;
private String Lyrics;
private int ArtistID;
public String printName()
{
return Name;
}
public String ToString()
{
String toReturn = "ID: " + Integer.toString(ID) + "\nArtist: " + Integer.toString(ArtistID)
+"\nLength: " + Length + "\nGenre: " + Genre;
return toReturn;
} }
In my MainActivity.java file I gave a function to GET request to api/artists and api/songs. The URI is correct and when I visit the API in the browser I can see that it works fine, so it must be a small issue that I'm missing.
When I click the Get Songs button in my app, it seems as though my toString() function in the Song class isn't working, and when I click the Get Artists button the app crashes completely.
Here is the functions to make the requests:
public void getArtists(View v)
{
final TextView outputTextView = (TextView) findViewById(R.id.outputTextView);
try
{
RequestQueue queue = Volley.newRequestQueue(this);
Log.d(TAG, "Making request to /api/artists/");
try
{
StringRequest strObjRequest = new StringRequest(Request.Method.GET, SERVICE_URI + "/artists",
new Response.Listener<String>()
{
#Override
public void onResponse(String response)
{
Gson gson = new Gson();
Artist[] artists = gson.fromJson(response, Artist[].class);
for(Artist a: artists)
{
outputTextView.setText(a.toString());
Log.d(TAG, "Data: " + a.toString());
}
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error)
{
outputTextView.setText(error.toString());
Log.d(TAG, "Error" + error.toString());
}
});
queue.add(strObjRequest);
}
catch (Exception e2)
{
Log.d(TAG, e2.toString());
outputTextView.setText(e2.toString());
}
}
catch (Exception e1)
{
Log.d(TAG, e1.toString());
outputTextView.setText(e1.toString());
}
}
public void getSongs(View v)
{
final TextView outputTextView = (TextView) findViewById(R.id.outputTextView);
try
{
RequestQueue queue = Volley.newRequestQueue(this);
Log.d(TAG, "Making request to /api/songs/");
try
{
StringRequest strObjRequest = new StringRequest(Request.Method.GET, SERVICE_URI + "/songs",
new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
Gson gson = new Gson();
Song[] songs = gson.fromJson(response, Song[].class);
for (Song s : songs) {
outputTextView.append("\n" + s.toString());
Log.d(TAG, "Data: " + s.toString());
}
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error)
{
outputTextView.setText(error.toString());
Log.d(TAG, "Error" + error.toString());
}
});
queue.add(strObjRequest);
}
catch (Exception e2)
{
Log.d(TAG, e2.toString());
outputTextView.setText(e2.toString());
}
}
catch (Exception e1)
{
Log.d(TAG, e1.toString());
outputTextView.setText(e1.toString());
}
}
And finally in the onCreate() function in the app.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Button getArtistButton = (Button) findViewById(R.id.getArtistsButton);
getArtistButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
getArtists(view);
}
});
Button getSongsButton = (Button) findViewById(R.id.getSongsButton);
getSongsButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
getSongs(view);
}
});
}
Apologies for the walls of code, any help is appreciated! :)
Also, here is the api response from inside the browser:
Based on the output you're seeing, it shows that the toString() is not implemented correctly in your Song class since the Object.toString() is being called, and that is the case for you:
Song.class
...
public String ToString() //Should be toString()
{
String toReturn = "ID: " + Integer.toString(ID) + "\nArtist: " + Integer.toString(ArtistID)
+"\nLength: " + Length + "\nGenre: " + Genre;
return toReturn;
}
You are overriding the wrong toString method, change ToString to toString and it should fix your problem.
In the future use #Override to catch such errors.
I found my error. I did have a typo in the toString() function signature, but also I could return the data correctly when I renamed the variables in the Artist and Song class to exactly the same as in the JSON response.
I'm new to android studio and I'm trying to create a simple weather app using OpenWeatherMap API. I am using OkHttp library to perform a GET request. All it does is take an input throught EditText and update the TextView on button click using a Button.
But the problem is, the TextView updates after two clicks on the Button. I want to update it right after the first click. So, how do I go over this?
Here is my code:
public class MainActivity extends AppCompatActivity {
private EditText cityName;
private TextView weatherData;
private TextView hiddenText;
private Button getBtn;
public String s = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
weatherData = (TextView)findViewById(R.id.weatherText);
getBtn = (Button)findViewById(R.id.getData);
cityName = (EditText)findViewById(R.id.cityName);
getBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getWeatherData(cityName.getText().toString());
weatherData.setText(s);
}
});
}
public void getWeatherData(String cityText){
String url = "https://api.openweathermap.org/data/2.5/weather?q=" + cityText + "&appid=ba45ceb57328448f7wd666hdc6d57aaf";
OkHttpClient client = new OkHttpClient();
final Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
s = "Something went wrong!";
}
});
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
if(response.isSuccessful()){
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
try{
s = response.body().string();
}
catch (IOException ioe){
s = "Error while getting JSON.";
}
}
});
}
}
});
}
}
I know that I can update the TextView in onResponse itself but I wanna know if it is possible to update it through onClickListener. If it's not possible, which method should I use? Any help would be appreciated.
you have to update text value in server response call back
public class MainActivity extends AppCompatActivity {
private EditText cityName;
private TextView weatherData;
private TextView hiddenText;
private Button getBtn;
public String s = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
weatherData = (TextView)findViewById(R.id.weatherText);
getBtn = (Button)findViewById(R.id.getData);
cityName = (EditText)findViewById(R.id.cityName);
getBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getWeatherData(cityName.getText().toString());
}
});
}
public void getWeatherData(String cityText){
String url = "https://api.openweathermap.org/data/2.5/weather?q=" + cityText + "&appid=ba45ceb57328448f7wd666hdc6d57aaf";
OkHttpClient client = new OkHttpClient();
final Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
s = "Something went wrong!";
}
});
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
if(response.isSuccessful()){
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
try{
s = response.body().string();
weatherData.setText(s);
}
catch (IOException ioe){
s = "Error while getting JSON.";
}
}
});
}
}
});
}
}
You are setting data on edit text on click after calling GET Request.
Update the textview with the data , once you get the response.
public class MainActivity extends AppCompatActivity {
private EditText cityName;
private TextView weatherData;
private TextView hiddenText;
private Button getBtn;
public String s = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
weatherData = (TextView)findViewById(R.id.weatherText);
getBtn = (Button)findViewById(R.id.getData);
cityName = (EditText)findViewById(R.id.cityName);
getBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getWeatherData(cityName.getText().toString());
}
});
}
public void getWeatherData(String cityText){
String url = "https://api.openweathermap.org/data/2.5/weather?q=" + cityText + "&appid=ba45ceb57328448f7wd666hdc6d57aaf";
OkHttpClient client = new OkHttpClient();
final Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
s = "Something went wrong!";
}
});
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
if(response.isSuccessful()){
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
try{
s = response.body().string();
weatherData.setText(s);
}
catch (IOException ioe){
s = "Error while getting JSON.";
}
}
});
}
}
});
}
}
Basically this it the code structure, I would like to know how i can modify my codes so that I can get the value inside onResponse and returning it. As of now, my mainReply variable return "(blank)" but im expecting it to pass the data in the arraylist called details inside my onResponse segment. Rest assure, there are values returned as I have checked, but i just cant get the value to be passed out of the onResponse segment.
I have checked for alternatives and they mentioned to use interface. However, I do not know how to modify my codes to use the solution that mentioned interface and use of callBacks.
public class MainActivity extends AppCompatActivity {
EditText et_message;
FloatingActionButton fab_send;
API api;
ListView list_view_conversation;
List<ChatModel> list_chat = new ArrayList<>();
RevealDetailsCallbacks callback;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_message = (EditText) findViewById(R.id.et_message);
fab_send = (FloatingActionButton) findViewById(R.id.fab_send);
list_view_conversation = (ListView) findViewById(R.id.list_view_conversation);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
api = retrofit.create(API.class);
fab_send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//this method ultimately is to get response and send back to user
String s = et_message.getText().toString();
ChatModel model = new ChatModel(s, true);
list_chat.add(model);
new retrieveDetails().execute(list_chat);
et_message.setText("'");
}
});
}
public class retrieveDetails extends AsyncTask<List<ChatModel>, Void, String> {
String text = et_message.getText().toString();
String mainReply = "";
List<ChatModel> models;
List<String> details = new ArrayList<String>();
#Override
public String doInBackground(List<ChatModel>[] lists) {
Call<List<Patient>> call = api.getPatients();
models = lists[0];
call.enqueue(new Callback<List<Patient>>() {
public String reply;
#Override
public void onResponse(Call<List<Patient>> call, Response<List<Patient>> response) {
List<Patient> patients = response.body();
for (int i = 0; i < patients.size(); i++) {
if (patients.get(i).getNric().equals(text)) {
details.add("Name: " + patients.get(i).getName() + "\nNRIC: " + patients.get(i).getNric()
+ "\nDOB: " + patients.get(i).getDob() + "\nContact No: " + patients.get(i).getContactno());
}
}
this.mainReply = details.get(0);
Log.i("Here Log i", reply);
}
#Override
public void onFailure(Call<List<Patient>> call, Throwable t) {
Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
return mainReply;//I want to reply with the data added into the details arraylist in the onResponse segment
}
#Override
public void onPostExecute(String s) {
ChatModel chatModel = new ChatModel(s, false);
models.add(chatModel);
CustomAdapter adapter = new CustomAdapter(models, getApplicationContext());
list_view_conversation.setAdapter(adapter);
}
}
}
If you wanted to modify your existing code, you would add an interface like the one I added up top (RevealDetailsCallbacks), pass it into the asynctask constructor, and run it. The code would look like this:
public class MainActivity extends AppCompatActivity {
//Interface callback here
interface RevealDetailsCallbacks {
public void getDataFromResult(List<String> details);
}
EditText et_message;
FloatingActionButton fab_send;
API api;
ListView list_view_conversation;
List<ChatModel> list_chat = new ArrayList<>();
RevealDetailsCallbacks callback;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_message = (EditText) findViewById(R.id.et_message);
fab_send = (FloatingActionButton) findViewById(R.id.fab_send);
list_view_conversation = (ListView) findViewById(R.id.list_view_conversation);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
this.callback = new RevealDetailsCallbacks() {
#Override
public void getDataFromResult(List<String> details) {
//Do stuff here with the returned list of Strings
}
};
api = retrofit.create(API.class);
fab_send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//this method ultimately is to get response and send back to user
String s = et_message.getText().toString();
ChatModel model = new ChatModel(s, true);
list_chat.add(model);
new retrieveDetails(callback).execute(list_chat);
et_message.setText("'");
}
});
}
public class retrieveDetails extends AsyncTask<List<ChatModel>, Void, String> {
String text = et_message.getText().toString();
String mainReply = "";
List<ChatModel> models;
List<String> details = new ArrayList<String>();
private RevealDetailsCallbacks listener;
retrieveDetails(RevealDetailsCallbacks listener){
this.listener = listener;
}
#Override
public String doInBackground(final List<ChatModel>[] lists) {
Call<List<Patient>> call = api.getPatients();
models = lists[0];
call.enqueue(new Callback<List<Patient>>() {
public String reply;
#Override
public void onResponse(Call<List<Patient>> call, Response<List<Patient>> response) {
List<Patient> patients = response.body();
for (int i = 0; i < patients.size(); i++) {
if (patients.get(i).getNric().equals(text)) {
details.add("Name: " + patients.get(i).getName() + "\nNRIC: " + patients.get(i).getNric()
+ "\nDOB: " + patients.get(i).getDob() + "\nContact No: " + patients.get(i).getContactno());
}
}
this.mainReply = details.get(0);
Log.i("Here Log i", reply);
if(listener != null) {
listener.getDataFromResult(details);
}
}
#Override
public void onFailure(Call<List<Patient>> call, Throwable t) {
//Don't make a toast here, it will throw an exception due to it being in doInBackground
//Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
return mainReply;//I want to reply with the data added into the details arraylist in the onResponse segment
}
#Override
public void onPostExecute(String s) {
ChatModel chatModel = new ChatModel(s, false);
models.add(chatModel);
CustomAdapter adapter = new CustomAdapter(models, getApplicationContext());
list_view_conversation.setAdapter(adapter);
}
}
}
However, there is no need for asynctask here since you are running Retrofit and calling .enqueue, which runs on a background thread. A simpler version would look like this:
public class MainActivity extends AppCompatActivity {
//Interface callback here
interface RevealDetailsCallbacks {
public void getDataFromResult(List<String> details);
}
//Keep your same variables here
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Same setup here
this.callback = new RevealDetailsCallbacks() {
#Override
public void getDataFromResult(List<String> details) {
//Do stuff here with the returned list of Strings
}
};
fab_send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Same setup here, then call the method
makeWebCalls();
}
});
}
private void makeWebCalls(){
Call<List<Patient>> call = api.getPatients();
models = lists[0];
call.enqueue(new Callback<List<Patient>>() {
#Override
public void onResponse(Call<List<Patient>> call, Response<List<Patient>> response) {
//Run your response code here. When done, pass to the callback
}
#Override
public void onFailure(Call<List<Patient>> call, Throwable t) {
Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
You can just enqueue the Retrofit call immediately in the OnClick and handle its response there
fab_send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final String text = et_message.getText().toString();
// if you're trying to filter data, add a parameter to getPatients()
api.getPatients().enqueue(new Callback<List<Patient>>() {
#Override
public void onResponse(Call<List<Patient>> call, Response<List<Patient>> response) {
// Here you have a full list of patients
final List<Patient> patients = response.body();
// adapter = new PatientAdapter(MainActivity.this, patients);
// mListView.setAdapter(adapter);
}
I am trying to do http requests using the volley service, and i found a really usefull answer here about how to organize the service for diferent http requests, so you don't need to do all that code for every request.
The request works fine and i got the result i want, but it never enters de callback on the mainActivity.
So this never gets executed:
void initVolleyCallback(){
mResultCallback = new IResult() {
#Override
public void notifySuccess(String requestType,JSONObject response) {
Log.d("GJ","success");
}
#Override
public void notifyError(String requestType,VolleyError error) {
Log.d(TAG, "Volley requester " + requestType);
Log.d(TAG, "Volley JSON post" + "That didn't work!");
}
};
}
Here is my main activity:
public class Register extends AppCompatActivity {
EditText usernameTxt;
EditText passwordTxt;
EditText emailTxt;
RequestQueue queue;
boolean formValid = false;
VolleyService mVolleyService;
IResult mResultCallback;
static final String TAG = "request12";
final String URL = "http://10.0.2.2:3000/register";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//hide status bar
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_register);
initVolleyCallback();
//inicialize queue with volley
queue = Volley.newRequestQueue(this);
//inicialize form fields
usernameTxt = (EditText)findViewById(R.id.username);
passwordTxt = (EditText)findViewById(R.id.password);
emailTxt = (EditText)findViewById(R.id.email);
//set text for developing stage
usernameTxt.setText("afcosta5");
passwordTxt.setText("moitarioavE10");
emailTxt.setText("filipecosta_10#hotmail.com");
}
public void register(View view) {
System.setProperty("http.keepAlive", "false");
//get form data
final String username = usernameTxt.getText().toString();
String password = passwordTxt.getText().toString();
String email = emailTxt.getText().toString();
Log.d("email",String.valueOf(isValidEmail(email)));
if (!isValidEmail(email)) {
emailTxt.setError("Invalid Email");
}
//inicialize a map with pair key value
final Map<String, String> params = new HashMap<String, String>();
// Add form fields to the map
params.put("username", username);
params.put("email", email);
params.put("password", password);
JSONObject sendObj = new JSONObject(params);
mVolleyService = new VolleyService(mResultCallback,this);
mVolleyService.postDataVolley(URL,sendObj);
void initVolleyCallback(){
mResultCallback = new IResult() {
#Override
public void notifySuccess(String requestType,JSONObject response) {
Log.d("GJ","success");
}
#Override
public void notifyError(String requestType,VolleyError error) {
Log.d(TAG, "Volley requester " + requestType);
Log.d(TAG, "Volley JSON post" + "That didn't work!");
}
};
}
I really don't know where is the issue, need some help
remove "initVolleyCallback()" method from "onCreate()". Implements "IResult" interface like
public class Register extends AppCompatActivity implements IResult
then You'll have to implement override methods of IResult
#Override
public void notifySuccess(String requestType,JSONObject response) {
Log.d("GJ","success");
}
#Override
public void notifyError(String requestType,VolleyError error) {
Log.d(TAG, "Volley requester " + requestType);
Log.d(TAG, "Volley JSON post" + "That didn't work!");
}
I am developing a an android app that uses service discovery over wifi direct,based on the provided google sample code, the problem is i can't get a fixed value of the advertised TXT record even though i'm using a final hashmap to store the value, the Hashmap is modified every time the onDnsSdTxtRecordAvailable callback is called, even though i'm using a final hashmap declared globally to store the first value, it gets replaced by null. here is the code i'm using. thanks
private WifiP2pManager manager;
private final IntentFilter intentFilter = new IntentFilter();
private Channel channel;
private BroadcastReceiver receiver = null;
private WifiP2pDnsSdServiceRequest serviceRequest;
private TextView statusTxtView;
private TextView services;
private Button register;
private Button broadcast;
private LocationManager locationManager;
final HashMap<String, String> buddies = new HashMap<String, String>();
private TextView locationTxt;
public String value1;
private Button loc;
private final String name = new String();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
statusTxtView = (TextView) findViewById(R.id.status);
services = (TextView) findViewById(R.id.services);
register = (Button) findViewById(R.id.discover);
broadcast = (Button) findViewById(R.id.bd);
locationTxt = (TextView)findViewById(R.id.location);
loc = (Button)findViewById(R.id.loc);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
intentFilter
.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
intentFilter
.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
channel = manager.initialize(this, getMainLooper(), null);
startRegistrationAndDiscovery();
register.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startRegistrationAndDiscovery();
}
});
broadcast.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
discoverService();
}
});
loc.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
doIt();
}
});
}
#Override
public void onResume() {
super.onResume();
receiver = new MyReceiver(manager, channel, this);
registerReceiver(receiver, intentFilter);
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
public void appendStatus(String status) {
String current = statusTxtView.getText().toString();
statusTxtView.setText(current + "\n" + status);
}
//service discvery handllng methods
private void startRegistrationAndDiscovery() {
Map<String, String> record = new HashMap<String, String>();
record.put(TXTRECORD_PROP_AVAILABLE, "visible");
WifiP2pDnsSdServiceInfo service = WifiP2pDnsSdServiceInfo.newInstance(
SERVICE_INSTANCE, SERVICE_REG_TYPE, record);
manager.addLocalService(channel, service, new ActionListener() {
#Override
public void onSuccess() {
appendStatus("Added Local Service");
}
#Override
public void onFailure(int error) {
appendStatus("Failed to add a service");
}
});
discoverService();
}
private void discoverService() {
/*
* Register listeners for DNS-SD services. These are callbacks invoked
* by the system when a service is actually discovered.
*/
manager.setDnsSdResponseListeners(channel,
new DnsSdServiceResponseListener() {
#Override
public void onDnsSdServiceAvailable(String instanceName,
String registrationType, WifiP2pDevice srcDevice) {
// A service has been discovered. Is this our app?
if (instanceName.equalsIgnoreCase(SERVICE_INSTANCE)) {
// update the UI and add the item the discovered
// device.
/* WiFiP2pService service = new WiFiP2pService();
service.device = srcDevice;
service.instanceName = instanceName;
service.serviceRegistrationType = registrationType;*/
//put data to textview here
services.setText(srcDevice.status+" Instance name " + instanceName + " type " + registrationType);
Log.d(TAG, "onBonjourServiceAvailable "
+ instanceName);
Http_client http_client = new Http_client(SERVICE_INSTANCE);
appendStatus("data sent to server successfully");
}
}
}, new DnsSdTxtRecordListener() {
/**
* A new TXT record is available. Pick up the advertised
* buddy name.
*/
#Override
public void onDnsSdTxtRecordAvailable(String fullDomainName, Map<String, String> record,WifiP2pDevice device) {
Log.d(TAG, device.deviceName + " is " + record.get(TXTRECORD_PROP_AVAILABLE));
buddies.put("mm",record.get(TXTRECORD_PROP_AVAILABLE));
Toast.makeText(getBaseContext(),record.get(TXTRECORD_PROP_AVAILABLE),Toast.LENGTH_LONG).show();
//
}
});
// After attaching listeners, create a service request and initiate
// discovery.
serviceRequest = WifiP2pDnsSdServiceRequest.newInstance();
manager.addServiceRequest(channel, serviceRequest,
new ActionListener() {
#Override
public void onSuccess() {
appendStatus("Added service discovery request");
}
#Override
public void onFailure(int arg0) {
appendStatus("Failed adding service discovery request");
}
});
manager.discoverServices(channel, new ActionListener() {
#Override
public void onSuccess() {
appendStatus("Service discovery initiated");
}
#Override
public void onFailure(int arg0) {
appendStatus("Service discovery failed");
}
});
}
public void doIt(){
buddies.put("mm","value1");
Toast.makeText(getBaseContext(),buddies.get("mm"),Toast.LENGTH_LONG).show();
buddies.put("mm","value2");
Toast.makeText(getBaseContext(),buddies.get("mm"),Toast.LENGTH_LONG).show();
}
A final variable will not help you, as I have commented. Based on your question, what you need to do is to always check if the value is set in your hashmap, before saving the new returned variable. Something like
if (!buddies.containKey("mm"))
buddies.put("mm", .....)