diff --git a/.gitignore b/.gitignore
index 8ccc4f86..d95437f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,5 @@
.externalNativeBuild
.cxx
local.properties
+keystore.properties
+*.jks
diff --git a/app/build.gradle b/app/build.gradle
index e10de03a..62a6b94b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -11,21 +11,50 @@ android {
minSdk 26
targetSdk 33
versionCode 1
- versionName "1.0"
+ versionName "0.1.0-Alpha"
+ }
+
+ viewBinding {
+ enabled = true
}
signingConfigs {
release {
- storeFile file("passwordmanager.jks")
- storePassword 'beMbDcv94lv3'
- keyAlias 'passwordmanager'
- keyPassword 'beMbDcv94lv3'
+ def keystorePropertiesFile = rootProject.file("keystore.properties")
+ if (keystorePropertiesFile.exists()) {
+ def keystoreProperties = new Properties()
+ keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
+
+ keyAlias keystoreProperties['keyAlias']
+ keyPassword keystoreProperties['keyPassword']
+ storeFile file(keystoreProperties['storeFile'])
+ storePassword keystoreProperties['storePassword']
+ }
+ }
+ }
+
+ splits {
+ abi {
+ enable true
+ reset()
+ include 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
+ universalApk true
}
}
+
+ lintOptions {
+ // You can enable lint checking and provide a baseline file if needed:
+ // baseline file("lint-baseline.xml")
+
+ // To ensure that lint uses the lint.xml configuration
+ lintConfig rootProject.file("lint.xml")
+ }
buildTypes {
release {
- signingConfig signingConfigs.release
+ if (rootProject.file("keystore.properties").exists()) {
+ signingConfig signingConfigs.release
+ }
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 11d3ca40..4d70ade2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -12,6 +12,7 @@
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="32"
tools:ignore="ScopedStorage" />
+
@@ -25,7 +26,7 @@
android:supportsRtl="true"
android:theme="@style/PasswordManagerTheme">
@@ -33,6 +34,10 @@
+
+
+
+
diff --git a/app/src/main/java/com/passwordmanager/MainActivity.java b/app/src/main/java/com/passwordmanager/MainActivity.java
deleted file mode 100644
index a7b46bfb..00000000
--- a/app/src/main/java/com/passwordmanager/MainActivity.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.passwordmanager;
-
-import android.os.Bundle;
-import android.widget.Toast;
-import androidx.annotation.NonNull;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.core.view.WindowCompat;
-import com.passwordmanager.utils.Permissions;
-
-public class MainActivity extends AppCompatActivity {
-
- private Permissions permissionsHandle;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
-
- // Make window fullscreen
- WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
-
- // Check and request permission when the app is first opened
- permissionsHandle = new Permissions(this);
- if (!permissionsHandle.checkPermission()) permissionsHandle.requestPermission();
- }
-
- @Override
- public void onRequestPermissionsResult(
- int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- if (requestCode == Permissions.PERMISSION_REQUEST_CODE) {
- if (permissionsHandle.isPermissionGranted(grantResults)) {
- // Permission has been granted
- Toast.makeText(this, getString(R.string.permission_granted), Toast.LENGTH_LONG).show();
- } else {
- // Permission not granted
- Toast.makeText(this, getString(R.string.permission_denied), Toast.LENGTH_LONG).show();
- }
- }
- }
-}
diff --git a/app/src/main/java/com/passwordmanager/database/MyDatabaseHelper.java b/app/src/main/java/com/passwordmanager/database/MyDatabaseHelper.java
new file mode 100644
index 00000000..8d2f8022
--- /dev/null
+++ b/app/src/main/java/com/passwordmanager/database/MyDatabaseHelper.java
@@ -0,0 +1,39 @@
+package com.passwordmanager.database;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+public class MyDatabaseHelper extends SQLiteOpenHelper {
+ private static final String DATABASE_NAME = "master.db";
+ private static final int DATABASE_VERSION = 1;
+
+ public static final String PASSWORDS_TABLE = "passwords";
+
+ // SQL statement to create a passwords table.
+ private static final String CREATE_PASSWORDS_TABLE = "CREATE TABLE IF NOT EXISTS " + PASSWORDS_TABLE + " (" +
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, " +
+ "domain VARCHAR(40) NOT NULL, " +
+ "username VARCHAR(60) NOT NULL, " +
+ "password VARCHAR(60) NOT NULL, " +
+ "notes VARCHAR(100), " +
+ "createdat DATE DEFAULT CURRENT_TIMESTAMP, " +
+ "updatedat DATE DEFAULT CURRENT_TIMESTAMP);";
+
+
+ public MyDatabaseHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ // Create passwords table.
+ db.execSQL(CREATE_PASSWORDS_TABLE);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ // not Implemented a not needed.
+ return;
+ }
+}
diff --git a/app/src/main/java/com/passwordmanager/models/PasswordModel.java b/app/src/main/java/com/passwordmanager/models/PasswordModel.java
new file mode 100644
index 00000000..e063c329
--- /dev/null
+++ b/app/src/main/java/com/passwordmanager/models/PasswordModel.java
@@ -0,0 +1,111 @@
+package com.passwordmanager.models;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+public class PasswordModel {
+ private int id; // Primary key of passwords table.
+ private String domain; // Domain associated with password entity.
+ private String username; // Username associated with password entity.
+ private String password; // Password of password entity.
+ private String notes; // Notes associated with the password entity.
+ private String createdAt; // Date of password entity when the entity was first saved.
+ private String updatedAt; // Date of password entity when the entity was last updated.
+
+ // Constructor to initialize a new password model without an ID.
+ public PasswordModel(String domain, String username, String password, String notes) {
+ this.domain = domain;
+ this.username = username;
+ this.password = password;
+ this.notes = notes;
+
+ // Retrieve the current date and time
+ LocalDateTime currentDate = LocalDateTime.now();
+
+ // Formatting the time so that it is better seen by users
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+ this.createdAt = currentDate.format(formatter);
+ this.updatedAt = currentDate.format(formatter);
+ }
+
+ // Constructor with ID (e.g., when fetching from the database)
+ public PasswordModel(int id, String domain, String username, String password, String notes, String createdAt, String updatedAt) {
+ this.id = id;
+ this.domain = domain;
+ this.username = username;
+ this.password = password;
+ this.notes = notes;
+ this.createdAt = createdAt;
+ this.updatedAt = updatedAt;
+ }
+
+ // Getters and Setters
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getDomain() {
+ return domain;
+ }
+
+ public void setDomain(String domain) {
+ this.domain = domain;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getNotes() {
+ return notes;
+ }
+
+ public void setNotes(String notes) {
+ this.notes = notes;
+ }
+
+ public String getCreatedAt() {
+ return createdAt;
+ }
+
+ public void setCreatedAt(String createdAt) {
+ this.createdAt = createdAt;
+ }
+
+ public String getUpdatedAt() {
+ return updatedAt;
+ }
+
+ public void setUpdatedAt(String updatedAt) {
+ this.updatedAt = updatedAt;
+ }
+
+ @Override
+ public String toString() {
+ return "PasswordModel{" +
+ "id=" + id +
+ ", domain='" + domain + '\'' +
+ ", username='" + username + '\'' +
+ ", password='" + password + '\'' +
+ ", notes='" + notes + '\'' +
+ ", createdAt='" + createdAt + '\'' +
+ ", updatedAt='" + updatedAt + '\'' +
+ '}';
+ }
+}
diff --git a/app/src/main/java/com/passwordmanager/ui/LoadPasswordActivity.java b/app/src/main/java/com/passwordmanager/ui/LoadPasswordActivity.java
new file mode 100644
index 00000000..c7e72049
--- /dev/null
+++ b/app/src/main/java/com/passwordmanager/ui/LoadPasswordActivity.java
@@ -0,0 +1,60 @@
+package com.passwordmanager.ui;
+
+import android.os.Bundle;
+import android.content.Intent;
+import android.widget.Toast;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.view.WindowCompat;
+
+import com.passwordmanager.R;
+import com.passwordmanager.utils.Controller;
+import com.passwordmanager.models.PasswordModel;
+import com.passwordmanager.databinding.ActivityLoadPasswordBinding;
+import com.passwordmanager.ui.adapter.PasswordAdapter;
+
+import java.util.List;
+
+public class LoadPasswordActivity extends AppCompatActivity {
+ private ActivityLoadPasswordBinding binding;
+ private PasswordAdapter passwordAdapter;
+ private Controller controller;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ binding = ActivityLoadPasswordBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
+
+ // Add event onclick listener
+ addOnClickListenerOnButton();
+
+ // Make window fullscreen
+ WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
+ }
+
+ private void fillPasswordList() {
+ controller = new Controller(LoadPasswordActivity.this);
+
+ List passwordList = controller.getAllPasswords();
+ passwordAdapter = new PasswordAdapter(this, passwordList);
+ binding.passwordList.setAdapter(passwordAdapter);
+ }
+
+ // Added all the onclick event listiners
+ private void addOnClickListenerOnButton() {
+ binding.passwordList.setOnItemClickListener((parent, view, position, id) -> {
+ PasswordModel selectedPassword = (PasswordModel) passwordAdapter.getItem(position);
+
+ // Do something with the selectedPassword
+ Intent intent = new Intent(LoadPasswordActivity.this, ViewPasswordActivity.class);
+ intent.putExtra("id", selectedPassword.getId());
+ startActivity(intent);
+ });
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ fillPasswordList();
+ }
+}
diff --git a/app/src/main/java/com/passwordmanager/ui/MainActivity.java b/app/src/main/java/com/passwordmanager/ui/MainActivity.java
new file mode 100644
index 00000000..a80dd48d
--- /dev/null
+++ b/app/src/main/java/com/passwordmanager/ui/MainActivity.java
@@ -0,0 +1,69 @@
+package com.passwordmanager.ui;
+
+import android.os.Bundle;
+import android.content.Intent;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.view.WindowCompat;
+import android.view.LayoutInflater;
+
+import com.passwordmanager.R;
+import com.passwordmanager.databinding.ActivityMainBinding;
+// import com.passwordmanager.utils.Permissions;
+
+public class MainActivity extends AppCompatActivity {
+
+ // private Permissions permissionsHandle;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
+
+ // Add event onclick listener
+ addOnClickListenerOnButton(binding);
+
+ // Make window fullscreen
+ WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
+
+ /* Comment the code as permission is not need to write into app data dir.
+ // Check and request permission when the app is first opened
+ permissionsHandle = new Permissions(this);
+ if (!permissionsHandle.checkPermission()) permissionsHandle.requestPermission();
+ */
+ }
+
+ /* Comment the code as permission is not need to write into app data dir.
+ @Override
+ public void onRequestPermissionsResult(
+ int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (requestCode == Permissions.PERMISSION_REQUEST_CODE) {
+ if (permissionsHandle.isPermissionGranted(grantResults)) {
+ // Permission has been granted
+ Toast.makeText(this, getString(R.string.permission_granted), Toast.LENGTH_LONG).show();
+ } else {
+ // Permission not granted
+ Toast.makeText(this, getString(R.string.permission_denied), Toast.LENGTH_LONG).show();
+ }
+ }
+ }
+ */
+
+ // Added all the onclick event listiners
+ private void addOnClickListenerOnButton(ActivityMainBinding binding) {
+ binding.savePasswordBtn.setOnClickListener(v -> {
+ Intent savepasswordintent = new Intent(MainActivity.this, SavePasswordActivity.class);
+ startActivity(savepasswordintent);
+ });
+
+ binding.loadPasswordBtn.setOnClickListener(v -> {
+ Intent loadpasswordintent = new Intent(MainActivity.this, LoadPasswordActivity.class);
+ startActivity(loadpasswordintent);
+ });
+
+ binding.quitBtn.setOnClickListener(v -> {
+ finishAndRemoveTask();
+ });
+ }
+}
diff --git a/app/src/main/java/com/passwordmanager/ui/SavePasswordActivity.java b/app/src/main/java/com/passwordmanager/ui/SavePasswordActivity.java
new file mode 100644
index 00000000..5a0283c3
--- /dev/null
+++ b/app/src/main/java/com/passwordmanager/ui/SavePasswordActivity.java
@@ -0,0 +1,49 @@
+package com.passwordmanager.ui;
+
+import android.os.Bundle;
+import android.widget.Toast;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.view.WindowCompat;
+
+import com.passwordmanager.R;
+import com.passwordmanager.utils.Controller;
+import com.passwordmanager.databinding.ActivitySavePasswordBinding;
+
+public class SavePasswordActivity extends AppCompatActivity {
+ private Controller controller;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ActivitySavePasswordBinding binding = ActivitySavePasswordBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
+
+ // Add event onclick listener
+ addOnClickListenerOnButton(binding);
+
+ // Make window fullscreen
+ WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
+ }
+
+ // Added all the onclick event listiners
+ private void addOnClickListenerOnButton(ActivitySavePasswordBinding binding) {
+ binding.savePasswordBtn.setOnClickListener(v -> {
+ String domain = binding.inputDomain.getText().toString();
+ String username = binding.inputUsername.getText().toString();
+ String password = binding.inputPassword.getText().toString();
+ String notes = binding.inputNotes.getText().toString();
+
+ controller = new Controller(SavePasswordActivity.this);
+ int res = controller.savePasswordEntity(domain, username, password, notes);
+
+ if (res == -2) {
+ Toast.makeText(SavePasswordActivity.this, getString(R.string.warn_fill_form), Toast.LENGTH_SHORT).show();
+ }
+ else if (res == -1) {
+ Toast.makeText(SavePasswordActivity.this, getString(R.string.fail_msg), Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(SavePasswordActivity.this, getString(R.string.sucess_clause) + res, Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/com/passwordmanager/ui/UpdatePasswordActivity.java b/app/src/main/java/com/passwordmanager/ui/UpdatePasswordActivity.java
new file mode 100644
index 00000000..b078dc41
--- /dev/null
+++ b/app/src/main/java/com/passwordmanager/ui/UpdatePasswordActivity.java
@@ -0,0 +1,75 @@
+package com.passwordmanager.ui;
+
+import android.os.Bundle;
+import android.content.Intent;
+import android.widget.Toast;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.view.WindowCompat;
+import android.view.LayoutInflater;
+
+import com.passwordmanager.R;
+import com.passwordmanager.utils.Controller;
+import com.passwordmanager.models.PasswordModel;
+import com.passwordmanager.databinding.ActivityUpdatePasswordBinding;
+
+/*
+ Activity expects id as intent parameters.
+*/
+
+public class UpdatePasswordActivity extends AppCompatActivity {
+ private int passwordEnitityId = 0;
+ private Controller controller;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ActivityUpdatePasswordBinding binding = ActivityUpdatePasswordBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
+
+ Intent intent = getIntent();
+ passwordEnitityId = intent.getIntExtra("id", -1); // -1 is a invalid id.
+
+ if (passwordEnitityId == -1) { //invalid enitity
+ finish();
+ }
+
+ controller = new Controller(UpdatePasswordActivity.this);
+ PasswordModel passwordmodel = controller.getPasswordById(passwordEnitityId);
+
+ // Put value in text view & edit texts
+ binding.tvId.setText(getString(R.string.id_prefix) + " " + passwordEnitityId);
+ binding.inputDomain.setText(passwordmodel.getDomain());
+ binding.inputUsername.setText(passwordmodel.getUsername());
+ binding.inputPassword.setText(passwordmodel.getPassword());
+ binding.inputNotes.setText(passwordmodel.getNotes());
+
+ // Add event onclick listener
+ addOnClickListenerOnButton(binding);
+
+ // Make window fullscreen
+ WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
+ }
+
+ // Added all the onclick event listiners
+ private void addOnClickListenerOnButton(ActivityUpdatePasswordBinding binding) {
+ binding.updatePasswordBtn.setOnClickListener(v -> {
+ // TODO: implement password update logic.
+ String newDomain = binding.inputDomain.getText().toString();
+ String newUsername = binding.inputUsername.getText().toString();
+ String newPassword = binding.inputPassword.getText().toString();
+ String newNotes = binding.inputNotes.getText().toString();
+
+ int res = controller.updatePassword(passwordEnitityId, newDomain, newUsername, newPassword, newNotes);
+
+ if (res == 1) {
+ Toast.makeText(UpdatePasswordActivity.this, getString(R.string.update_sucess_msg), Toast.LENGTH_SHORT).show();
+
+ finish();
+ } else {
+ Toast.makeText(UpdatePasswordActivity.this, getString(R.string.something_went_wrong_msg), Toast.LENGTH_SHORT).show();
+ }
+
+ finish();
+ });
+ }
+}
diff --git a/app/src/main/java/com/passwordmanager/ui/ViewPasswordActivity.java b/app/src/main/java/com/passwordmanager/ui/ViewPasswordActivity.java
new file mode 100644
index 00000000..c732c7b8
--- /dev/null
+++ b/app/src/main/java/com/passwordmanager/ui/ViewPasswordActivity.java
@@ -0,0 +1,87 @@
+package com.passwordmanager.ui;
+
+import android.os.Bundle;
+import android.content.Intent;
+import android.widget.Toast;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.view.WindowCompat;
+import android.view.LayoutInflater;
+
+import com.passwordmanager.R;
+import com.passwordmanager.utils.Controller;
+import com.passwordmanager.models.PasswordModel;
+import com.passwordmanager.databinding.ActivityViewPasswordBinding;
+
+/*
+ Activity expects id, domain, username, password, notes, createdat, updatedat as intent parameters.
+*/
+
+public class ViewPasswordActivity extends AppCompatActivity {
+ private int passwordEnitityId = 0;
+ private ActivityViewPasswordBinding binding;
+ private Controller controller;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ binding = ActivityViewPasswordBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
+
+ Intent intent = getIntent();
+ passwordEnitityId = intent.getIntExtra("id", 1); // -1 is a invalid id.
+
+ if (passwordEnitityId == -1) { //invalid enitity
+ finish();
+ }
+
+ controller = new Controller(ViewPasswordActivity.this);
+
+ // Filling the textviews with data
+ // fillDataInTextview();
+
+ // Add event onclick listener
+ addOnClickListenerOnButton();
+
+ // Make window fullscreen
+ WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
+ }
+
+ private void fillDataInTextview() {
+ PasswordModel passwordmodel = controller.getPasswordById(passwordEnitityId);
+
+ binding.tvDomain.setText(getString(R.string.domain_prefix) + " " + passwordmodel.getDomain());
+ binding.tvUsername.setText(getString(R.string.username_prefix) + " " + passwordmodel.getUsername());
+ binding.tvPassword.setText(getString(R.string.password_prefix) + " " + passwordmodel.getPassword());
+ binding.tvNotes.setText(getString(R.string.notes_prefix) + " " + passwordmodel.getNotes());
+ binding.tvCreatedAt.setText(getString(R.string.createdat_prefix) + " " + passwordmodel.getCreatedAt());
+ binding.tvUpdatedAt.setText(getString(R.string.updatedat_prefix) + " " + passwordmodel.getUpdatedAt());
+ }
+
+ // Added all the onclick event listiners
+ private void addOnClickListenerOnButton() {
+ binding.updatePasswordBtn.setOnClickListener(v -> {
+ Intent viewpasswordintent = new Intent(ViewPasswordActivity.this, UpdatePasswordActivity.class);
+ viewpasswordintent.putExtra("id", passwordEnitityId);
+ startActivity(viewpasswordintent);
+ });
+
+ binding.deletePasswordBtn.setOnClickListener(v -> {
+ controller = new Controller(ViewPasswordActivity.this);
+ int res = controller.deletePassword(passwordEnitityId);
+
+ if (res == 1) {
+ Toast.makeText(ViewPasswordActivity.this, getString(R.string.delete_sucess_msg), Toast.LENGTH_SHORT).show();
+
+ finish();
+ } else {
+ Toast.makeText(ViewPasswordActivity.this, getString(R.string.something_went_wrong_msg), Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ fillDataInTextview();
+ }
+}
diff --git a/app/src/main/java/com/passwordmanager/ui/adapter/PasswordAdapter.java b/app/src/main/java/com/passwordmanager/ui/adapter/PasswordAdapter.java
new file mode 100644
index 00000000..16f9bcdc
--- /dev/null
+++ b/app/src/main/java/com/passwordmanager/ui/adapter/PasswordAdapter.java
@@ -0,0 +1,57 @@
+package com.passwordmanager.ui.adapter;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.LayoutInflater;
+import android.widget.BaseAdapter;
+
+import com.passwordmanager.models.PasswordModel;
+import com.passwordmanager.databinding.PasswordListItemBinding;
+
+import java.util.List;
+
+public class PasswordAdapter extends BaseAdapter {
+
+ private Context context;
+ private List passwordList;
+
+ public PasswordAdapter(Context context, List passwordList) {
+ this.context = context;
+ this.passwordList = passwordList;
+ }
+
+ @Override
+ public int getCount() {
+ return passwordList.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return passwordList.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ PasswordListItemBinding binding;
+
+ if (convertView == null) {
+ binding = PasswordListItemBinding.inflate(LayoutInflater.from(context), parent, false);
+ convertView = binding.getRoot();
+ convertView.setTag(binding);
+ } else {
+ binding = (PasswordListItemBinding) convertView.getTag();
+ }
+
+ PasswordModel password = passwordList.get(position);
+ binding.tvDomain.setText(password.getDomain());
+ binding.tvUsername.setText(password.getUsername());
+
+ return convertView;
+ }
+}
diff --git a/app/src/main/java/com/passwordmanager/utils/Controller.java b/app/src/main/java/com/passwordmanager/utils/Controller.java
new file mode 100644
index 00000000..255be291
--- /dev/null
+++ b/app/src/main/java/com/passwordmanager/utils/Controller.java
@@ -0,0 +1,186 @@
+package com.passwordmanager.utils;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+
+import java.util.List;
+import java.util.ArrayList;
+
+import com.passwordmanager.database.MyDatabaseHelper;
+import com.passwordmanager.models.PasswordModel;
+
+public class Controller {
+ private MyDatabaseHelper dbHelper;
+
+ public Controller(Context context) {
+ dbHelper = new MyDatabaseHelper(context);
+ }
+
+ public int savePasswordEntity(String domain, String username, String password, String notes) {
+ // Return -2 on empty parameter.
+ // Return -1 on error in SQL.
+ // Return +ve on success.
+
+ if (domain.isEmpty() || username.isEmpty() || password.isEmpty()) {
+ return -2;
+ }
+
+ SQLiteDatabase db = dbHelper.getWritableDatabase();
+
+ ContentValues values = new ContentValues();
+ values.put("domain", domain);
+ values.put("username", username);
+ values.put("password", password);
+ if (!notes.isEmpty()) values.put("notes", notes);
+
+ long newRowId = db.insert(MyDatabaseHelper.PASSWORDS_TABLE, null, values);
+ db.close();
+
+ return newRowId == -1 ? -1 : (int) newRowId;
+ }
+
+ public PasswordModel getPasswordById(int id) {
+ SQLiteDatabase db = dbHelper.getReadableDatabase();
+
+ // Define the selection criteria
+ String selection = "id = ?";
+ String[] selectionArgs = new String[]{String.valueOf(id)};
+
+ Cursor cursor = db.query(
+ MyDatabaseHelper.PASSWORDS_TABLE,
+ null,
+ selection,
+ selectionArgs,
+ null, null, null);
+
+ PasswordModel passwordModel = null;
+
+ if (cursor != null) {
+ if (cursor.moveToFirst()) {
+ String domain = cursor.getString(cursor.getColumnIndex("domain"));
+ String username = cursor.getString(cursor.getColumnIndex("username"));
+ String password = cursor.getString(cursor.getColumnIndex("password"));
+ String notes = cursor.getString(cursor.getColumnIndex("notes"));
+ String createdAt = cursor.getString(cursor.getColumnIndex("createdat"));
+ String updatedAt = cursor.getString(cursor.getColumnIndex("updatedat"));
+
+ passwordModel = new PasswordModel(id, domain, username, password, notes, createdAt, updatedAt);
+ }
+ cursor.close();
+ }
+
+ db.close();
+ return passwordModel;
+ }
+
+ public PasswordModel getPasswordByUsernameAndDomain(String username, String domain) {
+ SQLiteDatabase db = dbHelper.getReadableDatabase();
+
+ // Define the selection criteria
+ String selection = "username = ? AND domain = ?";
+ String[] selectionArgs = new String[]{username, domain};
+
+ Cursor cursor = db.query(
+ MyDatabaseHelper.PASSWORDS_TABLE,
+ null,
+ selection,
+ selectionArgs,
+ null,
+ null,
+ null
+ );
+
+ PasswordModel passwordModel = null;
+
+ if (cursor != null) {
+ if (cursor.moveToFirst()) {
+ int id = cursor.getInt(cursor.getColumnIndex("id"));
+ String retrievedUsername = cursor.getString(cursor.getColumnIndex("username"));
+ String retrievedDomain = cursor.getString(cursor.getColumnIndex("domain"));
+ String password = cursor.getString(cursor.getColumnIndex("password"));
+ String notes = cursor.getString(cursor.getColumnIndex("notes"));
+ String createdAt = cursor.getString(cursor.getColumnIndex("createdat"));
+ String updatedAt = cursor.getString(cursor.getColumnIndex("updatedat"));
+
+ passwordModel = new PasswordModel(id, retrievedDomain, retrievedUsername, password, notes, createdAt, updatedAt);
+ }
+ cursor.close();
+ }
+
+ db.close();
+ return passwordModel;
+ }
+
+ public List getAllPasswords() {
+ List passwordList = new ArrayList();
+ SQLiteDatabase db = dbHelper.getReadableDatabase();
+ Cursor cursor = db.query(MyDatabaseHelper.PASSWORDS_TABLE, null, null, null, null, null, null);
+
+ if (cursor.moveToFirst()) {
+ do {
+ int id = cursor.getInt(cursor.getColumnIndexOrThrow("id"));
+ String domain = cursor.getString(cursor.getColumnIndexOrThrow("domain"));
+ String username = cursor.getString(cursor.getColumnIndexOrThrow("username"));
+ String password = cursor.getString(cursor.getColumnIndexOrThrow("password"));
+ String notes = cursor.getString(cursor.getColumnIndexOrThrow("notes"));
+ String createdAt = cursor.getString(cursor.getColumnIndexOrThrow("createdat"));
+ String updatedAt = cursor.getString(cursor.getColumnIndexOrThrow("updatedat"));
+
+ PasswordModel passwordItem = new PasswordModel(id, domain, username, password, notes, createdAt, updatedAt);
+ passwordList.add(passwordItem);
+ } while (cursor.moveToNext());
+ }
+
+ cursor.close();
+ db.close();
+
+ return passwordList;
+ }
+
+ public int updatePassword(int id, String domain, String username, String password, String notes) {
+ // Return -2 on empty parameter.
+ // Return -1 on error in SQL.
+ // Return number of rows affected on success.
+
+ if (domain.isEmpty() || username.isEmpty() || password.isEmpty()) {
+ return -2;
+ }
+
+ SQLiteDatabase db = dbHelper.getWritableDatabase();
+
+ ContentValues values = new ContentValues();
+ values.put("domain", domain);
+ values.put("username", username);
+ values.put("password", password);
+ values.put("notes", notes);
+
+ int rowsAffected;
+
+ try {
+ rowsAffected = db.update(MyDatabaseHelper.PASSWORDS_TABLE, values, "id = ?", new String[]{String.valueOf(id)});
+
+ if (rowsAffected > 0) {
+ String updateQuery = "UPDATE " + MyDatabaseHelper.PASSWORDS_TABLE + " SET updatedat = datetime('now') WHERE id = ?";
+ db.execSQL(updateQuery, new Object[]{id});
+ }
+ } catch (Exception e) {
+ db.close();
+ return -1; // Error in SQL
+ }
+ db.close();
+
+ return rowsAffected == 0 ? -1 : rowsAffected;
+ }
+
+ public int deletePassword(int id) {
+ // Return number of rows affected (should be 1 if the deletion is successful).
+
+ SQLiteDatabase db = dbHelper.getWritableDatabase();
+ int rowsDeleted = db.delete(MyDatabaseHelper.PASSWORDS_TABLE, "id = ?", new String[]{String.valueOf(id)});
+ db.close();
+
+ return rowsDeleted;
+ }
+}
diff --git a/app/src/main/res/layout/activity_load_password.xml b/app/src/main/res/layout/activity_load_password.xml
new file mode 100644
index 00000000..e86a016c
--- /dev/null
+++ b/app/src/main/res/layout/activity_load_password.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index a4d5b749..86de9d81 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -3,12 +3,61 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
- tools:context=".MainActivity">
+ android:orientation="vertical"
+ tools:context=".ui.MainActivity"
+ android:padding="4sp" >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_save_password.xml b/app/src/main/res/layout/activity_save_password.xml
new file mode 100644
index 00000000..fa1ceb26
--- /dev/null
+++ b/app/src/main/res/layout/activity_save_password.xml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_update_password.xml b/app/src/main/res/layout/activity_update_password.xml
new file mode 100644
index 00000000..7bad6921
--- /dev/null
+++ b/app/src/main/res/layout/activity_update_password.xml
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_view_password.xml b/app/src/main/res/layout/activity_view_password.xml
new file mode 100644
index 00000000..99e7f3d7
--- /dev/null
+++ b/app/src/main/res/layout/activity_view_password.xml
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/password_list_item.xml b/app/src/main/res/layout/password_list_item.xml
new file mode 100644
index 00000000..e36c7e35
--- /dev/null
+++ b/app/src/main/res/layout/password_list_item.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5d258bd9..f4904f18 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,7 +1,46 @@
Password Manager
-
-
+ v0.1.0-Alpha
+
+
+ Quit
+
+
+ Domain
+ Username
+ Password
+ Notes
+
+ Save Password
+ Load Password
+ Update Password
+ Delete Password
+
+
+ Load Password
+ Save Password
+ View Password
+ View Password
+
+
+ Id:
+ Domain:
+ Username:
+ Password:
+ Notes:
+ CreatedAt:
+ UpdatedAt:
+
+
Permission Granted
Permission Denied
+
+
+ 404: Not Found!!
+ Warning: please fill the form first!!
+ Failed: please try again!!
+ Success:
+ Updated Successfully!!
+ Deleted Successfully!!
+ Something Went Wrong!!
\ No newline at end of file
diff --git a/installondevice.bat b/installondevice.bat
new file mode 100644
index 00000000..418147d0
--- /dev/null
+++ b/installondevice.bat
@@ -0,0 +1,41 @@
+@REM Build & install on Android phone
+
+@REM Force continuation after Gradle command by capturing the output
+call gradle build
+if ERRORLEVEL 1 (
+ echo Gradle build failed! Check build_output.txt for details.
+ exit /b 1
+)
+
+@REM Start ADB server
+adb start-server
+if ERRORLEVEL 1 (
+ echo Failed to start ADB server! Exiting...
+ exit /b 1
+)
+
+@REM Check if a device is connected
+adb devices
+if ERRORLEVEL 1 (
+ echo No device found! Make sure your device is connected and USB debugging is enabled.
+ adb kill-server
+ exit /b 1
+)
+
+@REM Install the APK on the connected device
+adb install ./app/build/outputs/apk/release/app-universal-release.apk
+if ERRORLEVEL 1 (
+ echo APK installation failed! Exiting...
+ adb kill-server
+ exit /b 1
+)
+
+@REM Kill ADB server after installation
+adb kill-server
+if ERRORLEVEL 1 (
+ echo Failed to stop ADB server! Exiting...
+ exit /b 1
+)
+
+echo Build and installation completed successfully!
+exit /b 0
diff --git a/lint.xml b/lint.xml
new file mode 100644
index 00000000..e1452c37
--- /dev/null
+++ b/lint.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index 8ce983c4..cfdf065f 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -3,7 +3,7 @@ dependencyResolutionManagement {
repositories {
google()
mavenCentral()
- jcenter() // Warning: this repository is going to shut down soon
+ // jcenter()
}
}
rootProject.name = "Password Manager"