I am new to android development . I am making a small email client using javamail api . I am not able to find a solution on how will that activity start . Below is my code file for email manager which I want to start when I run the application .
I just need a way to start this , I am really confused with the android activities and have clue how to implement them
Thanks in Advance :)
package com.mailtest.android;
import android.app.Activity;
import android.os.Bundle;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import android.view.View;
import android.os.Bundle;
import android.content.Intent;
import android.widget.Button;
public class EmailManager extends Activity {
**/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);**
}
private String stmpHost = "smtp.gmail.com";
private String mailServer = "imap.gmail.com";
private EmailAccount account;
private Session smtpSession;
private Session imapSession;
private Folder inbox;
private Store store;
public EmailManager(String username, String password, String urlServer, String stmpHost, String mailServer) {
account = new EmailAccount(username, password, urlServer);
this.stmpHost = stmpHost;
this.mailServer = mailServer;
initProtocol();
}
private void initProtocol() {
EmailAuthenticator authenticator = new EmailAuthenticator(account);
Properties props1 = new Properties();
props1.setProperty("mail.transport.protocol", "smtps");
props1.setProperty("mail.host", stmpHost);
props1.put("mail.smtp.auth", "true");
props1.put("mail.smtp.port", "465");
props1.put("mail.smtp.socketFactory.port", "465");
props1.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props1.put("mail.smtp.socketFactory.fallback", "false");
props1.setProperty("mail.smtp.quitwait", "false");
smtpSession = Session.getDefaultInstance(props1, authenticator);
Properties props2 = new Properties();
props2.setProperty("mail.store.protocol", "imaps");
props2.setProperty("mail.imaps.host", mailServer);
props2.setProperty("mail.imaps.port", "993");
props2.setProperty("mail.imaps.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props2.setProperty("mail.imaps.socketFactory.fallback", "false");
imapSession = Session.getInstance(props2);
}
public Message[] getMails() throws MessagingException {
store = imapSession.getStore("imaps");
store.connect(mailServer, account.username, account.password);
inbox = store.getFolder("Inbox");
inbox.open(Folder.READ_ONLY);
Message[] result = inbox.getMessages();
return result;
}
public void close() {
//Close connection
try {
inbox.close(false);
store.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public synchronized void sendMail(String subject, String body, String sender, String recipients) throws Exception {
MimeMessage message = new MimeMessage(smtpSession);
DataHandler handler = new DataHandler(new ByteArrayDataSource(body.getBytes(), "text/plain"));
message.setSender(new InternetAddress(sender));
message.setSubject(subject);
message.setDataHandler(handler);
if (recipients.indexOf(',') > 0)
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipients));
else
message.setRecipient(Message.RecipientType.TO, new InternetAddress(recipients));
Transport.send(message);
}
}
AND THIS IS MY MAIN.XML
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello"
/>
</LinearLayout>
First of, you might want to have the email manager in its own class since it´s not a necessity to extend it as an Activity. However, to answer your question you could have a look at http://developer.android.com/reference/android/app/Activity.html
This is just an example and let´s say that the activity that should start the other activity is called MainActivity.
Then put this in MainActivity:
startActivity(new Intent(MainActivity.this, EmailManager.class));
Just remember to put the Email Manager as an Activity in your AndroidManifest.xml
<activity android:name=".EmailManager"/>
Possible duplicate answer, more can be found here: How to start activity in another application?
Go back to read this: http://developer.android.com/reference/android/app/Activity.html
Do not extend Activity for your EmailManager, you don't need to, as EmailManager doesn't interact with the user interface and doesn't depend on any context.
Implement a separate Activity where you call the relevant EmailManager methods from the Activity methods (OnCreate, OnResume, etc.) OnCreate is where your activity starts by the way
When you get a better understanding of the lifecycle of android components you are better of moving things from your activity to a service: http://developer.android.com/reference/android/app/Service.html
This is again because you have no ui-interaction from your EmailManager, and the type of work your EmailManager does is better suited for a service.
Related
I've looked at many tutorials on this yet none of them seem to work so no idea whether it's the server, client or potentially something on my network that's stopping it I don't know, so I come here for help.
Just for reference this is the tutorial that this is mainly based on: https://socket.io/blog/native-socket-io-and-android/
So this is my server. All it's supposed to do at the moment is detect when a user connects and then detect users sending messages and send them back to all the clients.
index.js
const express = require("express");
const app = express();
const path = require("path");
const server = require("http").createServer(app);
const io = require("socket.io")(server);
server.listen(3000, () => {
console.log("Server listening at 3000");
});
app.use(express.static(path.join(__dirname, "public")));
io.on("connection", (socket) => {
console.log("User connected");
socket.on("new message", (data) => {
console.log("New message" + data)
socket.emit("new message", {
message: data
});
})
});
My Android client is made up of 3 classes. But to try and keep this shorter I'll only include 2 of them as if the problem can be found in these it's fixable in the 3rd.
This is what's launched at the start and simply pressing the button brings you to the main 'chat' part, but on clicking the button the server should log the connection but nothing appears in the console. So I can only assume the socket connection isn't working for some reason. Also you can ignore the nickname, I've not implemented that yet, been trying to get the main part working first.
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import io.socket.client.Socket;
public class MainActivity extends AppCompatActivity {
private EditText nickname;
private Button enterChat;
private Socket mSocket;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
nickname = findViewById(R.id.nickname);
enterChat = findViewById(R.id.enterChat);
ChatApplication app = (ChatApplication) getApplication();
mSocket = app.getSocket();
mSocket.connect();
enterChat.setOnClickListener(v -> {
mSocket.emit("connection");
Intent i = new Intent(MainActivity.this, ChatActivity.class);
i.putExtra("name", nickname.getText().toString());
startActivity(i);
});
}
}
This is just to be able to get the Socket from any other activity.
ChatApplication.java
import android.app.Application;
import java.net.URISyntaxException;
import io.socket.client.IO;
import io.socket.client.Socket;
public class ChatApplication extends Application {
private Socket mSocket;
{
try {
//My IPv4 address here
mSocket = IO.socket("http://xxx.xxx.x.xxx:3000");
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
public Socket getSocket() {
return mSocket;
}
}
Any help appreciated :)
Found the problem, I need to add this to the AndroidManifest.xml
<application
...
android:usesCleartextTraffic="true"
...
</application>
I'm trying to send an email automatically, without user confirmation in my Android App. I'm trying to do with Javamail, but when I try my app on my phone, it's close with the typical "APP STOPPED, Open again" Android message.
My code is:
SEND MAIL CLASS:
package com.android.mdw.demo;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import android.util.Log;
public class EnviarEmail {
public static String emailEnvio = "XXX#gmail.com";
public static String passwordEmailEnvio = "#XXX";
public void EnviarEmail(String Mensaje, String Asunto, String email) {
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.port", "587");
Session session = Session.getInstance(props,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(emailEnvio, passwordEmailEnvio);
}
});
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(emailEnvio));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse(email));
message.setSubject(Asunto);
message.setText(Mensaje);
Transport.send(message);
} catch (MessagingException e) {
Log.w("ERROR", "No se ha podido enviar el email de confirmación.");
}
}
}
NOTICE MAIL CLASS:
package com.android.mdw.demo;
public class EmailAviso {
public void EmailAviso () {
String Mensaje = "CUERPO";
String Asunto = "ASUNTO";
String email = "AQUIENVA#gmail.com";
EnviarEmail EnviarEmail = new EnviarEmail();
EnviarEmail.EnviarEmail(Mensaje, Asunto, email);
}
}
EXTRACT FROM MAIN CLASS:
boolean PRUEBA=true;
boolean PRUEBA1=true;
if(PRUEBA==true && PRUEBA1==true) {
EmailAviso EmailAviso = new EmailAviso();
EmailAviso.EmailAviso();
}
And the log I recive in AS is:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.android.mdw.demo, PID: 18001
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1303)
at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:86)
at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:74)
at java.net.InetAddress.getLocalHost(InetAddress.java:816)
at javax.mail.internet.InternetAddress.getLocalAddress(InternetAddress.java:517)
at javax.mail.internet.UniqueValue.getUniqueMessageIDValue(UniqueValue.java:99)
at javax.mail.internet.MimeMessage.updateMessageID(MimeMessage.java:2054)
at javax.mail.internet.MimeMessage.updateHeaders(MimeMessage.java:2076)
at javax.mail.internet.MimeMessage.saveChanges(MimeMessage.java:2042)
at javax.mail.Transport.send(Transport.java:117)
at com.android.mdw.demo.EnviarEmail.EnviarEmail(EnviarEmail.java:41)
at com.android.mdw.demo.EmailAviso.EmailAviso(EmailAviso.java:10)
at com.android.mdw.demo.Main.onSensorChanged(Main.java:77)
at android.hardware.SystemSensorManager$SensorEventQueue.dispatchSensorEvent(SystemSensorManager.java:699)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:323)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
you are trying to send email from main thread which is not allowed, try creating separate worker thread for sending email. Try something like following:
new Thread(new Runnable() {
#Override
public void run() {
if(PRUEBA==true && PRUEBA1==true) {
EmailAviso EmailAviso = new EmailAviso();
EmailAviso.EmailAviso();
}
}
}).start();
Sending email directly from Android is considered as a bad practice, as you'll have to store your email and password in the source code, and a simple APK decomile can compromise the credentials.
If you want to send email without user interaction, you'll have to use an external API to send mail, or you'll have to develop your own API using any server stack such as PHP,nodejs, JSP etc.
I've created a simple library named SafeMail to fix this issue. All you have to do is to get your API Key from here and use it like in this example.
Sorry for the minimal documentation. Feel free to shoot queries in the comments.
I'm not a very experienced coder, but I have been learning. Right now I am in the process of writing a test email bot to, well, send emails. I ran across a problem when I tried to make it so you could type out the message and subject of the email in a JOptionPane Dialog box.
Here is the code, look at the Strings at the top and the messageobjs at the bottom..
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.swing.JOptionPane;
public class Ebot2
{
public static void main(String[] args)
{
String Dest;
Dest = JOptionPane.showInputDialog("Who would you like to message?");
String Subject;
Subject = JOptionPane.showInputDialog("What is the message subject?");
String Message;
Message = JOptionPane.showInputDialog("What is the message?");
String sendrmailid = "email#gmail.com";
final String uname = "email";
final String pwd = "pass";
Properties propvls = new Properties();
propvls.put("mail.smtp.auth", "true");
propvls.put("mail.smtp.starttls.enable", "true");
propvls.put("mail.smtp.host", "smtp.gmail.com");
propvls.put("mail.smpt.port", "25");
Session sessionobj = Session.getInstance(propvls,
new javax.mail.Authenticator()
{
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(uname, pwd);
}
});
try
{
Message messageobj = new MimeMessage(sessionobj);
messageobj.setFrom(new InternetAddress(sendrmailid));
messageobj.setRecipients(Message.RecipientType.TO,InternetAddress.parse(Dest));
messageobj.setSubject(Subject);
messageobj.setText(Message);
Transport.send(messageobj);
System.out.println("Your email sent successfully....");
}
catch (MessagingException exp)
{
throw new RuntimeException(exp);
}
}
}
sorry for the shit formatting, the code block thing was difficult. Anyways the error Im getting started, after I changed the setSubject and setText to Strings that are entered through a JOptionPane. And the error is..
Ebot2.java:53: error: cannot find symbol
messageobj.setRecipients(Message.RecipientType.TO,InternetAddress.parse(Dest));
^
symbol: variable RecipientType
location: variable Message of type String
1 error
Thanks to anyone who answers, I really need help on this!
I fixed it guys. The problem was I had the String for the message set as Message (same problem with subject) which was also a variable. So I just renamed the string and it all worked. Thanks for the help anyways, glad to know I can go to this site for questions.
Next I'm going to try to figure out how to send the email multiple times, but I should be able to figure that out on my own.
I've been troubleshooting for a while and may be suffering from the XY problem so this will be fairly descriptive.
Goal: Send a simple email message on the click of a button without leveraging external mail app.
Research led to the JavaMail API, which was successfully compiled, tested, and executed on a personal computer.
So after spending some time reading answers here I followed these steps to add the library.
Right click on App -> New Module -> Import .JAR/.AAR Package.
Utilize ellipsis button to find and add the jar.
App -> Module Settings
Under Modules, App -> Dependencies -> Add -> Module Dependency -> Selecting the JAR module.
In addition to this, I also did the following:
Ensured the app module's build.gradle included the dependency (In this case, listed as compile project(':javax.mail')
On project root, use and run gradlew clean as well as gradlew build
This has been tried a few other, failing ways but these are the latest series of steps. Android Studio detects the files, but when executed the app crashes with a NoClassDefFoundError. Intuition says the problem is classpath but after trying several different but ineffective solutions for this it's time to yield to more experienced advice.
For reference:
MainActivity:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button testButton = (Button) findViewById(R.id.emailButton);
testButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Emailer.send(getApplicationContext());
}
});
}
}
Emailer:
import android.content.Context;
import android.widget.Toast;
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class Emailer {
public static void send(Context context) {
// Recipient's email
String recipient = "myemail#gmail.com";
// Sender information
String sender = "myemail#gmail.com";
final String username = "myUsername";
final String password = "myPassword";
String host = "smtp.gmail.com";
Properties properties = new Properties();
properties.put("mail.smtp.auth", "true");
properties.put("mail.smtp.socketFactory.port", "465");
properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.put("mail.smtp.host", host);
properties.put("mail.smtp.port", "25");
Session session = Session.getInstance(properties,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
try {
// constructing the email
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(sender));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipient));
message.setSubject("Email Test");
message.setText("Testing the email capability using JavaMailAPI on Android");
// Sending
Transport.send(message);
Toast.makeText(context, R.string.email_success, Toast.LENGTH_SHORT).show();
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
}
I am using an application to authorize a user in Twitter using Twitter4j library. I want to incorporate a feature, my mobile app opens. It has a login button on click of which Twitter login dialog appears and lets you enter the login information . after the login is complete, another screen opens.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.Toast;
public class AndTweetVJActivity extends Activity {
/** Called when the activity is first created. */
Twitter twitter;
RequestToken requestToken;
public final static String consumerKey = "myKey"; // "your key here";
public final static String consumerSecret = "myKey"; // "your secret key here";
private final String CALLBACKURL = "T4JOAuth://main"; //Callback URL that tells the WebView to load this activity when it finishes with twitter.com. (see manifest)
//Calls the OAuth login method as soon as its started
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
OAuthLogin();
}
/* Creates object of Twitter and sets consumerKey and consumerSecret
* - Prepares the URL accordingly and opens the WebView for the user to provide sign-in details
* - When user finishes signing-in, WebView opens your activity back */
void OAuthLogin() {
try {
twitter = new TwitterFactory().getInstance();
twitter.setOAuthConsumer(consumerKey, consumerSecret);
requestToken = twitter.getOAuthRequestToken(CALLBACKURL);
String authUrl = requestToken.getAuthenticationURL();
this.startActivity(new Intent(Intent.ACTION_VIEW, Uri
.parse(authUrl)));
} catch (TwitterException ex) {
Toast.makeText(this, ex.getMessage(), Toast.LENGTH_LONG).show();
Log.e("in Main.OAuthLogin", ex.getMessage());
}
}
/*
* - Called when WebView calls your activity back.(This happens when the user has finished signing in)
* - Extracts the verifier from the URI received
* - Extracts the token and secret from the URL
*/
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Uri uri = intent.getData();
try {
String verifier = uri.getQueryParameter("oauth_verifier");
AccessToken accessToken = twitter.getOAuthAccessToken(requestToken,verifier);
String token = accessToken.getToken(), secret = accessToken.getTokenSecret();
//displayTimeLine(token, secret); //after everything, display the first tweet
} catch (TwitterException ex) {
Log.e("Main.onNewIntent", "" + ex.getMessage());
}
}
}
however on running this application, it gives me error in logcat :
11-18 10:36:27.727: E/in Main.OAuthLogin(282): 401:Authentication credentials (https://dev.twitter.com/docs/auth) were missing or incorrect. Ensure that you have set valid conumer key/secret, access token/secret, and the system clock in in sync.
11-18 10:36:27.727: E/in Main.OAuthLogin(282): <?xml version="1.0" encoding="UTF-8"?>
11-18 10:36:27.727: E/in Main.OAuthLogin(282): <hash>
11-18 10:36:27.727: E/in Main.OAuthLogin(282): <error>Desktop applications only support the oauth_callback value 'oob'</error>
11-18 10:36:27.727: E/in Main.OAuthLogin(282): <request>/oauth/request_token</request>
11-18 10:36:27.727: E/in Main.OAuthLogin(282): </hash>
I believe i had not set up callback URL, but i did that as well to https://dev.twitter.com/pages/welcome-anywhere
in my app.
Make sure that you have not register your app in Desktop application category at twitter application registration.
My Bad... My Web server was down and i did not noticed it until 5 minutes ago. thanks for all suggestions. I have already done these things.