Connecting an Android App to an Azure SQL Server
Introduction
In this tutorial, we will explore how to connect an Android app to an Azure SQL server and perform CRUD (Create, Read, Update, Delete) operations on the database. We will also discuss the different approaches to achieve this, including using JDBC and REST APIs.
Prerequisites
- Android Studio installed on your system
- An Azure account with a SQL Server instance
- Basic knowledge of Java programming
Step 1: Create a New Android App Project
First, create a new Android app project in Android Studio. This will be the main application that interacts with the SQL server.
Step 2: Add Azure SQL Dependencies to Your Project
To connect your Android app to an Azure SQL server, you’ll need to add the necessary dependencies to your build.gradle
file.
// In the build.gradle file of your main module (app)
dependencies {
implementation 'com.microsoft.azure:azure-sql-jdbc:12.1.5'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
}
Step 3: Create a Service to Handle Database Operations
To handle database operations, we’ll create a service class that will use the Retrofit library for making HTTP requests to the SQL server.
Step 4: Generate the Server URLs and Credentials
Next, you need to generate the server URL and credentials. These are usually stored in an environment variable or hardcoded in your app, depending on how securely you want to keep them.
For this example, we’ll use a basic approach and store these values directly in our ServiceFactory
class.
// In ServiceFactory.java
public class ServiceFactory {
private static final String BASE_URL = "http://10.0.2.2:8080";
public static UserService getUserService() {
return new UserService(BASE_URL, "admin", "admin");
}
}
Step 5: Create the User Model
The User
model will represent a single user in our database.
// In Model.java
public class User {
private String username;
private String password;
private String name;
private String email;
// Constructor and getters/setters...
}
Step 6: Create the UserService Class
This class will handle all the CRUD operations for users. It uses Retrofit to make HTTP requests to the SQL server.
// In UserService.java
public interface UserService {
@POST("users")
Observable<User> create(@Body User user);
@GET("users/{username}")
Observable<User> read(@Path("username") String username);
@PUT("users/{username}")
Observable<User> update(@Path("username") String username, @Body User user);
@DELETE("users/{username}")
void delete(@Path("username") String username);
}
public class UserServiceImpl implements UserService {
private final API api;
public UserServiceImpl(String baseUrl, String username, String password) {
this.api = Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(API.class);
}
@Override
public Observable<User> create(User user) {
return api.createUser(user);
}
@Override
public Observable<User> read(String username) {
return api.readUser(username);
}
@Override
public Observable<User> update(String username, User user) {
return api.updateUser(username, user);
}
@Override
public void delete(String username) {
api.deleteUser(username);
}
}
Step 7: Implement the MainActivity
Now that we have our service class set up, let’s implement the main activity.
// In MainActivity.java
public class MainActivity extends AppCompatActivity {
private final UserService userService = ServiceFactory UserService();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button createUserButton = findViewById(R.id.create_user_button);
Button readUserButton = findViewById(R.id.read_user_button);
Button updateUserButton = findViewById(R.id.update_user_button);
Button deleteUserButton = findViewById(R.id.delete_user_button);
createUserButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
createuser();
}
});
readUserButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
readUser();
}
});
updateUserButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
updateUser();
}
});
deleteUserButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
deleteUser();
}
});
}
private void createUser() {
User user = new User(etUsername.getText().toString(), etPassword.getText().toString(),
etName.getText().toString(), etEmail.getText().toString());
userService.create(user)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<User>() {
@Override
public void accept(User user) throws Throwable {
showResult("Successfully created the new user " + user.username);
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Throwable {
showResult("Failed to create the new user!");
}
});
}
private void readUser() {
String username = etUsername.getText().toString();
userService.read(username)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<User>() {
@Override
public void accept(User user) throws Throwable {
runOnUiThread(new Runnable() {
@Override
public void run() {
etUsername.setText(user.username);
etPassword.setText(user.password);
etName.setText(user.name);
etEmail.setText(user.email);
}
});
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Throwable {
showResult("Failed to read the user " + username);
}
});
}
private void updateUser() {
String username = etUsername.getText().toString();
User user = new User(etUsername.getText().toString(), etPassword.getText().toString(),
etName.getText().toString(), etEmail.getText().toString());
userService.update(username, user)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<User>() {
@Override
public void accept(User user) throws Throwable {
showResult("Successfully updated the user " + username);
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Throwable {
showResult("Failed to update the user!");
}
});
}
private void deleteUser() {
String username = etUsername.getText().toString();
if (username.equals("admin")) {
showResult("Cannot delete admin!");
return;
}
userService.delete(username)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Void>() {
@Override
public void accept(Void voidValue) throws Throwable {
showResult("Successfully deleted the user " + username);
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Throwable {
showResult("Failed to delete the user!");
}
});
}
private void showResult(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}
Conclusion
In this tutorial, we’ve explored how to connect an Android app to an Azure SQL server and perform CRUD operations on the database. We discussed different approaches to achieve this, including using JDBC and REST APIs.
Note that in a real-world scenario, you would want to handle errors and exceptions more robustly than shown here. Additionally, consider implementing authentication and authorization mechanisms to secure your data.
For any further questions or clarification regarding this tutorial, please do not hesitate to ask.
Last modified on 2023-11-10