pass object stream use intent method - android

how can I pass object stream (exmple: BufferedReader or DataOutputStream n etc) to other activity (from Client_layoutActivity.class to chat_wall.class ) if i use intent method like this:
Intent i = new Intent(Client_layoutActivity.this, chat_wall.class);
startActivity(i);
I made a chat application that consists of several pages. The first page is the login page. in the first page, client use socket to communicated with server. After login process is success than server will send "login success". After that clien side will change layout from first page (login page) to second page (chat wall page). I mean to use socket, BufferedReader and DataOuputstream method from first page (i assume socket for login process is still connected so i can still used this socket to communicate in second page - chatting process). So i want to pass object Socket, BufferedReader and DataOuputstream to second page to used this. i write my code bellow:
PAGE 1 : for login purpose
public void login(){
try {
String name = usrname.getText().toString(); // usrname is android object edit
text
String pass = password.getText().toString();// password is android
object edit text
String sending = "login."+name + "." + pass + "." +"\n";
System.out.println("Sending Message: "+sending);
Socket clientsock = new Socket("192.168.136.6", 28000);
System.out.println("connect to the server...");
BufferedReader in = new BufferedReader(new
InputStreamReader(clientsock.getInputStream()));
DataOutputStream out = new DataOutputStream(clientsock.getOutputStream());
out.writeBytes(sending);
String line = in.readLine();
if (line.contentEquals("login success")){
Toast.makeText(this, "login success", Toast.LENGTH_SHORT).show();
Toast.makeText(this, "receive data from
server:"+clientsock.getInetAddress(), Toast.LENGTH_SHORT).show();
Intent i = new Intent(Client_layoutActivity.this, chat_wall.class);
startActivity(i);
} else {
Toast.makeText(this, "Error ", Toast.LENGTH_SHORT).show();
}
}
catch (Exception e)
{
System.out.println(e);
System.out.println("Connection Failed");
}
PAGE 2 : for Chat purpose
package com.willis.layout;
import java.io.*;
import java.net.*;
import android.widget.*;
import android.os.Bundle;
import android.view.*;
import android.view.View.OnClickListener;
import android.app.Activity;
import android.R.integer;
public class chat_wall extends Activity {
Client_layoutActivity ob;
public EditText chatroom;
public Button sendbtn;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.chatwall);
sendbtn = (Button)findViewById(R.id.sendmsg);
sendbtn.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
sendingmsg();
}
});
chatroom = (EditText)findViewById(R.id.chatroom);
}
public void sendingmsg (){
try
{
BufferedReader in = new BufferedReader(new
InputStreamReader(clientsock.getInputStream()));
DataOutputStream out = new DataOutputStream(clientsock.getOutputStream());
String name = chatroom.getText().toString();
String send = "chat."+name+". \n";
System.out.println("Sending message: "+send);
out.writeBytes(send);
String msgin = in.readLine();
Toast.makeText(this, msgin, Toast.LENGTH_SHORT).show();
}
catch (Exception e)
{
System.out.println(e);
System.out.println("Connection Failed");
}
}
}

As I understood what you want is to use the same socket for login and chat purposes. Instead of sending a Socket object with Intent between activities consider another options:
Define a class to manage opened sockets and create it's static instance or make it a Singleton.
Use a local Service as described in documentation. Define your sendingmsg and login methods in it and bind with Activity on it's onResume:
private ChatService mService;
...
#Override
protected void onResume() {
doBindService();
sendbtn.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
mService.sendingmsg();
}
});
}
#Override
protected void onPause() {
doUnbindService();
}

Related

error: package net.sourceforge.jtds.jdbc does not exist

i'm trying to connect to SQL Server Database from android studio
i'm using jtds and already import "jtds-1.3.1.jar" module to android studio
in the import part below line i got error
import net.sourceforge.jtds.jdbc.*;
and the error is:
"error: package net.sourceforge.jtds.jdbc does not exist"
. i don't know what i miss.
package com.example.mycar4;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.StrictMode;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import net.sourceforge.jtds.jdbc.*;
public class database extends AppCompatActivity {
// Declaring layout button, edit texts
Button login;
EditText username,password;
ProgressBar progressBar;
// End Declaring layout button, edit texts
// Declaring connection variables
Connection con;
String un,pass,db,ip;
String usernam,passwordd;
//End Declaring connection variables
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_database);
// Getting values from button, texts and progress bar
login = (Button) findViewById(R.id.btn_Login);
username = (EditText) findViewById(R.id.et_username);
password = (EditText) findViewById(R.id.et_password);
progressBar = (ProgressBar) findViewById(R.id.pbbar);
progressBar.setVisibility(View.GONE);
// End Getting values from button, texts and progress bar
// Declaring Server ip, username, database name and password
ip = "***";
db = "***";
un = "***";
pass = "***";
// Declaring Server ip, username, database name and password
// Setting up the function when button login is clicked
login.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
usernam = username.getText().toString();
passwordd = password.getText().toString();
CheckLogin checkLogin = new CheckLogin();// this is the Asynctask, which is used to process in background to reduce load on app process
checkLogin.execute("");
}
});
//End Setting up the function when button login is clicked
}
public class CheckLogin extends AsyncTask<String,String,String>
{
String z = "";
Boolean isSuccess = false;
#Override
protected void onPreExecute()
{
progressBar.setVisibility(View.VISIBLE);
}
#Override
protected void onPostExecute(String r)
{
progressBar.setVisibility(View.GONE);
Toast.makeText(database.this, r, Toast.LENGTH_SHORT).show();
if(isSuccess)
{
Toast.makeText(database.this , "Login Successfull" , Toast.LENGTH_LONG).show();
//finish();
}
}
#Override
protected String doInBackground(String... params)
{
if(usernam.trim().equals("")|| passwordd.trim().equals(""))
z = "Please enter Username and Password";
else
{
try
{
con = connectionclass(un, pass, db, ip); // Connect to database
if (con == null)
{
z = "Check Your Internet Access!";
}
else
{
String query = "select * from login where username= '" + usernam.toString() + "' and password = '"+ passwordd.toString() +"' ";
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query);
if(rs.next())
{
z = "Login successful";
isSuccess=true;
con.close();
}
else
{
z = "Invalid Credentials!";
isSuccess = false;
}
}
}
catch (Exception ex)
{
isSuccess = false;
z = ex.getMessage();
}
}
return z;
}
}
#SuppressLint("NewApi")
public Connection connectionclass(String user, String password, String database, String server)
{
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Connection connection = null;
String ConnectionURL = null;
try
{
Class.forName("net.sourceforge.jtds.jdbc.Driver").newInstance();
ConnectionURL = "jdbc:jtds:sqlserver://sql5009.mywindowshosting.com;database=DB_A2C00B_login;user=DB_A2C00B_login_admin;password=login#123";
// ConnectionURL =
"jdbc:jtds:sqlserver://192.168.1.9;database=msss;instance=SQLEXPRESS;Network
Protocol=NamedPipes" ;
connection = DriverManager.getConnection(ConnectionURL);
}
catch (SQLException se)
{
Log.e("error here 1 : ", se.getMessage());
}
catch (ClassNotFoundException e)
{
Log.e("error here 2 : ", e.getMessage());
}
catch (Exception e)
{
Log.e("error here 3 : ", e.getMessage());
}
return connection;
}
}
To connect an Android App with a SQL server, you'll need to set up a web (Http) server in between the two. You can build this web server in any language you're familiar with be it java (J2EE) or php etc.
This web server will be hosted with your SQL server and will take Http requests from the Android app, process it, forward the request as queries to your SQL server and then return it back to your app as REST/JSON (the current format of sending data over the web) or SOAP/XML (the old way of sending data over the web).
App >> Web Server >> Database Server
The web server should be RESTful and the app can interact with it via Http requests via the library Retrofit2.
Here's some resources to get you started;
Retrofit by Square.
Retrofit Github repository.
Simple CRUD example with Java RESTful Web Service, a brief tutorial.
RESTful Web Services: A Tutorial Android + Java Web Services
if you are using android studio or eclipse you should put the jtds jar file in the correct location
it is in the libs (library) folder inside app n your project. Once you put it in the libs > right click then add library.
another note you should use 1.2.7 or lower which is much supported

Connecting to FTP server using AsyncTask

I am quite new to android developing
I have written the following code to connect my android to a ftp server
package com.example.test1;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import org.apache.commons.net.ftp.*;
public class MainActivity extends Activity {
public FTPClient mFTPClient = null;
Button but;
public boolean ftpConnect(String host, String username, String password, int port) {
try {
mFTPClient = new FTPClient();
// connecting to the host
mFTPClient.connect(host, port);
// Now check the reply code, if positive mean connection success
if (FTPReply.isPositiveCompletion(mFTPClient.getReplyCode())) {
// Login using username & password
boolean status = mFTPClient.login(username, password);
mFTPClient.setFileType(FTP.BINARY_FILE_TYPE);
mFTPClient.enterLocalPassiveMode();
return status;
}
} catch(Exception e) {
CharSequence c = ""+e;
int d = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(getApplicationContext(),c,d);
toast.show();
}
return false;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
but=(Button)findViewById(R.id.button1);
but.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ftpConnect("127.0.0.1","userName","Password",21);
}
});
}
}
But this gives a networkOnMainThread Exception so after searching i found out i have to use AsyncTask but i have no idea how to implement it!
public void onClick(View v) {
new AsyncTask() {
publc Object doInBackground(Object...) {
try {
mFTPClient = new FTPClient();
// connecting to the host
mFTPClient.connect(host, port);
// Now check the reply code, if positive mean connection success
if (FTPReply.isPositiveCompletion(mFTPClient.getReplyCode())) {
// Login using username & password
boolean status = mFTPClient.login(username, password);
mFTPClient.setFileType(FTP.BINARY_FILE_TYPE);
mFTPClient.enterLocalPassiveMode();
return status;
}
} catch(Exception e) {
return e;
}
}
}
public void onPostExecute(Object res) {
if (res instanceof Exception) {
int d = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(getApplicationContext(),""+res,d);
toast.show();
}
}
}.execute();
Another temporary 'workaround' is to set your android:targetSdkVersion="9" or below in AndroidManifest.xml, as this exception was introduced in API level 10.
Documentation on Android Developers is pretty rich on such an important topic. You'll get it through with that.
http://developer.android.com/reference/android/os/AsyncTask.html
You may want to refer the NetworkConnect sample from the Android SDK.

Android Async Task Error with ClientService

I am creating simple system that has a windows service running, complete with a table of users, and I want to validate someone's login credentials by sending something to the service. I am trying to send their username and password, but I keep getting an error with my Async Task. I know that you're not supposed to mess with UI stuff in there and I am not. Originally I had a call to another activity in there but I commented it out. Now the only thing in doInBackground is setting a boolean value to true if the validation was good. From there I read the value after the async has executed, and then put together a bundle to move to the next place. I just don't know what's wrong here. It has been awhile since I've programmed in Android so maybe I'm missing something stupid. If anyone could help me out I would greatly appreciate it! Thank you. This could also be an issue with sending the information to the service?
UPDATE: After adding in the internet usage in the manifest, if I have the log.d in the program in my doInBackground, it prints out. If I don't have it, the result value stays false. It looks like there is some issue with the connection between my service and android app...
import java.util.ArrayList;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class LoginActivity extends Activity {
private static final int DATA_FROM_MAIN_ACTIVITY = 1;
private static final String SERVICEURL = "http://localhost:56638/ClientService.svc";
private EditText userTextBox, passTextBox;
private Button loginButton;
private String uName, pass;
private Boolean result = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
userTextBox = (EditText) findViewById(R.id.userTextBox);
passTextBox = (EditText) findViewById(R.id.passTextBox);
loginButton = (Button) findViewById(R.id.loginButton);
loginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
uName = userTextBox.getText().toString();
pass = passTextBox.getText().toString();
SendLoginMessage task = new SendLoginMessage();
task.execute(uName, pass);
if (result.equals(true)) {
Intent goToMainScreen = new Intent(getApplicationContext(),
MainActivity.class);
goToMainScreen.putExtra("username", uName);
goToMainScreen.putExtra("password", pass);
startActivityForResult(goToMainScreen,
DATA_FROM_MAIN_ACTIVITY);
} else {
Toast.makeText(
getApplicationContext(),
"There was an issue with your username or password.",
Toast.LENGTH_LONG).show();
}
}
});
}
#Override
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;
}
private class SendLoginMessage extends AsyncTask<String, String, Void> {
#Override
protected void onPreExecute() {
// Log.d("message almost at server, " + textFromArea, selected,
// null);
}
#Override
protected Void doInBackground(String... names) {
ArrayList<NameValuePair> postParams = new ArrayList<NameValuePair>();
postParams.add(new BasicNameValuePair("username", names[0]));
postParams.add(new BasicNameValuePair("password", names[1]));
String response = null;
try {
response = HttpClient.executeHttpPost(SERVICEURL, postParams);
String newResponse = response.toString();
newResponse = newResponse.replaceAll("\\s+", "");
// if user was authenticated...
if (newResponse.equals(true)) {
result = true;
// creating an intent to take user to next page.
// load their DB objects on the
// on create in other activity
// pass the username/password to next activity
// then make a request to the server for their database
// objects.
// Intent goToMainScreen = new
// Intent(getApplicationContext(), MainActivity.class);
// goToMainScreen.putExtra("username", names[0]);
// goToMainScreen.putExtra("password", names[1]);
// startActivityForResult(goToMainScreen,
// DATA_FROM_MAIN_ACTIVITY);
}
} catch (Exception e) {
Log.d("ERROR", "exception in background");
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// Toast.makeText(getApplicationContext(),
// .show();
}
}
}
Do it like this:
private class SendLoginMessage extends AsyncTask<String, String, Boolean> {
#Override
protected Boolean doInBackground(String... names) {
ArrayList<NameValuePair> postParams = new ArrayList<NameValuePair>();
postParams.add(new BasicNameValuePair("username", names[0]));
postParams.add(new BasicNameValuePair("password", names[1]));
String response = null;
try {
response = HttpClient.executeHttpPost(SERVICEURL, postParams);
String newResponse = response.toString();
newResponse = newResponse.replaceAll("\\s+", "");
// if user was authenticated...
if (newResponse.equals("true")) {
return true;
}
} catch (Exception e) {
Log.d("ERROR", "exception in background");
}
return false;
}
#Override
protected void onPostExecute(Boolean result) {
if (result) {
Intent goToMainScreen = new Intent(getApplicationContext(),
MainActivity.class);
goToMainScreen.putExtra("username", uName);
goToMainScreen.putExtra("password", pass);
startActivityForResult(goToMainScreen,
DATA_FROM_MAIN_ACTIVITY);
} else {
Toast.makeText(
getApplicationContext(),
"There was an issue with your username or password.",
Toast.LENGTH_LONG).show();
}
}
}
and in your onClick() just call execute()
uName = userTextBox.getText().toString();
pass = passTextBox.getText().toString();
SendLoginMessage task = new SendLoginMessage();
task.execute(uName, pass);
After execution is finished onPostExecute() will be called and your Activity will start depending on result variable.
Don't check your result variable after you invoke execute() because execute() is invoked asynchronously. By the time you check your global result variable, your doInBackground() might not have been finished. Using my approach you don't need a global variable. Please read doc carefully before using any component.

unable to run my android application

I am trying to establish a chatting application between a server and a client, but the application could not run because of this line of code : message = (String) input.readObject();
because at first, inputStream is null ! any one can help please ? here is my code
package com.example.test;
import java.io.BufferedReader;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.net.Socket;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.StrictMode;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
private Button send;
private Button connect;
private EditText userText;
private TextView chatWindow;
private String serverIP;
private ObjectOutputStream output;
private ObjectInputStream input;
private String message = "";
private Socket connection;
#SuppressLint({ "NewApi", "NewApi", "NewApi" })
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
serverIP = "192.168.1.4";
//userText.setEnabled(false);
send = (Button)findViewById(R.id.button1);
connect = (Button)findViewById(R.id.button2);
chatWindow =(TextView)findViewById(R.id.textView1);
userText = (EditText)findViewById(R.id.editText1);
userText.setHint("Enter your message here");
connect.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//connect to the server
try{
connectToServer();
setupStreams();
}catch(EOFException eofException){
showMessage("\n client terminated the connection");
}catch(IOException ioException){
ioException.printStackTrace();
}
}
});
send.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String message = userText.getText().toString();
sendMessage(message);
userText.setText("");
}
});
while(true){
try{
message = (String) input.readObject();
showMessage("\n" + message + " NULL ");
chatWindow.refreshDrawableState();
}catch(ClassNotFoundException classNotFoundException){
showMessage("\n I don't know that object type");
}
catch(NullPointerException e){
e.printStackTrace();
}
catch (OptionalDataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} // end of onCreate
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
//connect to the server
private void connectToServer() throws IOException {
showMessage("Attempting connection... \n");
connection = new Socket( "192.168.1.4", 6789);
showMessage("Connected to " + connection.getInetAddress().getHostName() );
}
//setup streams to send and receive messages
private void setupStreams() throws IOException{
output = new ObjectOutputStream(connection.getOutputStream());
output.flush();
input = new ObjectInputStream(connection.getInputStream());
showMessage("\n Your streams are now good to go! \n ");
}
//whileChatting with server
private void whileChatting() throws IOException{
try{
message = (String) input.readObject();
showMessage("\n" + message + " NULL ");
chatWindow.refreshDrawableState();
}catch(ClassNotFoundException classNotFoundException){
showMessage("\n I don't know that object type");
}
}
//close the streams and sockets
private void closeCrap(){
showMessage("\n closing crap down");
ableToType(false);
try{
output.close();
input.close();
connection.close();
}catch(IOException ioException){
ioException.printStackTrace();
}
}
// gives user permission to type into the text box
private void ableToType(final boolean tof){
userText.setEnabled(tof);
}
// send messages to server
private void sendMessage(String message){
try{
output.writeObject("CLIENT - " + message);
output.flush();
showMessage("\nCLIENT - " + message);
}catch(IOException ioException){
chatWindow.append("\n somethine messed up sending message!");
}
}
//change/update chatWindow
private void showMessage(final String m){
chatWindow.append(m);
chatWindow.refreshDrawableState();
}
} // end of class MainActivity
Your code is definitely not following any good UI guidelines: You are doing network operations on the Main (UI) Thread, and you have an infinite loop in onCreate(). Android should actually offer to force close your app if nothing crashes. Now, a likely cause for the null problem you are facing:
setupStreams() is only called upon a button click. However, your while (true) loop is in the root of onCreate(). This means that as soon as the click listeners are made and set, the loop runs, attempts to read in from input and fails since setupStreams() hasn't been called.
So please don't do away with StrictMode - it's there to help, and thing about your code from an event driven standpoint ("Once X happens, then do Y"). And also get rid of loops in the Main (UI) Thread. Loops are fine for Console windows, but with UIs (which have their own complex lifecycle), you can't do this without freezing a lot of things.
Do all of your network tasks in doInBackground() ofAsyncTask then update your UI variables in onPostExecute(). Something like
public class TalkToServer extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
#Override
protected String doInBackground(String... params) {
//do your work here
return something;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// do something with data here-display it or send to mainactivity
}
Here is the documentation on AsyncTask
Another thing to consider is you are using the variable message in different places which may cause you problems. It looks like you have it defined as a member variable then as a local variable to other methods. You don't want to re-use the same variable name this way. Don't define String message multiple times in the same Activity

App using AsyncTask still hogging the UI thread?

I've written an app that sits in the 'Share via' menu (for quickly emailing myself links to things I find on the web or look at in RSS readers) For this I'm using an intent.action.SEND intent-filter:
<activity
android:name="uk.co.baroquedub.checkit.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
Here's the MainActivity package, it grabs the page title and url from the Intent and uses a separate GMailSender class to directly email me this info:
package uk.co.baroquedub.checkit;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends Activity {
private static Dialog dialog;
String title;
String url;
String message;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
intent.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP );
String action = intent.getAction();
// if this is from the share menu
if (Intent.ACTION_SEND.equals(action)) {
title = intent.getStringExtra(Intent.EXTRA_SUBJECT);
url = intent.getStringExtra(Intent.EXTRA_TEXT);
// Flipboard fix (remove title in URL)
url = url.replace(title, "");
if (url != null){
url = title+"\n"+url;
} else {
url = "error getting URL";
}
// Asynch Task
doSendTask task = new doSendTask();
task.execute(new String[] { url });
}
}
protected void showDialog (String response){
dialog = new Dialog(this);
dialog.setContentView(R.layout.dialog);
dialog.setTitle(response);
Button button = (Button) dialog.findViewById(R.id.Button01);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dialog.dismiss();
finish();
}
});
dialog.show();
}
private class doSendTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String response = "";
String senderPassword = getResources().getString(R.string.senderPassword);
String senderEmail = getResources().getString(R.string.senderEmail);
String recipientEmail = getResources().getString(R.string.recipientEmail);
String subjectText = getResources().getString(R.string.subjectText);
GMailSender sender = new GMailSender(senderEmail, senderPassword);
try {
sender.sendMail(subjectText,
url,
senderEmail,
recipientEmail);
response = "Email sent";
} catch (Exception e) {
//Log.e("SendMail", e.getMessage(), e);
response = "Error sending email";
}
return response;
}
#Override
protected void onPostExecute(String result) {
showDialog(result);
}
}
#Override
public void onDestroy() {
super.onDestroy();
/*
* Kill application when the root activity is killed.
*/
UIHelper.killApp(true);
}
}
Version 1 worked fine but I was sending the email from within 'onCreate' which meant that until the "Email sent" notification appeared, the phone's browser would be unresponsive (I wasn't able to scroll or navigate to a new page). I then changed the code (as per above) to place the email sending code inside an AsyncTask class - but although the app still works the browser remains unresponsive until the dialog appears. AsyncTask seems to have made no difference.
Can anyone explain why, and hopefully suggest a solution?
ANSWER?... I've massively simplified the above code to try to work out what might be wrong. I created a bog standard App and used the following:
package uk.co.baroquedub.testcheck;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
doSendTask task = new doSendTask();
task.execute(new String[] { "urlString" });
}
protected void showDialog (String response){
Toast.makeText(this, response, Toast.LENGTH_SHORT).show();
finish();
}
private class doSendTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String response = "";
try {
Thread.sleep(5000);
response = "Waited";
}
catch (InterruptedException ex) { }
return response;
}
#Override
protected void onPostExecute(String result) {
showDialog(result);
}
}
}
This has allowed me to see what's going wrong: my app is opening on top of the browser (a white screen appears with a title bar showing the name of the app) I wasn't aware of this with my proper app (above) because I was using a Theme that used a transparent background.
See: screencast for demo of problem
So although the email is being sent as an AsyncTask, while this is happening the app itself is appearing on top of the browser - which is what is stopping it from being accessible. (I'll post a request for help on this as a separate question)
No, AsyncTask is not bond to your UI thread and you will not be blocking it as you did while doing some lengthy operation in your onCreate().
I think you have a mistake in your code:
doSendTask task = new doSendTask();
task.execute(url); // if you want to put more urls task.execute(url,url1,url2);
try {
sender.sendMail(subjectText,
url[0], // get the first url
senderEmail,
recipientEmail);
response = "Email sent";
} catch (Exception e) {
//Log.e("SendMail", e.getMessage(), e);
response = "Error sending email";
}
ASyncTasks are, indeed, executed on their own thread, as written on their reference page.
When you create the intent for this activity, you pass the flag 'FLAG_ACTIVITY_CLEAR_TOP', which reads something like '...all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent.'. Doesn't this mean that the old activity is locked until this new one terminates?

Categories

Resources