I have a button in my application which on click should run AsyncTask but the doInBackground method is not being called, I am trying to connect to my server using okHTTP inside AsyncTask, here is my code,
public class Home extends Fragment implements View.OnClickListener {
Button button;
public static final String TAG = "aj";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.home, container, false);
button = (Button) v.findViewById(R.id.button);
button.setOnClickListener(this);
FirebaseMessaging.getInstance().subscribeToTopic("test");
FirebaseInstanceId.getInstance().getToken();
return v;
}
#Override
public void onClick(View v) {
sendRequest myTask = new sendRequest();
if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.HONEYCOMB)
myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
myTask.execute();
}
private class sendRequest extends AsyncTask<Void,Void,Void>{
#Override
protected Void doInBackground(Void... params) {
Log.v(TAG, "doInBackground");
String token = FirebaseInstanceId.getInstance().getToken();
OkHttpClient client = new OkHttpClient();
RequestBody body = null;
if (token != null) {
body = new FormBody.Builder()
.add("Token", token)
.build();
}
Request request = new Request.Builder()
.url("https://www.example.com/aj20010319")
.post(body)
.build();
try {
client.newCall(request).execute();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
}
I don't know why the doInBackground method is not being called, the logger doesn't log anything regarding it. And if I am correct, it is setup correctly. I tried the solutions in other threads but none is working.
checked your code in my machine removing the complexities its working fine i pasted the code bellow.
Two thing it can happen
problem with build version . just call the myTask.execute();remove all the if else
It might happen with the logcat . if possible make toast from the doInBackground
Toast.makeText(getApplicationContext(), "text", Toast.LENGTH_LONG).show();
If you are searching in the logcat it always searches by message not by tag so search by doInBackground not by aj
public class MainActivity extends Activity implements View.OnClickListener{
Button button;
#Override
public void onClick(View arg0) {
sendRequest myTask = new sendRequest();
if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.HONEYCOMB)
myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
myTask.execute();
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=(Button)findViewById(R.id.button1);
button.setOnClickListener(this);
}
private class sendRequest extends AsyncTask<Void,Void,Void>{
#Override
protected Void doInBackground(Void... params)
{
int i=0;
while(++i<100)
{
Log.i("www", "www");
}
return null;
}
}
}
You need to instantiate the class
new myTask().execute();
Inside the onClickListener
Related
I am new to Android dev and have the following design question when one makes an asnyc rest web request. In my main activity I have a button that does the request using an async task:
public class MainActivity extends ActionBarActivity {
final Context context=this;
.......
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
Button btn = (Button)findViewById(R.id.myshowbutton);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
WebRequest wr=new WebRequest(view.getRootView());
wr.execute("http://www.cheesejedi.com/rest_services/get_big_cheese?level=1");
}
});
}
Th async task class which is in a separate java file:
public class WebRequest extends AsyncTask<String, String, String> {
private View view;
public WebRequest(View v) {
this.view = v;
}
#Override
protected String doInBackground(String... uri) {
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response;
String responseString = null;
try {
response = httpclient.execute(new HttpGet(uri[0]));
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpStatus.SC_OK){
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
responseString = out.toString();
} else{
//Closes the connection.
response.getEntity().getContent().close();
throw new IOException(statusLine.getReasonPhrase());
}
} catch (ClientProtocolException e) {
//TODO Handle problems..
} catch (IOException e) {
//TODO Handle problems..
}
return responseString;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
EditText et=(EditText)view.findViewById(R.id.editText);
et.setText(result);
}
}
As you can see I am setting the EditText box to the JSON which is returned. I pass a reference of the root view to my WebRequest class so that I can get hold of the EditText box.
Is there a better way of doing this? It does not seem very elegant. Perhaps a nice libary for web requests?
This way works fine, and it is good to know how to write this. There are a couple of things you can do to improve this, and there is also a library you can use to greatly simplify your code.
Option 1: Improve your code
First, you can use a Callback to set the text in the EditText in your Activity, instead:
Change these lines in WebRequest:
private View view;
public WebRequest(View v) {
this.view = v;
}
to
public interface Callback {
public void call(String result);
}
private Callback callback;
public WebRequest(Callback c) {
this.callback = callback;
}
Then in onPostExecute, just call:
callback.call(result);
Now, when you start the web service, your call will look like this:
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
WebRequest wr=new WebRequest(new Callback() {
#Override
public void call(String result) {
((EditText)view.findViewById(R.id.editText)).setText(result);
}
});
wr.execute("http://www.cheesejedi.com/rest_services/get_big_cheese?level=1");
}
});
Option 2: Use a library
If, however, you do want to use a library, I recommend droidQuery. Using this, you can simplify your code from this:
Button btn = (Button)findViewById(R.id.myshowbutton);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
WebRequest wr=new WebRequest(view.getRootView());
wr.execute("http://www.cheesejedi.com/rest_services/get_big_cheese?level=1");
}
});
to:
$.with(this, R.id.myshowbutton).click(new Function() {
#Override
public void invoke($ d, Object... args) {
$.ajax(new AjaxOptions().url("http://www.cheesejedi.com/rest_services/get_big_cheese?level=1").success(new Function() {
#Override
public void invoke($ d, Object... args) {
$.with(MyActivity.this, R.id.editText).text(args[0].toString());
}
}));
}
});
and you no longer need your WebRequest class.
The main problem with handing in a reference to a view into your AsyncTask is what happens when the Activity is destroyed and recreated for example in case of an orientation change (turning the device). In this case you can leak a reference to the Activity, which can get expensive memory-wise.
There are a couple of libraries around that try to help with this kind of problems. Maybe have a look at RoboSpice also.
If you want to decouple the EditText from your WebRequest, consider making a callback interface for your MainActivity to implement.
MainActivity.java
public class MainActivity extends ActionBarActivity implements WebRequestCallback {
...
#Override
public void handleStringResult(String result) {
btn.setText(result);
}
...
#Override
protected void onCreate(Bundle savedInstanceState) {
...
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
WebRequest wr = new WebRequest(this);
wr.execute("http://www.cheesejedi.com/rest_services/get_big_cheese?level=1");
}
});
}
...
}
WebRequestCallback.java
public interface WebRequestCallback {
public void handleStringResult(String result);
}
WebRequest.java
public class WebRequest extends AsyncTask<String, String, String> {
private WebRequestCallback callback;
public WebRequest(WebRequestCallback callback) {
this.callback = callback;
}
#Override
protected String doInBackground(String... uri) {
...
}
#Override
protected void onPostExecute(String result) {
callback.handleStringResult(result);
}
}
Also, while I have not used it myself, I have heard good things about Ion if you are looking for a more robust Android networking library.
I recently started developing programs in Android, and have a small problem with this simple code. I am trying to parse the title of a website and stored in a string, but so far unsuccessful. Is it because I am not doing it in Async ? Or can it be a different issues all together?
public class MainActivity extends Activity implements OnClickListener {
private Button btnSearch;
private EditText editTextCarReg;
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//-------------------------------------------------
btnSearch = (Button) findViewById(R.id.btnSearch);
btnSearch.setOnClickListener(this);
//------------------------------------------------
editTextCarReg = (EditText) findViewById(R.id.editTextRegistration);
editTextCarReg.setOnClickListener(this);
}
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void example() throws IOException
{
Document doc = Jsoup.connect("http://http://9gag.com/").get();
String title = doc.title();
}
public void onClick(View v)
{
if(v.getId() == btnSearch.getId())
{
try {
example();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
}
From your logs:
android.os.NetworkOnMainThreadException
This exception is thrown when an application attempts to perform a networking operation on its main thread.
Run Jsoup logic in AsyncTask.
(be sure that you added <uses-permission android:name="android.permission.INTERNET"/> as well)
You can write something like:
class JsoupTask extends AsyncTask<String, Void, Void> {
private Exception exception;
protected void doInBackground(String... url) {
Document doc = Jsoup.connect(url).get();
String title = doc.title();
...
}
protected void onPostExecute(RSSFeed feed) {
// here you can update your UI thread through Handler, for example
}
}
And call, like:
new JsoupTask().execute(url);
public static int SDK_INT = android.os.Build.VERSION.SDK_INT;
write this code before your request
if (SDK_INT >= 10) {
ThreadPolicy tp = ThreadPolicy.LAX;
StrictMode.setThreadPolicy(tp);
}
Using asynctask is better practice.
I have an android app that I am having trouble with.
Basically the ProgressDialog is not showing at all. I believe this to be a threading issue of some sort but I don't know how to fix it.
I am using ActionBarSherlock with some Fragments. I am also using the new Android DrawerLayout where I have my options on the drawer, which replace a fragment when clicked.
On first load of my app, I want to check the database to see if the inital data has been downloaded. If not, then I go off and begin an AsyncTask to download the data. This SHOULD have a ProgressDialog display during this, but it doesnt.
Can someone see where I am going wrong? Thanks.
MainScreen - The default landing page/fragment when the app opens
public class MainScreen extends SherlockFragment {
public static final String TAG = "MainScreen";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.activity_main, container, false);
setHasOptionsMenu(false);
ImageView imgLogo = (ImageView) rootView.findViewById(R.id.imgMainScreen);
imgLogo.setOnClickListener(new ButtonHandler(getActivity()));
checkDatabase();
return rootView;
}
private void checkDatabase() {
//Ensure there is data in the database
DBHelper db = new DBHelper(this.getSherlockActivity());
db.checkDatabase();
}
...
}
DBHelper.checkDatabase() - The method that initiates the download
public void checkDatabase() {
if (isEmpty()) {
//Connect to net and download data
NetworkManager nm = new NetworkManager(activity);
if (!nm.downloadData()) {
Toast.makeText(activity, R.string.internetCheck, Toast.LENGTH_SHORT).show();
}
}
}
and finally
NetworkManager.downloadData() - The method that kicks off the AsyncTask:
public boolean downloadData() {
try {
return new HttpConnection(activity).execute().get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return false;
}
public class HttpConnection extends AsyncTask<Void, Void, Boolean> {
private ProgressDialog progressDialog;
private Activity m_activity;
protected HttpConnection(Activity activity) {
m_activity = activity;
}
#Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(m_activity);
progressDialog.setMessage("Wait ...");
progressDialog.setCancelable(false);
progressDialog.setMax(100);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.show();
super.onPreExecute();
}
#Override
protected Boolean doInBackground(Void... params) {
String[] types = new String[]{"type1", "type2", "type3", "type4", };
StringBuilder sb = new StringBuilder();
for(String type : types) {
sb = new StringBuilder();
if(DBHelper.TYPE4_TABLE.equals(type)) {
InputStream is = activity.getResources().openRawResource(R.raw.dbdata);
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
try {
sb.append(reader.readLine());
} catch (IOException e) {
Toast.makeText(activity.getApplicationContext(), "Error retriveving data", Toast.LENGTH_SHORT).show();
Log.e(Constants.TAG, "Error reading data");
e.printStackTrace();
}
} else {
sb = fetchURLData(Constants.ALL_URL+type);
}
cleanDataAndStore(sb, type);
}
return true;
}
#Override
protected void onPostExecute(Boolean result){
progressDialog.hide();
}
}
Using the above code, all I get is a white screen as the app tries to load, and sometimes an ANR. When the download is done, the fragment loads. So it works fine except for the missing ProgressDialog.
PS, Notice I'm setting the activity in each constructor.
Thanks.
Remove .get() from return new HttpConnection(activity).execute().get(); You are basically locking your UI thread. Once removed it should work as AsyncTasks are expected to work.
The purpose is to be Asynchronous so boolean downloadData() should have a return type of void. If you need to do something with the data then you should implement an interface "listener" and pass it to the AsyncTask.
Example Listener:
class TaskConnect extends AsyncTask<Void, Void, ConnectionResponse> {
private final AsyncTaskListener mListener;
/**
*
*/
public TaskConnect(AsyncTaskListener listener) {
...
mListener = listener;
}
#Override
protected void onPreExecute() {
if (mListener != null) {
mListener.onPreExecute(mId);
}
}
#Override
protected ConnectionResponse doInBackground(Void... cData) {
...
return responseData;
}
#Override
protected void onPostExecute(ConnectionResponse response) {
if (mListener != null) {
mListener.onComplete(response);
} else {
LOG.w("No AsyncTaskListener!", new Throwable());
}
}
}
public interface AsyncTaskListener {
public abstract void onPreExecute(int id);
public abstract void onComplete(ConnectionResponse response);
}
My issue was not the common issue of others where they were calling get() method after execute() method. My issue was the Context I was passing to my AsyncTask method. I have a settingsActivity and I have a ReadMeActivity that calls the asynctask task. Instead of using the context in which is was being called (ReadMeActivity.this) I used the settingsActivity which prevented it from being seen. Once I switched it and passed it the context in which the activity was being called it worked.
Hope it helps someone else.
First of all, I am relatively new to android programming.
I am creating a ViewPager application with two Fragments. One of the Fragments requests data from a server and return a result to the main FragmentActivity. My problem is that this request to the server can take sometime, and I have been trying to get a ProgressDialog to appear with AsyncTask while the user waits for the data to be retrieved. Once I create the background thread to retrieve the data, I successfully execute some code in the onPostExecute() method and set some variables. However, the return statement that sends information back to the FragmentActivity is being executed before the background thread actually ends. I can't seem to figure out a way for the main thread to wait on the background thread. Using Asyctask's get() method results in the ProgressDialog from appearing. I have looked through a lot of posts in here, but can't seem to find an answer.
Anything helps.
Code below:
SplashScreen.java
public class SplashScreen extends FragmentActivity {
MainMenu mainMenu;
MapScreen mapScreen;
PagerAdapter pagerAdapter;
ViewPager viewPager;
List<LatLng> geoPoints;
private Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_splash_screen);
context = this;
initializePaging();
}
private void initializePaging()
{
mainMenu = new MainMenu();
mapScreen = new MapScreen();
pagerAdapter = new PagerAdapter(getSupportFragmentManager());
pagerAdapter.addFragment(mainMenu);
pagerAdapter.addFragment(mapScreen);
viewPager = (ViewPager) super.findViewById(R.id.viewPager);
viewPager.setAdapter(pagerAdapter);
viewPager.setOffscreenPageLimit(2);
viewPager.setCurrentItem(0);
viewPager.setOnPageChangeListener(new OnPageChangeListener()
{
#Override
public void onPageScrollStateChanged(int postion){}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2){}
#Override
public void onPageSelected(int position)
{
switch(position){
case 0: findViewById(R.id.first_tab).setVisibility(View.VISIBLE);
findViewById(R.id.second_tab).setVisibility(View.INVISIBLE);
break;
case 1: findViewById(R.id.first_tab).setVisibility(View.INVISIBLE);
findViewById(R.id.second_tab).setVisibility(View.VISIBLE);
break;
}
}
});
}
//Called from onClick in main_mainu.xml
public void getDirections(View view)
{
InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
try
{
geoPoints = mainMenu.getDirections(context);
mapScreen.plotPoints(geoPoints);
}
catch(Exception e)
{
Toast.makeText(getApplicationContext(), "Error! Invalid address entered.", Toast.LENGTH_LONG).show();
mainMenu.clear();
}
}
}
MainMenu.java
public class MainMenu extends Fragment {
String testString;
int testInt;
TextView testTV;
private TextView tvDisplay;
private EditText departure;
private EditText destination;
private Geocoder geocoder;
private List<Address> departAddress;
private List<Address> destinationAddress;
private List<LatLng> geoPoints;
private String departString;
private String destinationString;
private Address departLocation;
private Address destinationLocation;
private LatLng departurePoint;
private LatLng destinationPoint;
private Context contextMain;
private GetData task;
public MainMenu()
{
super();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View root = (View) inflater.inflate(R.layout.main_menu, null);
geoPoints = new ArrayList<LatLng>(2);
return root;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
departure = (EditText) getView().findViewById(R.id.depart_field);
destination = (EditText) getView().findViewById(R.id.destination_field);
tvDisplay = (TextView) getView().findViewById(R.id.textView1);
}
public List<LatLng> getDirections(Context context)
{
contextMain = context;
geocoder = new Geocoder(getActivity());
departString = departure.getText().toString();
destinationString = destination.getText().toString();
try
{
task = new GetData(new Callback(){
public void run(Object result)
{
//return geoPoints;
}
});
task.execute((Void[])null);
}catch(Exception e)
{
e.printStackTrace();
}
return geoPoints;
}
public void clear()
{
departure.setText("");
destination.setText("");
tvDisplay.setText("Enter departure point, and destination point");
}
private class GetData extends AsyncTask<Void, Void, List<List<Address>>>
{
Callback callback;
private ProgressDialog processing;
public GetData(Callback callback)
{
this.callback = callback;
}
#Override
protected void onPreExecute()
{
processing = new ProgressDialog(contextMain);
processing.setTitle("Processing...");
processing.setMessage("Please wait.");
processing.setCancelable(false);
processing.setIndeterminate(true);
processing.show();
}
#Override
protected List<List<Address>> doInBackground(Void...arg0)
{
List<List<Address>> list = new ArrayList<List<Address>>(2);
try
{
departAddress = geocoder.getFromLocationName(departString, 5, 37.357059, -123.035889, 38.414862, -121.723022);
destinationAddress = geocoder.getFromLocationName(destinationString, 5, 37.357059, -123.035889, 38.414862, -121.723022);
list.add(departAddress);
list.add(destinationAddress);
}catch(IOException e)
{
e.printStackTrace();
}
return list;
}
#Override
protected void onPostExecute(List<List<Address>> list)
{
departLocation = list.get(0).get(0);
destinationLocation = list.get(1).get(0);
departurePoint = new LatLng(departLocation.getLatitude(), departLocation.getLongitude());
destinationPoint = new LatLng(destinationLocation.getLatitude(), destinationLocation.getLongitude());
if(geoPoints.size() >= 2)
{
geoPoints.clear();
}
geoPoints.add(departurePoint);
geoPoints.add(destinationPoint);
callback.run(list);
processing.dismiss();
}
}
}
#Override
protected Object doInBackground(Void...arg0)
{
Object result = null;
try
{
departAddress = geocoder.getFromLocationName(departString, 5, 37.357059, -123.035889, 38.414862, -121.723022);
destinationAddress = geocoder.getFromLocationName(destinationString, 5, 37.357059, -123.035889, 38.414862, -121.723022);
}catch(IOException e)
{
e.printStackTrace();
}
return result;
}
You never set the value of result...
I have two major classes in my project. The first is for creating the connection between the client and the server. The second is for switching between activities.
first:
public class MyActivity extends Activity{
private ListView mList;
private ArrayList<String> arrayList;
private MyCustomAdapter mAdapter;
public TCPClient mTcpClient;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
boolean flag = getIntent().getBooleanExtra("flag",false);
arrayList = new ArrayList<String>();
final EditText editText = (EditText) findViewById(R.id.editText);
Button send = (Button)findViewById(R.id.send_button);
Button menu = (Button)findViewById(R.id.button1);
if (flag == true)
{
//relate the listView from java to the one created in xml
mList = (ListView)findViewById(R.id.list);
mAdapter = new MyCustomAdapter(this, arrayList);
mList.setAdapter(mAdapter);
new connectTask().execute("");
Intent myIntent = new Intent(MyActivity.this,Menu.class);
startActivity(myIntent);
}
send.setOnClickListener(new View.OnClickListener() {
// #Override
public void onClick(View view) {
String message = editText.getText().toString();
//clean the listView to 1 item
if (message.equals("clean"))
{
arrayList.removeAll(arrayList);
mList.removeAllViewsInLayout();
}
//add the text in the arrayList
arrayList.add("c: " + message);
//sends the message to the server
if (mTcpClient != null) {
mTcpClient.sendMessage(message);
}
//refresh the list
mAdapter.notifyDataSetChanged();
editText.setText("");
}
});
//change Activity to live screen mode (live)
menu.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent myIntent = new Intent(MyActivity.this, Menu.class);
startActivity(myIntent);
}
});
}
public class connectTask extends AsyncTask<String,String,TCPClient> {
#Override
protected TCPClient doInBackground(String... message) {
//we create a TCPClient object and
mTcpClient = new TCPClient(new TCPClient.OnMessageReceived() {
// #Override
//print the message as an Item
public void messageReceived(String message) {
//this method calls the onProgressUpdate
publishProgress(message);
}
});
mTcpClient.run();
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
//in the arrayList we add the messaged received from server
arrayList.add(values[0]);
// notify the adapter that the data set has changed. This means that new message received
// from server was added to the list
mAdapter.notifyDataSetChanged();
}
}
}
the object TCPClient mTcpClient is the major factor in my app. I use it communicate with the server. In addition, even if I switch between activities it is still running properly so I still get info from server even though I am not in that activity.
second:
public class Menu extends Activity
{
public MyActivity myActivity;
public TCPClient mtcp;
protected void onCreate(Bundle savedInstanceState, MyActivity myActivity)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.menu);
ImageView action = (ImageView) findViewById(R.id.imageView1);
action.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event)
{
// here I would like to use mTcpClient object mentioned in the first class
return false;
}
});
}
Basically what I need is a help on how to create in the second class reference to the object mTcpClient that is described in the first class.
You are doing it wrong. If you want to use TcpClient class regardless of context it should NOT be related to first Activity. What you should do is to use singleton pattern:
class TcpClient {
protected static TcpClient mInstance = null;
public TcpClient() {
// your init code...
}
public static TcpClient getInstance() {
if( mInstance == null ) {
mInstance = new TcpClient();
}
return mInstance;
}
...
}
and then, whenever you want to use TcpClient you just do:
TcpClient client = TcpClient.getInstance();