I am working on GCM.
I am able to send notifications to all registered android devices from my local server.
I have saving regid and userid in database. my requirement is send notifications to particular devices.how to do that?
am using java on server side. Any answers will save me..i posted server side code
server side code
public class GCMNotification extends HttpServlet {
private static final long serialVersionUID = 1L;
// Put your Google API Server Key here
private static final String GOOGLE_SERVER_KEY = "AIzaSyDzlDr2viv-EghBFZGpjwXcDoqh24Wt9yE";
static final String MESSAGE_KEY = "message";
static final String TITLE_KEY = "title";
static final String IMAGE_KEY= "image";
static final String ORDER_KEY= "order";
private List<String> androidTargets = new ArrayList<String>();
public GCMNotification() {
super();
// androidTargets.add(re);
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
//doPost(request, response);
Connection con=null;
try {
Class.forName("com.mysql.jdbc.Driver");
//Get a connection to the particular database
con=DriverManager.getConnection(
"jdbc:mysql://localhost:3306/my_db","root","root1");
String sql;
sql = "SELECT regid, fname, email FROM my_db.Persons";
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()){
//Retrieve by column name
int id = rs.getInt("regid");
String first = rs.getString("fname");
String last = rs.getString("email");
androidTargets.add(id);
}
rs.close();
stmt.close();
con .close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
response.setContentType("text/html");
PrintWriter pw = response.getWriter();
//MulticastResult result = null;
//Result result1=null;
Writer writer=null;
Connection con=null;
PrintWriter out = response.getWriter();
String share = request.getParameter("shareRegId");
// GCM RedgId of Android device to send push notification
String reg = "";
String emailId="";
String fname="";
if (share != null && !share.isEmpty()) {
reg = request.getParameter("regId");
emailId=request.getParameter("email");
fname=request.getParameter("name");
System.out.println("regId: " + reg);
System.out.println("mailid " + emailId);
System.out.println("name "+ fname);
try {
//Load the Driver for connection
Class.forName("com.mysql.jdbc.Driver");
//Get a connection to the particular database
con=DriverManager.getConnection(
"jdbc:mysql://localhost:3306/my_db","root","root1");
PreparedStatement pst=con.prepareStatement("insert into my_db.Persons(regid,email,fname) values(?,?,?)");
pst.setString(1,reg);
pst.setString(2,emailId);
pst.setString(3,fname);
int i = pst.executeUpdate();
if(i!=0){
pw.println("<br>Record has been inserted");
}
else{
pw.println("failed to insert the data");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MulticastResult result1=null;
String userMessage = request.getParameter("message");
String imageUrl = request.getParameter("image");
String order1=request.getParameter("odt");
String titl=request.getParameter("tit");
Sender sender = new Sender(GOOGLE_SERVER_KEY);
Message message = new Message.Builder().timeToLive(10000)
.delayWhileIdle(false)
.addData(TITLE_KEY, titl)
.addData(MESSAGE_KEY,userMessage)
.addData(IMAGE_KEY, imageUrl)
.addData(ORDER_KEY, order1)
.build();
try {
// use this for multicast messages. The second parameter
HashSet<String> set = new HashSet<String>(androidTargets);
// Create ArrayList from the set.
ArrayList<String> result = new ArrayList<String>(set);
System.out.println("reg2:"+result);
// of sender.send() will need to be an array of register ids.
result1 = sender.send(message, result,1);
/* if (result1.getResults() != null) {
int canonicalRegId = result1.getCanonicalIds();
if (canonicalRegId != 0) {
}
} else {
int error = result1.getFailure();
System.out.println("Broadcast failure: " + error);
}*/
} catch (Exception e) {
e.printStackTrace();
}
request.setAttribute("pushStatus", result1.toString());
request.getRequestDispatcher("index.jsp")
.forward(request, response);
}
}
Simply add a where clause to your sql query to filter out the exact user you want to deal with. If you want to filter the user by the email then use something like this..
sql = "SELECT regid, fname, email FROM my_db.Persons where email = 'abc#gmail.com'";
Related
So I'm back on Android Development, still getting to know stuff again, and this is the first time I make an app that connects to a database in a server.
So far I have used this code to be able to connect to the server and it works by showing that the "connection is true"
The only thing I want to know now is how I can use this same class to throw queries to do things like "SELECT * FROM TABLE" etc.
I know that it bad practice to do what I'm doing by connecting direct to a db, but this is just a very small app that will not do important stuff but just so I can understand things better in Android.
package com.example.databasetest;
import java.sql.Connection;
import java.sql.DriverManager;
public class Database {
private Connection connection;
private final String host = "xxxxx";
private final String database = "xxxx";
private final int port = "xxxx";
private final String user = "xxxx";
private final String pass = "xxxx";
private String url = "jdbc:postgresql://%s:%d/%s";
private boolean status;
public Database() {
this.url = String.format(this.url, this.host, this.port, this.database);
connect();
//this.disconnect();
System.out.println("connection status:" + status);
}
private void connect() {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
Class.forName("org.postgresql.Driver");
connection = DriverManager.getConnection(url, user, pass);
status = true;
System.out.println("connected:" + status);
} catch (Exception e) {
status = false;
System.out.print(e.getMessage());
e.printStackTrace();
}
}
});
thread.start();
try {
thread.join();
} catch (Exception e) {
e.printStackTrace();
this.status = false;
}
}
public Connection getExtraConnection(){
Connection c = null;
try {
Class.forName("org.postgresql.Driver");
c = DriverManager.getConnection(url, user, pass);
} catch (Exception e) {
e.printStackTrace();
}
return c;
}
}
This is my MainActivity:
package com.example.databasetest
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val db = Database()
}
}
Edit:
Ok, so I tried to replicate the "private void connect()" function into a "public void load()" function which sends sql queries to the db.
public void load() {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
Connection con;
Statement stmt;
String sql = "SELECT * FROM INVENTORY";
Class.forName("org.postgresql.Driver");
con = DriverManager.getConnection(url, user, pass);
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()){
int id = rs.getInt("ID");
String description = rs.getString("DESCRIPTION");
String amount = rs.getString("AMOUNT");
String local = rs.getString("LOCAL");
System.out.print("ID: "+id);
System.out.print("Description: "+description);
System.out.print("Amount: "+amount);
System.out.print("Local: "+local);
con.close();
}
} catch (Exception e) {
status = false;
System.out.print(e.getMessage());
e.printStackTrace();
}
}
});
thread.start();
try {
thread.join();
} catch (Exception e) {
e.printStackTrace();
this.status = false;
}
}
The problem now is that in the Logcat this warning appears:
"I/Choreographer: Skipped 83 frames! The application may be doing too much work on its main thread."
It worked for one time, but then now it just gives me this error. The database doesn't even have that much info, it has like 12 rows.
How can I multithread (?) this function when accessing the database?
This is where I call db.load() in my MainActivity:
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = findViewById<EditText>(R.id.ID)
return when (item.itemId) {
R.id.load -> {
val db = Database()
db.load()
true
}
You have got the instance of Connection, does the Connection contain a method to execute SQL queries (or sth. like that)?
public class Database {
...
public Cursor query(String sql) { //cursor is nullable
// TODO connection.xxxx
}
}
In the class MainActivity, you can access the method query to get the Cursor...
[Update]
public class Database {
private Connection connection;
private final String host = "xxxxx";
private final String database = "xxxx";
private final int port = 9999;//needs int
private final String user = "xxxx";
private final String pass = "xxxx";
private final String SQL_DRIVER = "org.postgresql.Driver";
private String url = "jdbc:postgresql://%s:%d/%s";
private boolean status;
public Database() {
this.url = String.format(this.url, this.host, this.port, this.database);
System.out.println("the final url is " + this.url);
}
public Connection getConnection() {
Connection c = null;
try {
Class.forName(SQL_DRIVER);
c = DriverManager.getConnection(url, user, pass);
status = true;
System.out.println("connected:" + status);
} catch (Exception e) {
status = false;
System.out.print(e.getMessage());
e.printStackTrace();
}
return c;
}
public void load() {
Thread thread = new Thread(new Runnable() {
Connection con;
#Override
public void run() {
try {
Statement stmt;
String sql = "SELECT * FROM INVENTORY";
Class.forName(SQL_DRIVER);
con = DriverManager.getConnection(url, user, pass);
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(sql);
status = true;
while (rs.next()) {
int id = rs.getInt("ID");
String description = rs.getString("DESCRIPTION");
String amount = rs.getString("AMOUNT");
String local = rs.getString("LOCAL");
System.out.print("ID: " + id);
System.out.print("Description: " + description);
System.out.print("Amount: " + amount);
System.out.print("Local: " + local);
}
} catch (Exception e) {
try {
con.close();
} catch (SQLException exp) {
exp.printStackTrace();
}
status = false;
System.out.print(e.getMessage());
e.printStackTrace();
}
}
});
thread.start();
// try to comment
//try {
// thread.join();
//} catch (Exception e) {
// e.printStackTrace();
// this.status = false;
//}
}
}
I'm developing an android App that collect some data from 4 sensors via Bluetooh and at the end send the data to a SFTP server.
I'm using the JSCh (ChannelSftp), the thing works fine with some servers, but with the server of my University the App crash.
I have performed a deep debug with the IT officer and we discovered that once the SSH channel is open some background traffic arrives to the server (ex.: myIP --- otherIP--- packet). At that point the firewall close the connection and the App crash.
Is there a way to block the background traffic for a small window of time from the App?. Has anyone had the same problem as me?
Thanks in advance
public class SftpClass extends AsyncTask <Object, Void, String> {
private Context context;
private long size;
private long fileSize;
public SftpClass (Context con){
context = con;
size = 0;
fileSize = -1;
}
#Override
protected String doInBackground(Object... params){
//Params: File file, String host, String port, String username, String password
File file = (File) params[0];
String host = (String) params[1];
String port = (String) params[2];
String username = (String) params[3];
String password = (String) params[4];
String path = (String) params[5];
int portnumber = Integer.valueOf(port);
fileSize = file.length();
String localFilePath = file.getAbsolutePath();
String fileName = localFilePath.substring(localFilePath.lastIndexOf("/") + 1);
String remoteFilePath = fileName;
JSch jsch = new JSch();
Session session = null;
try {
session = jsch.getSession(username, host, portnumber);
session.setConfig("StrictHostKeyChecking", "no");
session.setPassword(password);
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
final ChannelSftp sftpChannel = (ChannelSftp) channel;
sftpChannel.put(localFilePath, path+remoteFilePath);
try
{
Thread.sleep(3000);
}
catch(InterruptedException ex)
{
Thread.currentThread().interrupt();
}
SftpATTRS attrs = null;
try {
attrs = sftpChannel.lstat(path+remoteFilePath);
} catch (SftpException e) {
e.printStackTrace();
}
if ( attrs != null){
size = attrs.getSize();
}
sftpChannel.exit();
session.disconnect();
} catch (JSchException e) {
e.printStackTrace();
} catch (SftpException e) {
e.printStackTrace();
}
return "";
}
#Override
protected void onPostExecute(String result) {
if (size == fileSize){
Toast.makeText(context, "File uploaded\n"+Long.toString(size)+"Bytes", Toast.LENGTH_SHORT).show();
}
}
}
i am using the code below to generate a crash file, the file is created at parse.com but it is empty.
any idea why?
Another problem is that "ACRA.DEFAULT_REPORT_FIELDS;" has an error, default report fields is not available.
public class LocalSender implements ReportSender {
private final Map<ReportField, String> mMapping = new HashMap<ReportField, String>() ;
private FileOutputStream crashReport = null;
private Context ctx;
public LocalSender(Context ct) {
ctx = ct;
}
public void send(CrashReportData report) throws ReportSenderException {
final Map<String, String> finalReport = remap(report);
ByteArrayOutputStream buf = new ByteArrayOutputStream();
Log.i("hcsh","Report send");
try {
Set set = finalReport.entrySet();
Iterator i = set.iterator();
String tmp;
while (i.hasNext()) {
Map.Entry<String,String> me = (Map.Entry) i.next();
tmp = "[" + me.getKey() + "]=" + me.getValue();
buf.write(tmp.getBytes());
}
ParseFile myFile = new ParseFile("crash.txt", buf.toByteArray());
myFile.save();
ParseObject jobApplication = new ParseObject("AppCrash");
jobApplication.put("MyCrash", "app name");
jobApplication.put("applicantResumeFile", myFile);
try {
jobApplication.save();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}catch (FileNotFoundException e) {
Log.e("TAG", "IO ERROR",e);
}
catch (IOException e) {
Log.e("TAG", "IO ERROR",e);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private Map<String, String> remap(Map<ReportField, String> report) {
ReportField[] fields = ACRA.getConfig().customReportContent();
if (fields.length == 0) {
fields = ACRA.DEFAULT_REPORT_FIELDS;
}
final Map<String, String> finalReport = new HashMap<String, String>(
report.size());
for (ReportField field : fields) {
if (mMapping == null || mMapping.get(field) == null) {
finalReport.put(field.toString(), report.get(field));
} else {
finalReport.put(mMapping.get(field), report.get(field));
}
}
return finalReport;
}
}
There is no such constant as ACRA.DEFAULT_REPORT_FIELDS. You are looking for ACRAConstants.DEFAULT_REPORT_FIELDS
ACRA.DEFAULT_REPORT_FIELDS constant value is in acra-4.3.0 version ...
if you are using acra-4.5.0 version ACRA you will get this error "DEFAULT_REPORT_FIELDS cannot be resolved or is not a field" .
try to use acra-4.5.0 version and then use following code
// Extract the required data out of the crash report.
String reportBody = createCrashReport(report);
/** Extract the required data out of the crash report. */
private String createCrashReport(CrashReportData report) {
// I've extracted only basic information.
// U can add loads more data using the enum ReportField. See below.
StringBuilder body = new StringBuilder();
body.append(
"Device : " + report.getProperty(ReportField.BRAND) + "-"
+ report.getProperty(ReportField.PHONE_MODEL))
.append("\n")
.append("Android Version :"
+ report.getProperty(ReportField.ANDROID_VERSION))
.append("\n")
.append("App Version : "
+ report.getProperty(ReportField.APP_VERSION_CODE))
.append("\n")
.append("STACK TRACE : \n"
+ report.getProperty(ReportField.STACK_TRACE));
return body.toString();
}
Don't use following code
////////////////////////
final String reportBody = buildBody(arg0);
private String buildBody(CrashReportData errorContent) {
ReportField[] fields = ACRA.getConfig().customReportContent();
if (fields.length == 0) {
// fields = ACRA.DEFAULT_MAIL_REPORT_FIELDS;
fields = ACRA.DEFAULT_REPORT_FIELDS;
}
final StringBuilder builder = new StringBuilder();
for (ReportField field : fields) {
builder.append(field.toString()).append("=");
builder.append(errorContent.get(field));
builder.append('\n');
}
return builder.toString();
}
Happy Coding....
i am new in asmack. i am writing a chat application and when i add a user by send him/her a subscription packet an he accept, i check openFire server nikename and other properties is ok for new user and mode is both.
but when i try to get friends data nickname is empty.
if i debug the code nickname receive correctly but in run mode can not?
code to receive friends :
public static void getContacts(final Context ctx)
{
try
{
try
{
Thread.sleep(1000);
}
catch(Exception ex)
{
}
Roster roster = connection.getRoster();
Collection<RosterEntry> entries = roster.getEntries();
if(globalVars.friends == null)
globalVars.friends = new ArrayList<globalVars.UserList>();
globalVars.friends.clear();
for(RosterEntry entry: entries)
{
String user = entry.getUser();
String username = user.split("#")[0];
Presence presence = roster.getPresence(entry.getUser());
int status = R.drawable.offline;
if(presence.getType().equals(Presence.Type.available))
status = R.drawable.online;
//String fromto = presence.getFrom() + " "+presence.getTo();
globalVars.UserList ul = new UserList(username, status, globalVars.smallImageAddress(ctx, username));
String wathsUp = "";
try
{
if(presence.getStatus() != null)
wathsUp = presence.getStatus();
}
catch(Exception ex)
{
}
ul.setComment(wathsUp);
ul.setFriend(true);
ul.setNikName(entry.getName());
globalVars.friends.add(ul);
}
can anyone help me?
Use vCard for setting nickname or other details of a user.
Use this code for getting Vcard information from a jid
VCard mVCard = new VCard();
mVCard.load(your xmppconnection,user jid);
String name = mVCard.getNickName();
Just an update on this matter: VCard load() method is now deprecated.
Instead you can use this method:
/**
* retrieves an user VCard
*
* #param userJid the user jid
* #return the VCard object
*/
public VCard getVCard(String userJid) {
VCard vCard = null;
VCardManager vCardManager = VCardManager.getInstanceFor(connection);
boolean isSupported;
try {
//remove resource name if necessary
if (!TextUtils.isEmpty(userJid) && userJid.contains("/")) {
userJid = userJid.split("/")[0];
}
isSupported = vCardManager.isSupported(userJid);
if (isSupported) // return true
vCard = vCardManager.loadVCard(userJid);
} catch (SmackException.NoResponseException e) {
e.printStackTrace();
} catch (XMPPException.XMPPErrorException e) {
e.printStackTrace();
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
} catch (IllegalArgumentException iAE) {
iAE.printStackTrace();
}
return vCard;
}
As you can see, the method checks if the user understands the vCard-XML format and exchange. If it does, it returns the VCard.
Then just retrieve the user nickname from VCard.
Is there a way to wait for the result when using IntentService?
Scenario.
Service App is running --> receives login credentials from another app --> Service app then checks database (for some reason I always get Connection time out. And I know this is bad but for POC and a quick hack this will do for now) --> Wait for validation query then results.
Is this possible?
I tried using AsynTask inside the Service but still to no avail, I always get Connection timeout error.
DEMOSERVICE
#Override
public IBinder onBind(Intent intent) {
return new IDemoService.Stub() {
#Override
/**
* Login validation implementation
*/
public boolean login(String id, String password)
throws RemoteException {
UserLoginTask userLoginTask = new UserLoginTask(id, password);
try {
return userLoginTask.execute((Void) null).get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
};
}
USERLOGINTASK
private class UserLoginTask extends AsyncTask<Void, Void, Boolean> {
private String uId;
private String uPassword;
public UserLoginTask(String id, String password) {
uId = id;
uPassword = password;
}
#Override
protected Boolean doInBackground(Void... arg0) {
Connection conn;
try {
int count = 0;
Class.forName("org.postgresql.Driver");
String url = "jdbc:postgresql://xxx.xxx.x.xxx/test_db?user=postgres&password=password";
conn = DriverManager.getConnection(url);
if (conn != null) {
Statement st = conn.createStatement();
String sql = "Select count(*) as cnt from tbl_persons where id = '"
+ uId.toUpperCase(Locale.getDefault()).trim()
+ "' AND pwd='" + uPassword.trim() + "';";
Log.d("DemoService", "Login sql - " + sql);
ResultSet rs = st.executeQuery(sql);
while (rs.next()) {
count = rs.getInt("cnt");
}
rs.close();
st.close();
conn.close();
if (count == 0)
return false;
return true;
}
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}