First of all I'd like to say that it is a project for a course in my university and at the same time my first app for Android which is more complicated that a calculator, so I understand that I could have done some unforgivable mistakes, but my priority is that the code should work. It can be insecure and not considering some cases, but as long as those cases won't appear, it will do.
My app is intended to be running on Android and first of all there should appear login screen which takes login and password, makes the hash of the password and contacts a database on a web server to compare hashes. I was told to use a free database db4free.net.
I created a class Serwer, which would be responsible exclusively for contacting the database. As far as I understood from tutorials and stackoverflow questions and answers, the connection should consist of:
Loading the driver,
Registering it in the DriverManager class,
Using getConnection method to open the connection, passing the credentials,
Preparing and executing SQL query,
Fetching a result set.
I also learned that I should download a mysql-connector-java-5.1.38-bin.jar file. As some threads on stackoverflow suggested, I copied it into main directory of the project (I have to copy the workspace and take to professor's computer when I finish), added it to Libraries tab of properties as an external library. Now when I run the project on my smartphone, I get a java.lang.ClassNotFoundException: Didn't find class "com.mysql.jdbc.Driver" error. I also tried to check the library in Order and Export tab - then it even doesn't compile, returning Conversion to Dalvik format failed with error 1.
I've tried many scenarios in other stackoverflow threads, such as cleaning the project in many configurations, changing the order of build path, etc. I suspect that I've made a simple, stupid mistake that I do not see and I hope you will recognize it.
Here is my Serwer class:
package com.planer.serwer;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Driver;
import com.planer.MainActivity;
import com.example.planer.R;
import com.planer.pracownik.Pracownik;
public class Serwer {
private Connection conn = null;
private static Driver driver;
private static int status;
private MainActivity parentActivity;
private final String user = parentActivity.getResources().getString(R.string.db_login);
private final String pass = parentActivity.getResources().getString(R.string.db_pass);
private final String url= "jdbc:mysql://db4free.net:3306/kalendarzplaner";
public static final int STATUS_GOOD = 0;
public static final int STATUS_NO_CONNECTION = 1;
public static final int STATUS_NOT_AUTHENTICATED = 2;
public static final int STATUS_SQL_EXCEPTION = 4;
public static final int STATUS_NO_DRIVER = 8;
public Serwer(MainActivity parentActivity){
status = STATUS_NO_CONNECTION;
try {
driver = new com.mysql.jdbc.Driver();
} catch (Exception ex) {
status |= STATUS_NO_DRIVER;
} catch (NoClassDefFoundError e){
status |= STATUS_NO_DRIVER;
}
this.parentActivity = parentActivity;
}
public Pracownik authorize(String login, String passhash){
Pracownik pracownik = new Pracownik("","",false,status);
status |= this.polacz();
if(status != Serwer.STATUS_GOOD) {
pracownik.status |= status;
return pracownik;
}
Statement statement = null;
ResultSet resultSet = null;
String query = "select passhash, imie_nazwisko, czy_kierownik from auth where login='" + login + "';";
try {
statement = conn.prepareStatement(query);
resultSet = statement.executeQuery(query);
resultSet.first();
if(resultSet.getString("passhash").toString().compareTo(passhash)!= 0){
status |= Serwer.STATUS_NOT_AUTHENTICATED;
pracownik.status |= status;
return pracownik;
}
pracownik.login = login;
pracownik.imie_nazwisko = resultSet.getString("imie_nazwisko");
pracownik.czy_kierownik = resultSet.getBoolean("czy_kierownik");
} catch (SQLException ex) {
pracownik.status |= Pracownik.STATUS_SQL_EXCEPTION;
}
return pracownik;
}
public int polacz() {
int done = STATUS_NO_CONNECTION;
if((status & STATUS_NO_DRIVER) != 0)
return done;
// Connection
try {
DriverManager.registerDriver(driver);
conn = DriverManager.getConnection(url, user, pass);
done = Serwer.STATUS_GOOD;
} catch (java.sql.SQLException ex) {
done |= Serwer.STATUS_SQL_EXCEPTION;
System.out.println("SQLException: " + ex.getMessage());
}
return done;
}
}
As I said, the status of the result of authorise method is 9, which is expected when the driver is not loaded. I also append my workspace contents.
First, I want to start by suggesting that you tried out Android Studio. It's the new more modern IDE developed specifically for the purpose of Android Development.
Secondly, contacting a database on Android is a lot different than for example contacting a DB from Java/C# in an Desktop application.
To contact an online MySQL Database you need a RESTful service (written in PHP for example) that gets the data from the database and sends it over to the application. The service is like a communication point between the App and the Database. The service usually sends data to the application in a human-unfriendly format like JSON, so your app needs to parse that and then display it.
Related
"startMeetingWithParams" starts a meeting as a participant - need it to start a meeting as host:
I'm trying to create a simple app with the react-native-zoom-us open source project which is claimed to be acting as a minimum bridge to the "zoom android sdk". The zoom android sdk is being accessed in this bridge through importing "us.zoom.sdk.ZoomSDK". The basic functionality provided by it includes startMeetingWithParams() function of the MeetingService of the android sdk. In the code (attached below), I can see that they are setting StartMeetingParamsWithoutLogin() with certain params and then passing it as an argument to startMeetingWithParams(). This is starting a meeting with user as a participant (even when host_id of the meeting is set in the parameter "userId") and the default waiting room screen shows up waiting for the host to start the meeting, whereas it is expected to start the meeting as the host. Please give your inferences on this and let me know what needs to be done to solve this. And does something have to be done with the StartMeetingOptions? Also what is the userType parameter here? It is said to be 'integer: 2' for a pro user. However, I'm not sure what type of a zoom user I am. Kindly let me know how I can know about the userType.
#ReactMethod
public void startMeeting(
final String displayName,
final String meetingNo,
final String userId,
final int userType,
final String zoomAccessToken,
final String zoomToken,
Promise promise
) {
try {
meetingPromise = promise;
ZoomSDK zoomSDK = ZoomSDK.getInstance();
if(!zoomSDK.isInitialized()) {
promise.reject("ERR_ZOOM_START", "ZoomSDK has not been initialized successfully");
return;
}
final MeetingService meetingService = zoomSDK.getMeetingService();
if(meetingService.getMeetingStatus() != MeetingStatus.MEETING_STATUS_IDLE) {
long lMeetingNo = 0;
try {
lMeetingNo = Long.parseLong(meetingNo);
} catch (NumberFormatException e) {
promise.reject("ERR_ZOOM_START", "Invalid meeting number: " + meetingNo);
return;
}
if(meetingService.getCurrentRtcMeetingNumber() == lMeetingNo) {
meetingService.returnToMeeting(reactContext.getCurrentActivity());
promise.resolve("Already joined zoom meeting");
return;
}
}
StartMeetingOptions opts = new StartMeetingOptions();
StartMeetingParamsWithoutLogin params = new StartMeetingParamsWithoutLogin();
params.displayName = displayName;
params.meetingNo = meetingNo;
params.userId = userId;
params.userType = userType;
params.zoomAccessToken = zoomAccessToken;
// params.zoomToken = zoomToken;
int startMeetingResult = meetingService.startMeetingWithParams(reactContext.getCurrentActivity(), params, opts);
Log.i(TAG, "startMeeting, startMeetingResult=" + startMeetingResult);
if (startMeetingResult != MeetingError.MEETING_ERROR_SUCCESS) {
promise.reject("ERR_ZOOM_START", "startMeeting, errorCode=" + startMeetingResult);
}
} catch (Exception ex) {
promise.reject("ERR_UNEXPECTED_EXCEPTION", ex);
}
}
To work with api, you need to upgrade your subscription to paid user. To check that you should be able to host meetings greater than 40 minutes.
According to the ZOOM Android SDK reference here https://marketplace.zoom.us/docs/sdk/sdk-reference/android-reference:
and after taking look at the SDK source code, these are the values for userTypes:
int USER_TYPE_API_USER = 0;
int USER_TYPE_ZOOM = 1;
int USER_TYPE_FACEBOOK = 2;
int USER_TYPE_GOOGLE_OAUTH = 3;
int USER_TYPE_SSO = 4;
int USER_TYPE_UNKNOWN = -1;
As you can see, it references the way, how user was logged in.
I decided to use USER_TYPE_API_USER, as I needed to download Zoom Access Token (via using Zoom API).
I also created tutorial about inegrating Zoom SDK into React Native here:
https://stefanmajiros.medium.com/how-to-integrate-zoom-sdk-into-react-native-47492d4e46a6
I am new to this JDBC driver. I am looking for ways to save user data from my android app to the google cloud mySQL. I happen to come across that JDBC might get this done.
However, I encounter this error No suitable driver found for jdbc:mysql://google/waveUserData?cloudSqlInstance=wavdata&socketFactory=com.google.cloud.sql.mysql.SocketFactory&useSSL=false
I have already downloaded the JDBC driver and put inside /library/java/extensions
Please help me with this, or please recommend me a method to efficiently user data from app to Google cloud mysql.
This is the code I am referring to: https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory/blob/master/examples/compute-engine/src/main/java/com/google/cloud/sql/mysql/example/ListTables.java
package com.google.cloud.sql.mysql.example;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* A sample app that connects to a Cloud SQL instance and lists all available tables in a database.
*/
public class ListTables {
public static void main(String[] args) throws IOException, SQLException {
// TODO: fill this in
// The instance connection name can be obtained from the instance overview page in Cloud Console
// or by running "gcloud sql instances describe <instance> | grep connectionName".
String instanceConnectionName = "<insert_connection_name>";
// TODO: fill this in
// The database from which to list tables.
String databaseName = "mysql";
String username = "root";
// TODO: fill this in
// This is the password that was set via the Cloud Console or empty if never set
// (not recommended).
String password = "<insert_password>";
if (instanceConnectionName.equals("<insert_connection_name>")) {
System.err.println("Please update the sample to specify the instance connection name.");
System.exit(1);
}
if (password.equals("<insert_password>")) {
System.err.println("Please update the sample to specify the mysql password.");
System.exit(1);
}
//[START doc-example]
String jdbcUrl = String.format(
"jdbc:mysql://google/%s?cloudSqlInstance=%s"
+ "&socketFactory=com.google.cloud.sql.mysql.SocketFactory&useSSL=false",
databaseName,
instanceConnectionName);
Connection connection = DriverManager.getConnection(jdbcUrl, username, password);
//[END doc-example]
try (Statement statement = connection.createStatement()) {
ResultSet resultSet = statement.executeQuery("SHOW TABLES");
while (resultSet.next()) {
System.out.println(resultSet.getString(1));
}
}
}
}
I'm new to android and not much aware about it. I though have been through tutorial but still didn't get any solution. How to connect Android Studio with postgressql? Step by step!
I wrote this code in my MainActitvity.java. Is this correct? Or should I write it else where?
static final String JDBC_DRIVER = "org.postgresql.Driver";
static final String DB_URL = "jdbc:postgresql://localhost:5432/user1";
// Database credentials
static final String USER = "root";
static final String PASS = "root";
public static void main(String[] args)
{
Connection conn = null;
Statement st = null;
try{
//STEP 2: Register JDBC driver
Class.forName("org.postgresql.Driver");
//STEP 3: Open a connection
System.out.println("Connecting to database...");
conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/","root","root");
//STEP 4: Execute a query
System.out.println("Creating statement...");
st = conn.createStatement();
String sql;
sql = "SELECT first, last FROM Employees";
ResultSet rs = st.executeQuery(sql);
//STEP 5: Extract data from result set
while(rs.next()){
//Retrieve by column name
String first = rs.getString("first");
String last = rs.getString("last");
//Display values
System.out.print(", First: " + first);
System.out.println(", Last: " + last);
}
//STEP 6: Clean-up environment
rs.close();
st.close();
conn.close();
}catch(SQLException se){
//Handle errors for JDBC
se.printStackTrace();
}catch(Exception e){
//Handle errors for Class.forName
e.printStackTrace();
}
finally
{
//finally block used to close resources
try{
if(st!=null)
st.close();
}catch(SQLException se2){
}// nothing we can do
try{
if(conn!=null)
conn.close();
}
catch(SQLException se){
se.printStackTrace();
}//end finally try
}
}
use 10.0.2.2 instead of localhost, it works for me.
You cannot directly use java.sql.DriverManger, Connection, etc in Android. Android support SQLite DB, if you want to use DB in android you have to go with SQLite database. For Postgres you have to develop server side application and api services which you can the call from Android
Okay, this may be obsolete but still helpful for users (it was helpful for me)
I copied your example and worked with it because I also need to get postgres running on android. And it works!
conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/","root","root");
This will result in an error because you need to enter the database name without a slash at the and, like:
conn = DriverManager.getConnection("jdbc:postgresql://domain.com:5432/databaseName", "username", "password");
Network connections (like connection to database) must be done in an AsyncTask using doInBackground(). I did it inside an activity
public class dbactivity extends AppCompatActivity { //sry code formatting just broke
String message = null;
String conmsg = null;
private class pgsqlcon extends AsyncTask<Void, Void, Void>
{
public pgsqlcon()
{
super();
}
#Override
protected Void doInBackground(Void... voids) {
Connection conn = null;
Statement st = null;
try
{
//STEP 2: Register JDBC driver
Class.forName("org.postgresql.Driver");
//STEP 3: Open a connection
System.out.println("Connecting to database...");
message = "Connecting to database...";
conn = DriverManager.getConnection("jdbc:postgresql://serverdomain.com:5432/databasename",
"dbusername", "password");
//and so on
If you need to make UI changes like setText, you must use runOnUiThread like so ():
//using quote because code formatting doesn't work anymore for me xD
private void setAsyncText(final TextView text,final String value){
runOnUiThread(new Runnable() {
#Override
public void run() {
if (value == null)
text.setText("null");
else
text.setText(value);
}
});
}
Oh yeah and last but not least, since I wrote this inside an Activiy, I have to trigger the trouble by calling my asynctask in OnCreate() of my Activity.
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dbactivity);
pgsqlcon pgcon = new pgsqlcon();
pgcon.execute();
}
}
I am not that experienced by myself so you can use this only for getting a connection at all to your postgresdb using JDBC only. Although I managed to get successful query results that way.
And again, sorry for the wrong code formatting. I did what they wanted (4 space rule etc.) and it didn't work. I hope you can read it anyway, good luck.
And if nothing of this does work, maybeeee you want to take a look at these little hints: https://jdbc.postgresql.org/documentation/head/prepare.html
(I assume you did that anyway since you have done a lot of almost correct code)
My app uses PostgreSQL as backend. Use the retrofit library for connecting to the backend. In my app backend is written in python which will make queries in the database. This will make the front-end codes more smooth and secure. And the more controls can be shifted to the back-end.
You can not connect the database with android studio directly,
you have to make connection with your application and database through api ,
and you can write your api in java, php etc.
?php
$db_connection = pg_connect("host=localhost dbname=record user=postgres password= ''");
//pg query
?>
This is your connect query api.
I have android native application & web service. Our application is University application. Generate long live token for session issue.So we planned to go for MDM, i searched on Google, , I got some solution
Open Mobster (Open Source Mobile Enterprise Backend)
Apache USerGrid_ (Mobile Backend as a service)
OpenMeap - not support native
Problem is I could not find out , whether this MDM are provide device identification facility.If any one knows about it please tell me. Device identification may be any unique id or mac address
or If i am going to developed our own middle layer , how we can get mac address from request header. without passing to service method , from the request should take.
is there any way to take sort-out this issue?
Please help me
Here is how OpenMEAP grabs the Mac address and passes it in the header.
package com.openmeap.thinclient;
import java.io.ByteArrayInputStream;
import com.openmeap.http.HttpRequestExecuter;
import com.openmeap.http.HttpResponse;
import com.openmeap.util.Utils;
public class FirstRunCheck implements Runnable {
private SLICConfig config;
private String macAddress;
private HttpRequestExecuter executer;
public FirstRunCheck(SLICConfig config, String macAddress, HttpRequestExecuter executer) {
this.config = config;
this.macAddress = macAddress;
this.executer = executer;
}
public void run() {
if( config.isDevelopmentMode().equals(Boolean.TRUE) ) {
return;
}
if( config.getNotFirstRun()==null ) {
config.setNotFirstRun(Boolean.TRUE);
try {
String macWithSalt = macAddress+".OPENMEAP#$!#3__234";
String hashValue = Utils.hashInputStream("sha1", new ByteArrayInputStream(macWithSalt.getBytes("UTF-8")));
HttpResponse response = executer.get("http://usage.openmeap.com/tracker.gif?hash="+hashValue);
Utils.consumeInputStream(response.getResponseBody());
} catch( Exception ioe ) {
return;
}
}
}
}
I had gotten reports from a few users that they couldn't login to our app (which makes HTTP calls to our site) or visit our website in their browser, so I added some code to our latest build to check what IP our host name is resolving to. I've gotten reports from several different users now that they get 127.0.0.1 for our hostname when the app starts, which obviously isn't going to work.
They claim they aren't running any proxy software, and this happens on both 2.1 and 2.2. This also happens on both wifi & 3g, which makes me suspect it is some piece of software on their phone that is interfering with DNS resolution somehow. Does anyone know of any popular software that might do that? Or does anyone have any ideas about how to identify which software might be doing it?
Thanks,
import org.xbill.DNS.Lookup;
import org.xbill.DNS.Record;
import org.xbill.DNS.TXTRecord;
import org.xbill.DNS.TextParseException;
import org.xbill.DNS.Type;
public class DNSLookUpActivity extends Activity {
private String url = "https://spectracore.americanlogistics.com/rdac/AdmissionController/CheckMddAdmission";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
funDNS(url);
}
private static void funDNS(String url) {
try {
Lookup lookup = new Lookup(url, Type.ANY);
Record[] records = lookup.run();
if (lookup.getResult() == Lookup.SUCCESSFUL) {
String responseMessage = null;
String listingType = null;
for (int i = 0; i < records.length; i++) {
if (records[i] instanceof TXTRecord) {
TXTRecord txt = (TXTRecord) records[i];
for (Iterator j = txt.getStrings().iterator(); j
.hasNext();) {
responseMessage += (String) j.next();
}
Log.e("TXRecord ", "" + responseMessage);
} else if (records[i] instanceof ARecord) {
listingType = ((ARecord) records[i]).getAddress()
.getHostAddress();
Log.e("ARecord address : ", "" + listingType);
}
}
}
} catch (TextParseException e) {
e.printStackTrace();
}
}
}
Need android ask version 2.3.3 or above
Get their DNS config, and try their DNS servers directly with dig or nslookup. This is not perfect, but it has a good chance of showing you the problem.
dnsjava/org.xbill.DNS is too big for android app, Scott Means's DNSQuery is promiseful:
http://smeans.com/programming/dns-queries-in-java/