How can I implement push notifications and user file upload and downloads? - Java for Android App Development

I'd like to add push notifications for my webview app for when a user receives notifications on my forum but I'm not sure how to go about doing that. Also I would like to know how to allow users to upload and download files from my forum.
Here's my code:
Code:
[COLOR="MediumTurquoise"]package technologx.technologx;
/**
* Created by Technologx on 12/22/15
* ©2015 Technologx All Rights Reserved
* http://technologx.fulba.com
*/
import android.os.Build;
import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.common.api.GoogleApiClient;
@SuppressLint("SetJavaScriptEnabled")
public class MainActivity extends Activity {
private static final String TAG = "TechnologxFetch";
private static final String API_KEY = "d8b4541518368aa71b83cc1f90381067";
...
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
private GoogleApiClient client;
...
String getUrlString(String urlSpec) throws IOEception {
return new String(geUrlBytes(urlSpec));
}
private WebView webView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// If the Android version is lower than Jellybean, use this call to hide
// the status bar.
if (Build.VERSION.SDK_INT < 16) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
// Adds Progress Bar Support
this.getWindow().requestFeature(Window.FEATURE_PROGRESS);
// Makes Progress Bar Visible
getWindow().setFeatureInt(Window.FEATURE_PROGRESS, Window.PROGRESS_VISIBILITY_ON);
// Use forum.xml as webview layout
setContentView(R.layout.activity_main);
webView = (WebView) findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
// Adds Zoom Control (You may not need this)
webView.getSettings().setSupportZoom(true);
// Enables Multi-Touch. if supported by ROM
webView.getSettings().setBuiltInZoomControls(true);
// Change to your own forum url
webView.loadUrl("http://technologx.96.lt/");
webView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// Loads only your forum domain and no others!
if (url.contains("technologx.96.lt") == true) {
view.loadUrl(url);
// Adds Progress Bar Support
super.onPageStarted(view, url, null);
findViewById(R.id.progressbar).setVisibility(View.VISIBLE);
// If they are not your domain, use browser instead
} else {
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
}
return true;
}
@Override
public void onPageFinished(WebView view, String url) {
// Removes Progress Bar
findViewById(R.id.progressbar).setVisibility(View.GONE);
// Adds Cookies. Yummy!
CookieSyncManager.getInstance().sync();
}
});
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
public void fetchItems() {
try {
String url = Uri.parse("http://technologx.9.lt")
.buildUpon()
.appendQueryParameter("method", "technologx.fetch.getRecent")
.appendQueryParameter("d8b4541518368aa71b83cc1f90381067", API_KEY)
.appendQueryParameter("format", "json")
.appendQueryParameter("nojsoncallback", "1")
.appendQueryParameter("extras", "url_s")
.build().toString();
String jsonString = getUrlString(url);
Log.i(TAG, "Received JSON: " + jsonString);
} catch (IOEception ioe) {
Log.e(TAG, "Failed to fetch items", ioe);
}
}
}
@Override
public void onBackPressed() {
// Enables going back history
if (webView.copyBackForwardList().getCurrentIndex() > 0) {
webView.goBack();
} else {
// Your exit alert code, or alternatively line below to finish
// Finishes forum activity
super.onBackPressed();
}
}
@Override
public void onStart() {
super.onStart();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client.connect();
Action viewAction = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"Main Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app deep link URI is correct.
Uri.parse("android-app://technologx.technologx/http/host/path")
);
AppIndex.AppIndexApi.start(client, viewAction);
}
@Override
public void onStop() {
super.onStop();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
Action viewAction = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"Main Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app deep link URI is correct.
Uri.parse("android-app://technologx.technologx/http/host/path")
);
AppIndex.AppIndexApi.end(client, viewAction);
client.disconnect();
}
}[/COLOR]

Implementing push messages is a great thing, if you have just the webview. Cause your app has to authenticate against your site. Just if the user is authenticated you can use the Google Cloud Messaging or Websockets to push from your server to the app.
At the moment the authentication is created by the webview. But AFAIK you have no access to the cookies from the webview. So either you have to create a seconds authentication method from the app or you can't use push messages.
Maybe you can use the W3C Push Message Api but I don't think so.

pbeckmann said:
Implementing push messages is a great thing, if you have just the webview. Cause your app has to authenticate against your site. Just if the user is authenticated you can use the Google Cloud Messaging or Websockets to push from your server to the app.
At the moment the authentication is created by the webview. But AFAIK you have no access to the cookies from the webview. So either you have to create a seconds authentication method from the app or you can't use push messages.
Maybe you can use the W3C Push Message Api but I don't think so.
Click to expand...
Click to collapse
Would you be able to help I'm new to mobile coding?

Theoretically yes, but at the moment I'm just in my exams, and after I have to do some work on for my study. So unfortunately I haven't the time right now...
Sorry.
A short advice is to look right into the official Google Documentation.

pbeckmann said:
Theoretically yes, but at the moment I'm just in my exams, and after I have to do some work on for my study. So unfortunately I haven't the time right now...
Sorry.
A short advice is to look right into the official Google Documentation.
Click to expand...
Click to collapse
Alright thank you um do you happen to know anything about the second part of my question user uploading and download files to and from my forum using the app?

Unfortunately I have not really an idea. I would look at the built-in http client from android. It should be able to handle this. But I've never tried.

Well I give up I am a noob to coding and can't figure this out.

Related

Android/Java Newbie

Hi all, im having a go at developing a simple app. i have little experience with Java and Android development. i have a little test app at the moment and have created a new class, im trying to create a new instance of this class on a button click. it fails to do so, i cant for the life of me see why so.. can someone shed any light on this?
Thanks
Debuging this shows it hitting the "LocationFactory locationf = new LocationFactory();" line and throwing an exception-
"java.lang.NullPointerException"
Main
Code:
package com.example.testapp;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;
import java.io.IOException;
public class MainActivity extends Activity {
private static final Context Context = null;
protected static final String TAG = null;
[user=439709]@override[/user]
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
[user=439709]@override[/user]
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void mainButton(View view) throws IOException {
try {
LocationFactory locationf = new LocationFactory();
Toast.makeText(this, locationf.getAddress(),Toast.LENGTH_LONG).show();
} catch (Exception e)
{
Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show();
}
}
}
Class
Code:
package com.example.testapp;
import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationManager;
import java.io.IOException;
import java.util.Locale;
import java.util.List;
public class LocationFactory
{
private static final Context Context = null;
Geocoder geocoder = new Geocoder(Context, Locale.getDefault());
LocationManager manager = (LocationManager) Context.getSystemService(android.content.Context.LOCATION_SERVICE);
public double Latitude = 0.0;
public double Longitude = 0.0;
public LocationFactory()
{
}
public String getAddress() throws IOException
{
String ReturnAddress = "";
String Address = "", City = "", Country = "";
List<Address> addresses = null;
if(manager.isProviderEnabled(LocationManager.GPS_PROVIDER))
{
// Use GPS Radio Location
Location GPSlocation = manager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
Latitude = GPSlocation.getLatitude();
Longitude = GPSlocation.getLongitude();
}
else
{
// Use Cell Tower Location
Location NETlocation = manager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
Latitude = NETlocation.getLatitude();
Longitude = NETlocation.getLongitude();
}
if(Latitude > 0 && Longitude > 0)
{
addresses = geocoder.getFromLocation(Latitude, Longitude, 1);
if(!addresses.isEmpty())
{
Address = addresses.get(0).getAddressLine(0);
City = addresses.get(0).getAddressLine(1);
Country = addresses.get(0).getAddressLine(2);
}
}
ReturnAddress = Address + " " + City + " " + Country;
return ReturnAddress;
}
}
I don't see anywhere in your code where you are calling the mainButton(View view) method. In the Android lifecycle, the onCreate method is the equivalent of a normal Java program's main() method, which means that code execution begins with the first line of onCreate(). Not knowing what you're trying to do, a good start would be to call your mainButton() method AFTER setContentView() in onCreate().
Side note: your mainButton() method has a View parameter that is never used. Is there a reason for that?
Android activity lifecycle: http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
You have to use an intent on that button click, use the method onClickListener and define the intent in the androidmanifest.xml
e.g
Code:
Button button = (Button) findViewById(R.id.[B]button[/B]) // replace latter button with actual id defined in main xml.
button.setOnClickListener(new View.OnClickListener() {
[user=439709]@override[/user]
public void onClick(View arg0) {
// TODO Auto-generated method stub
startActivity(new Intent("[B]com.example.packagename.CLASSNAME[/B]")); // this should be your own package name.
}
});
Also define this in android manifest under the <application> and </application>
Code:
<activity
android:name=".[B]CLASSNAME[/B]"
android:label="@string/app_name"
>
<intent-filter>
<action android:name="[B]com.example.packagename.CLASSNAME[/B]" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Change the values of BOLD text according to your own values.
I tried to help you as far as I understood your question. Please let me know if you face any problem I would be more than happy to help you. Rest I am also in the learning phase so you can always PM me if you face any problem.
Hit thanks if I have helped you in any way.
coolbud012 said:
You have to use an intent on that button click, use the method onClickListener and define the intent in the androidmanifest.xml
Click to expand...
Click to collapse
Nope! He didn't say that he wanted to launch a new Activity when the button is clicked. He wants to create a new instance of his LocationFactory Class.
jpepin said:
Nope! He didn't say that he wanted to launch a new Activity when the button is clicked. He wants to create a new instance of his LocationFactory Class.
Click to expand...
Click to collapse
Oops yeah right read that now...I thought he want to start an activity... Anyways tried to delete my reply but not getting an option to delete.
There are many flaws in his code. And the other thing is if its his first app and if he has low level of programming experience then according to me it would be a next to impossible app for him, as per his code and what he is trying to implement.
I think he should rather start up with small apps, understand things and then move on to complex apps.
P.S - its just my opinion
Click to expand...
Click to collapse
Agreed that he should start small...which is exactly why your suggestion for creating and handling Intents makes no sense. Before that, he should first understand the activity lifecycle. Until then, he can just stick to trivial single-activity apps to gain experience.
OP: This code should be placed in the onCreate method:
Code:
Button button = (Button) findViewById(R.id.your_button_ID_here)
button.setOnClickListener(new View.OnClickListener() {
[user=439709]@override[/user]
public void onClick(View arg0) {
mainButton(); // get rid of the View parameter in this method...it's not needed
}
});
This will cause a new instance of your LocationFactory to be created, and will also cause your Toast message to be displayed.
thanks for the replies. yes you are right in that i am inexperienced, but this is just a test app for me to play around with and learn on. i tend to learn better by doing rather than constantly reading. thanks for your suggestions ill look into them
osmorgan said:
thanks for the replies. yes you are right in that i am inexperienced, but this is just a test app for me to play around with and learn on. i tend to learn better by doing rather than constantly reading. thanks for your suggestions ill look into them
Click to expand...
Click to collapse
I also believe in the same, I also keep on doing experiments and testing things out.
What I would suggest is that start with a small app and understand the insights on how android works and all...
Thanks
Potential Solution
Alright, I think I've found your problem. Have a look at where you define your variables in your LocationManager class:
Code:
private static final Context Context = null;
Geocoder geocoder = new Geocoder(Context, Locale.getDefault());
LocationManager manager = (LocationManager) Context.getSystemService(android.content.Context.LOCATION_SERVICE);
This is your problem:
Code:
Context Context = null;
If your context is null, and you use it to create a geocoder and call Context.getSystemService, you'll hit a null pointer. You're trying to access an object (the Context) that doesn't even exist
I'd recommend you pass the context in the LocationManager constructor and then instantiate your objects there. That's standard java procedure.
Code:
private Context mContext = null;
Geocoder geocoder = null;
LocationManager manager = null;
public double Latitude = 0.0;
public double Longitude = 0.0;
public LocationFactory(Context context)
{
this.mContext = context;
this.geocoder = new Geocoder(context, Locale.getDefault());
this.manager = (LocationManager) Context.getSystemService(android.content.Context.LOCATION_SERVICE);
}
I also renamed Context to mContext - it's generally a good idea to keep the instance's name separate from the class name.
Try that - it should work. Please feel free to ask any more questions - this is how I learned, and I think it's the best way!

[Q]How to hand different Strings to dynamically created Fragments using ViewPager?

I can't seem to find a way to give different text to a dynamically created fragment for my pageviewer-supoorted application. I've came to a point of my codding where I got stuck. For my application I want to have 400-500 dynamically created fragments, where you can horizontally slide thru them and every content of the fragment to be the same (repeating the same fragment) and the only different thing to be the text on them.
Here's where I got stuck at my codding :
Code:
package com.example.testarearg;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class MainActivity extends FragmentActivity {
/**
* The {@link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
* will keep every loaded fragment in memory. If this becomes too memory
* intensive, it may be best to switch to a
* {@link android.support.v4.app.FragmentStatePagerAdapter}.
*/
SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {@link ViewPager} that will host the section contents.
*/
ViewPager mViewPager;
[user=439709]@override[/user]
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
[user=439709]@override[/user]
public void onPageSelected(int position) {
}
});
}
/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
[user=439709]@override[/user]
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a DummySectionFragment (defined as a static inner class
// below) with the page number as its lone argument.
Fragment fragment = new DummySectionFragment();
Bundle args = new Bundle();
args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1);
fragment.setArguments(args);
return fragment;
}
[user=439709]@override[/user]
public int getCount() {
// Show 3 total pages.
return 3;
}
}
/**
* A dummy fragment representing a section of the app, but that simply
* displays dummy text.
*/
public static class DummySectionFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/ private String mText; // display this text in your fragment
public static Fragment getInstance(String text) {
Fragment f = new Fragment();
Bundle args = new Bundle();
args.putString("text", text);
f.setArguments(args);
return f;
}
public void onCreate(Bundle state) {
super.onCreate(state);
setmText(getArguments().getString("text"));
// rest of your code
}
public static final String ARG_SECTION_NUMBER = "section_number";
public DummySectionFragment() {
}
[user=439709]@override[/user]
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main_dummy, container, false);
TextView dummyTextView = (TextView) rootView.findViewById(R.id.section_label);
dummyTextView.setText(Integer.toString(getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView;
}
public String getmText() {
return mText;
}
public void setmText(String mText) {
this.mText = mText;
}
}
}
featyhu James
I wanted to first off introduce you to a widget called Viewpagerindicator by Jake Wharton if you haven't already come across it. It is a very popular viewpager extension.
You can download a demo from google play (this I recommend), search for "viewpager indicator"
To give you a back of the envelope solution, I would suggest you try creating at least 2 fragments and then page between them updating the text in on resume(). Do these fragment words need to be remembered? For instance if the user swipes back and forth are the same words meant to reappear?
hgpb said:
I wanted to first off introduce you to a widget called Viewpagerindicator by Jake Wharton if you haven't already come across it. It is a very popular viewpager extension.
You can download a demo from google play (this I recommend), search for "viewpager indicator"
To give you a back of the envelope solution, I would suggest you try creating at least 2 fragments and then page between them updating the text in on resume(). Do these fragment words need to be remembered? For instance if the user swipes back and forth are the same words meant to reappear?
Click to expand...
Click to collapse
Ohh, I was not aware about this extension. I'm gonna try it and see what I get out of it. Yes, the words need to be remembered. Thank you for the heads-up about 'viewpager indicator' .
Feciuc said:
Ohh, I was not aware about this extension. I'm gonna try it and see what I get out of it. Yes, the words need to be remembered. Thank you for the heads-up about 'viewpager indicator' .
Click to expand...
Click to collapse
When you get the Viewpager indicator setup with a couple of fragments initialised you need to track the words you create. You could use a SparseArray/ArrayList or such like to track the position of frag and word perhaps. Then you should be able to move through the array depending on the swipe you receive. The swipe would move you up or down the array giving you access.
Code:
SparseArray<String> sa = new SparseArray<String>();
As I said this is a back of the envelope solution but it may just do the trick.

[Q] Communication between digi wifi module and an app

Hello, I could use some guidance with my first app. I have a digi wifi module + sam3x8e arm cortex m3 microcontroller connected tethered to my phone and I would like to send some data between two. Microcontroller is pulling data from a pressure sensor, air fuel ratio sensor, flow sensor and and transmits data as: B25A13F1B25A13F1B25A13F1 where B=boost, A= AFR, F=flow
In app I need to pull the info of the tethered devices, send info to the microcontroller. Then I need to process incoming string and display it in app.
Since this is my first app, I could use help on how to structure the app itself and links to the reference materials you guys are using. I have read bunch of tutorial so far and created a simple TCP socket app that can transmit data when i press the button but thats not what i need to do, and I do not understand how to make the app continiously process incoming data.
Thank you,
Yaro
So I ended up with 2 fragments inside my main activity, interface, and a service that I can bind to.
I really need your help guys, Java aint that tough but I very much lack understanding of philosophy behind app design. Where should I break down incoming String data B25A13F1B25A13F1B25A13F1 into useable data. Should I do in service or Fragment? Please help... it took me way too long to figure out that I can't start service from fragment
Code to illustrate the communication.
Communication from service to GUI (main activity):
Code:
private class IncomingMessageHandler extends Handler {
[user=439709]@override[/user]
public void handleMessage(Message msg) {
switch (msg.what) {
case MyService.MSG_SET_INT_VALUE:
textIntValue.setText("Int Message: " + msg.arg1);
break;
case MyService.MSG_SET_STRING_VALUE:
String str1 = msg.getData().getString("str1");
textStrValue.setText("Str Message: " + str1);
break;
default:
super.handleMessage(msg);
}
}
}
Communication from Service to GUI (Service)
Code:
private void sendMessageToUI(int intvaluetosend) {
Iterator<Messenger> messengerIterator = mClients.iterator();
while(messengerIterator.hasNext()) {
Messenger messenger = messengerIterator.next();
try {
// Send data as an Integer
messenger.send(Message.obtain(null, MSG_SET_INT_VALUE, intvaluetosend, 0));
// Send data as a String
Bundle bundle = new Bundle();
bundle.putString("str1", "ab" + intvaluetosend + "cd");
Message msg = Message.obtain(null, MSG_SET_STRING_VALUE);
msg.setData(bundle);
messenger.send(msg);
} catch (RemoteException e) {
// The client is dead. Remove it from the list.
mClients.remove(messenger);
}
}
}
You CAN start a Service from a Fragment:
Code:
getActivity().startService(<your parameters here>);
Everything related to this (e.g. the bind action) can be done from a Fragment if you put getActivity() in front of it.
nikwen said:
You CAN start a Service from a Fragment:
Code:
getActivity().startService(<your parameters here>);
Everything related to this (e.g. the bind action) can be done from a Fragment if you put getActivity() in front of it.
Click to expand...
Click to collapse
Thank you sir, that peace of information simplified my life quite nicely.
I found very nice simple example that works on the net and it works. kinda... After I click my button there is about 2-3 second delay before my client displays the response. Also I am trying to send "Hello there" and I get "....t..Hello there". I am intending to communicate both ways, from the phone and to the phone at the same time and such a huge delay is unacceptable. Any ideas why? Code below.
Code:
package com.example.mytcpcleint;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView serverMessage;
Thread m_objThreadClient;
Socket clientSocket;
[user=439709]@override[/user]
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
serverMessage=(TextView)findViewById(R.id.textView1);
}
public void Start(View view)
{
m_objThreadClient=new Thread(new Runnable() {
public void run()
{
try
{
clientSocket= new Socket("192.168.43.59",9750);
ObjectOutputStream oos = new ObjectOutputStream(clientSocket.getOutputStream());
oos.writeObject("Hello there");
// Message serverMessage= Message.obtain();
// ObjectInputStream ois =new ObjectInputStream(clientSocket.getInputStream());
// String strMessage = (String)ois.readObject();
// serverMessage.obj=strMessage;
// mHandler.sendMessage(serverMessage);
oos.close();
// ois.close();
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
m_objThreadClient.start();
}
Handler mHandler = new Handler() {
[user=439709]@override[/user]
public void handleMessage(Message msg) {
messageDisplay(msg.obj.toString());
}
};
public void messageDisplay(String servermessage)
{
serverMessage.setText(""+servermessage);
}
}

Data That is Fetched From The Web Server Are Appending

I have this search function for my app that fetches data from web server using json, everything works completely except that everytime I search something, the data keeps on appending on my listview. For example if I search for a data with an id number 7 then press search button, the data is fetched and placed on the listview which what I want, but then if I search again the id number 7, there are now 2 instances of data with an id number of 7 in the listview. What I want is to refresh the listview for every search so that the only data that will appear on the listview is the current searched data.
MainActivity.java
Code:
package learn2crack.listview;
import java.util.ArrayList;
import java.util.HashMap;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.EditText;
import learn2crack.listview.library.JSONParser;
public class MainActivity extends Activity {
ListView list;
TextView title;
Button Btngetdata;
ArrayList<HashMap<String, String>> oslist = new ArrayList<HashMap<String, String>>();
//JSON Node Names
private static final String TAG_NEWS = "news";
private static final String TAG_TITLE = "title";
JSONArray android = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
oslist = new ArrayList<HashMap<String, String>>();
Btngetdata = (Button)findViewById(R.id.getdata);
Btngetdata.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new JSONParse().execute();
}
});
}
private class JSONParse extends AsyncTask<String, String, JSONObject> {
private ProgressDialog pDialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
title = (TextView)findViewById(R.id.title);
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Getting Data ...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
@Override
protected JSONObject doInBackground(String... args) {
JSONParser jParser = new JSONParser();
String url = "http://localhost/abc-news/news.php?json-request-news=";
EditText id = (EditText)findViewById(R.id.search_text);
url = url + id.getText().toString();
// Getting JSON from URL
JSONObject json = jParser.getJSONFromUrl(url);
return json;
}
@Override
protected void onPostExecute(JSONObject json) {
pDialog.dismiss();
try {
// Getting JSON Array from URL
android = json.getJSONArray(TAG_NEWS);
for(int i = 0; i < android.length(); i++){
JSONObject c = android.getJSONObject(i);
// Storing JSON item in a Variable
String title = c.getString(TAG_TITLE);
// Adding value HashMap key => value
HashMap<String, String> map = new HashMap<String, String>();
map.put(TAG_TITLE, title);
oslist.add(map);
list=(ListView)findViewById(R.id.list);
ListAdapter adapter = new SimpleAdapter(MainActivity.this, oslist,
R.layout.list_v,
new String[] { TAG_TITLE }, new int[] {
R.id.title });
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(MainActivity.this, "You Clicked at "+oslist.get(+position).get("name"), Toast.LENGTH_SHORT).show();
}
});
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
I attached an image below to support this problem I'm encountering.
Code:
oslist.add(map);
you're adding to the list that drives the adapter, add does what it implies ... maybe you should go though some basics, copy and pasting code sometimes wastes more time that you think it would save in the long run.
Hope that helps
Can you explain it more clearly here?
clonedaccnt said:
Can you explain it more clearly here?
Click to expand...
Click to collapse
erm, add = add ? sorry to come across like this but not sure what you are expecting... a,b,c .add(d) == a,b,c,d
What do I need to do to my code so that the newly searched data will not append on the previous data that is fetched?
clonedaccnt said:
What do I need to do to my code so that the newly searched data will not append on the previous data that is fetched?
Click to expand...
Click to collapse
I thought that was clear, don't "add" to what you have? Are you aware of what an array is ? or a list? and an adapter? cause I think I would start there, you just keep adding to the list that powers the adapter. If you dont want to add to it just don't, either clear it or replace it.
so just to be clear, a list or map has the method .clear() <--- that clears it of all data
I've already solve the problem earlier, I was going to post that I've already solve it but found out that you've already replied on the thread, sorry. About the problem, yes I too used the .clear() of the ArrayList to clear the array before adding a new one, it's my first time to create an activity that pass the data on the same activity, I'm used to passing the data from one activity to another so I don't have a chance to encounter this kind of problem.
Anyways thanks for helping I will not have accomplished this without your help.

[Q] Code placement for writing TCP/IP data to TextView

Hello,
I am a first time poster new to Android app development so please bear with me. I am currently working off of two great TCP/IP Client examples. My goal is to create a simple TCP/IP Client that connects to a server and, once a connection is established, continuously updates a TextView with strings passed from the server. If the user presses a button, the client sends a stop command to the server and I would ultimately like to expand the TextView into a graph with the converted string values. I am able to establish the connection to the server and send the stop command from the client but my attempts at adding the read capability have, so far, been unsuccessful with the app crashing as soon as it starts up.
Since it is my first time posting, I am not allowed to link the examples I am using. If anyone is interested in seeing them, however, they are posts from the android-er blog titled: "Android Server/Client example - client side using Socket" and "Bi-directional communication between Client and Server, using ServerSocket, Socket, DataInputStream and DataOutputStream".
Here is the code in my MainActivity:
Code:
package com.example.androidclient;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity {
TextView textResponse;
TextView textIn;
EditText editTextAddress, editTextPort;
Button buttonConnect, buttonStopTest, buttonDisconnect;
Socket socket = null;
DataInputStream incomingString = null;
DataOutputStream terminalLetter = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_main);
editTextAddress = (EditText)findViewById(R.id.address);
editTextPort = (EditText)findViewById(R.id.port);
buttonConnect = (Button)findViewById(R.id.connect);
buttonDisconnect = (Button)findViewById(R.id.disconnect);
buttonStopTest = (Button)findViewById(R.id.stop_test);
textResponse = (TextView)findViewById(R.id.response);
textIn = (TextView)findViewById(R.id.text_in);
buttonConnect.setOnClickListener(buttonConnectOnClickListener);
buttonStopTest.setOnClickListener(buttonStopTestOnClickListener);
buttonDisconnect.setOnClickListener(buttonDisconnectOnClickListener);
}
OnClickListener buttonConnectOnClickListener = new OnClickListener(){
//setOnClickListener sets a callback to be invoked when the button is clicked
@Override
public void onClick(View arg0) {
//Clicking button (Connect) calls a MyClientTask defined below.
MyClientTask myClientTask = new
MyClientTask(editTextAddress.getText().toString(),
Integer.parseInt(editTextPort.getText().toString()));
myClientTask.execute();
}
};
OnClickListener buttonStopTestOnClickListener = new OnClickListener(){
//setOnClickListener sets a callback to be invoked when the button is clicked
@Override
public void onClick(View arg0) {
try {
terminalLetter = new DataOutputStream(socket.getOutputStream());
terminalLetter.writeByte('b');
terminalLetter.writeByte('\n');
terminalLetter.close();
socket.close();
}
catch (IOException e) {
System.err.println("Couldn't get I/O for the connection.");
}
}
};
OnClickListener buttonDisconnectOnClickListener = new OnClickListener(){
//setOnClickListener sets a callback to be invoked when the button is clicked
@Override
public void onClick(View arg0) {
try {
socket.close();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
public class MyClientTask extends AsyncTask<Void, Void, Void> {
String IPaddress;
int Port;
String response = "";
MyClientTask(String addr, int port){
IPaddress = addr;
Port = port;
}
@Override
protected Void doInBackground(Void... arg0) {
//Took socket declaration from here.
try {
//Taking relevant parameters and applying them to socket
socket = new Socket(IPaddress, Port);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);
byte[] buffer = new byte[1024];
int bytesRead;
InputStream inputStream = socket.getInputStream();
incomingString = new DataInputStream(socket.getInputStream());
textIn.setText(incomingString.readUTF());
/*
* notice:
* inputStream.read() will block if no data return
*/
while ((bytesRead = inputStream.read(buffer)) != -1){
byteArrayOutputStream.write(buffer, 0, bytesRead);
response += byteArrayOutputStream.toString("UTF-8");
}
}
catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "UnknownHostException: " + e.toString();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
response = "IOException: " + e.toString();
}
finally{
if(socket != null){
try {
socket.close();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
@Override
protected void onPostExecute(Void result) {
textResponse.setText(response);
super.onPostExecute(result);
}
}
}
I put the commands for reading data from the server and writing it to the TextView with the code that sets up the connection to the socket. The idea was that it would be the next step after the connection is established but I realize that it looks like I am only reading once. I tried adding a while loop and bringing it out of the doInBackground. In each case, all I got was the whole app crashing on me. It looks fairly straight forward in the example but there the connection is automatic, not triggered and I have not been able to modify the code successfully.
I am still new to Android and this feels like it is an important part of app development so I am hoping someone in the community can help me understand where the section of code relevant to reading data (continuously) should be placed in relation to the rest.
Best,
Yusif Nurizade
P.S. I was going to include the fragment but, since the post is long enough, I chose to omit it. I can share upon request and the logcat.

Categories

Resources