You are on page 1of 18

Introduction:

After SDK 1.5, an API was made available for executing Note taking in Android Activities,
without worrying with threads and manners to access the UI. For that, onemust use
Notetaking. Here a simple example is provided of how to properly use this API. Later, it will
be discussed when to use (and when not to use) this API.

Literature Review:

 Note-taking applications have become an integral part of our digital lives, allowing us to
capture and organize our thoughts, ideas, and important information. In this digital age,
where visual content and web links play a crucial role in communication and
information sharing, the inclusion of image and URL support in a note-taking
application becomes highly relevant and beneficial.

 Note-taking applications have become indispensable tools for organizing and managing
information effectively. With the inclusion of a delete note feature, users can maintain a clutter-
free note repository by removing unnecessary or outdated content. This addition improves
overall note management and optimizes the user experience.

 Note-taking applications have become essential tools for managing and organizing information.
With the integration of an advanced search feature, users can effortlessly locate specific notes
among a vast collection, significantly enhancing productivity and reducing the time spent in
information retrieval.

 In today's digital landscape, users seek transparency and connection with the applications they
use. The inclusion of an "About Us" page in the Android note-taking application allows users to
understand the people behind the app, their motivations, and the principles guiding its
development. This fosters a sense of trust and establishes a user-centric environment.

Page | 1
 The user will access the applications through the device of their choice, commonly via a laptop
or tablet. Some note-taking applications are available cross-platform and on multiple devices
while others may be limited to one platform or device. For example, Notability is only
available within Apple products whereas OneNote markets their availability across all
platforms and devices.

 The user will access the applications through the device of their choice, commonly via a laptop
or tablet. Some note-taking applications are available cross-platform and on multiple devices
while others may be limited to one platform or device. For example, Notability is only
available within Apple products whereas OneNote markets their availability across all
platforms and devices.

Page | 2
ABSTRACT

 This report presents a detailed account of the development process and key features of an
Android note-taking application. The application aims to provide users with a seamless and
intuitive interface to capture, organize, and manage their notes effectively.

 The report covers various aspects of the development lifecycle, including project planning,
design considerations, implementation details, testing methodologies, and future
enhancements. Through this report, readers will gain insights into the challenges faced and the
solutions implemented during the development of the note-taking application.

 This article highlights the advancements made in the Android note-taking application, which
now includes the ability to add images and URLs to notes. Additionally, the application
incorporates intelligent validation checks to ensure that users enter valid URLs and that the
title and note text fields are not left empty.

 This feature enhancement significantly enhances the versatility and usability of the
application, enabling users to capture and organize multimedia-rich content with ease. This
article provides a detailed description of the implementation process and outlines the benefits
of these new features.

 This article focuses on the integration of a delete note feature in the Android note-taking
application. The delete note functionality enhances the user experience by allowing users to
efficiently remove unwanted or outdated notes. This article outlines the implementation details
of the delete note feature, discusses its benefits, and highlights the impact on note organization
and user productivity.

Page | 3
SNAPSHOT

Search feature in the Android note-taking application, enabling


users to quickly retrieve specific notes based on search queries.
The search functionality enhances user productivity and
organization by facilitating the efficient location of relevant
information within a large note collection.

This article delves into the implementation details of the search


feature, explores its benefits, and discusses its impact on user
experience and note management.

Page | 4
 The note-taking application now allows users to add images directly to their notes.
This functionality is achieved by integrating the device's camera or image gallery,
enabling users to capture new images or select existing ones...

 The inclusion of URL support allows users to embed web links within their notes.
When adding a URL, the application validates the entered link to ensure its
correctness and prevent broken or invalid URLs.

Page | 5
About

 This article explores the significance and implementation of an "About Us" page in the Android
note-taking application. The "About Us" page provides users with valuable insights into the
application's development team, their vision, and the core values driving the app's creation.

 By incorporating an "About Us" page, the note-taking application fosters transparency, trust, and
a user-centric environment.

 This article discusses the importance of an "About Us" page, outlines its key components, and
highlights the impact on user engagement and satisfaction.

Page | 6
XML CODE

<?xml version="1.0" encoding="utf-8"?>


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
/>

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/App_Name"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.NotesApp"
tools:targetApi="q">
<activity
android:name=".activities.About_Us"
android:exported="false" />
<activity
android:name=".activities.AddNote"
android:exported="false"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden" />
<activity
android:name=".activities.MainActivity"
android:exported="true"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />


</intent-filter>
</activity>
</application>

</manifest>

Page | 7
MainActivity.java
package com.example.notesapp.activities;

import static androidx.recyclerview.widget.StaggeredGridLayoutManager.*;


import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;

import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.widget.EditText;
import android.widget.ImageView;

import com.example.notesapp.R;
import com.example.notesapp.adapters.NotesAdapter;
import com.example.notesapp.database.NotesDB;
import com.example.notesapp.entities.Note;
import com.example.notesapp.listeners.NotesListeners;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class MainActivity extends AppCompatActivity implements NotesListeners{

private RecyclerView notesRecyclerView;


private List<Note> noteLists;
private NotesAdapter
notesAdapter;

public static final int REQUEST_CODE_ADD_NOTE = 1;


public static final int REQUEST_CODE_UPDATE_NOTE = 2;
public static final int REQUEST_CODE_SHOW_NOTES = 3;

private int noteClickedPosition = -1;


private ActivityResultLauncher<Intent> addNoteLauncher;
private ActivityResultLauncher<Intent> viewUpdateNoteLauncher;
@Override
protected void onCreate(Bundle savedInstanceState) {
Page | 8
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

ImageView img_AddNoteMain = findViewById(R.id.add_btn_main);

//Activity launcher register for adding the notes


addNoteLauncher = registerForActivityResult(new
ActivityResultContracts.StartActivityForResult(),result -> {
if(result.getResultCode() == RESULT_OK && result.getData() != null){
getNotes(REQUEST_CODE_ADD_NOTE,false);
}else{
Log.d("Add note","Add note");
}
});

//Activity launcher register for viewing or updating the notes


viewUpdateNoteLauncher = registerForActivityResult(new
ActivityResultContracts.StartActivityForResult(),result -> {
Intent data = result.getData();
if(result.getResultCode() == RESULT_OK && result.getData() != null){

getNotes(REQUEST_CODE_UPDATE_NOTE,data.getBooleanExtra("isNoteDeleted",false));
}else{
Log.d("View or update","Updated note");
}
img_AddNoteMain.setOnClickListener(v -> {
Intent it = new Intent(getApplicationContext(), AddNote.class);
it.putExtra("requestCode",REQUEST_CODE_ADD_NOTE);
addNoteLauncher.launch(it);
});

notesRecyclerView = findViewById(R.id.layout_recycler);

notesRecyclerView.setLayoutManager(new
StaggeredGridLayoutManager(2,VERTICAL));

noteLists = new ArrayList<>();


notesAdapter = new NotesAdapter(noteLists,this);
notesRecyclerView.setAdapter(notesAdapter);

getNotes(REQUEST_CODE_SHOW_NOTES,false);

//Functionality for search note


EditText inpSearch = findViewById(R.id.inp_search);
inpSearch.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
Page | 9
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
notesAdapter.cancelTimer();
}
@Override
public void afterTextChanged(Editable s) {
if(noteLists.size() != 0){
notesAdapter.searchNotes(s.toString());

//After clicking the about us button in quick actions then redirecting to about us
page findViewById(R.id.img_aboutUs).setOnClickListener(v->{
Intent it = new Intent(getApplicationContext(),About_Us.class);
startActivity(it);
});

@Override
public void onNoteClicked(Note note, int position) {
noteClickedPosition = position;
Intent it = new Intent(getApplicationContext(),
AddNote.class); it.putExtra("isViewOrUpdate",true);
it.putExtra("note",note);
it.putExtra("requestCode",REQUEST_CODE_UPDATE_NOTE);
viewUpdateNoteLauncher.launch(it);
}

// Function to display the notes in recycler view

private void getNotes(final int requestCode,final boolean isNoteDeleted){

ExecutorService executor = Executors.newSingleThreadExecutor();

Future<List<Note>> future = executor.submit(()->


NotesDB.getDatabase(getApplicationContext()).notes_dao().getAllNotes());

executor.execute(()->{
try {
List<Note> notes = future.get();

//Displaying the notes after the following operations


if(requestCode == REQUEST_CODE_SHOW_NOTES){
noteLists.addAll(notes);
notesAdapter.notifyDataSetChanged();
}else if(requestCode == REQUEST_CODE_ADD_NOTE){
noteLists.add(0,notes.get(0));
notesAdapter.notifyItemInserted(0);

Page | 10
}else if(requestCode == REQUEST_CODE_UPDATE_NOTE){
noteLists.remove(noteClickedPosition);

//After deleting the note


if(isNoteDeleted){
notesAdapter.notifyItemRemoved(noteClickedPosition);
}else{ noteLists.add(noteClickedPosition,notes.get(noteClickedPositi
on)); notesAdapter.notifyItemChanged(noteClickedPosition);
}
}
notesRecyclerView.smoothScrollToPosition(0);
}catch (Exception e){
e.printStackTrace();
}finally {
executor.shutdown();
}
}
}
Function to initialize the miscellaneous layout
private void initMiscellaneous(){
final LinearLayout layoutMiscellaneous = findViewById(R.id.layout_miscellaneous);
final BottomSheetBehavior<LinearLayout> bottomSheetBehaviorLayout =
BottomSheetBehavior.from(layoutMiscellaneous);
layoutMiscellaneous.findViewById(R.id.txtMiscellaneous).setOnClickListener(v -> {
if(bottomSheetBehaviorLayout.getState() != BottomSheetBehavior.STATE_EXPANDED){
bottomSheetBehaviorLayout.setState(BottomSheetBehavior.STATE_EXPANDED);
}else{
bottomSheetBehaviorLayout.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
});

//Function after selecting the color for the note

final ImageView imgColor1 = findViewById(R.id.imgColor1);


final ImageView imgColor2 = findViewById(R.id.imgColor2);
final ImageView imgColor3 = findViewById(R.id.imgColor3);
final ImageView imgColor4 = findViewById(R.id.imgColor4);
final ImageView imgColor5 = findViewById(R.id.imgColor5);

layoutMiscellaneous.findViewById(R.id.view_color1).setOnClickListener(v -> {
selectedNoteColor = "#333333";
imgColor1.setImageResource(R.drawable.ic_done);
imgColor2.setImageResource(0);
imgColor3.setImageResource(0);
imgColor4.setImageResource(0);
imgColor5.setImageResource(0);
setViewSubtitleIndicatorColor();
});
layoutMiscellaneous.findViewById(R.id.view_color2).setOnClickListener(v -> {
Page | 11
selectedNoteColor = "#fdbe3b";
imgColor1.setImageResource(0);
imgColor2.setImageResource(R.drawable.ic_done);
imgColor3.setImageResource(0);
imgColor4.setImageResource(0);
imgColor5.setImageResource(0);
setViewSubtitleIndicatorColor();
});
layoutMiscellaneous.findViewById(R.id.view_color3).setOnClickListener(v -> {
selectedNoteColor = "#ff4842";
imgColor1.setImageResource(0);
imgColor2.setImageResource(0);
imgColor3.setImageResource(R.drawable.ic_done);
imgColor4.setImageResource(0);
imgColor5.setImageResource(0);
setViewSubtitleIndicatorColor();
});
layoutMiscellaneous.findViewById(R.id.view_color4).setOnClickListener(v -> {
selectedNoteColor = "#3a52fc";
imgColor1.setImageResource(0);
imgColor2.setImageResource(0);
imgColor3.setImageResource(0);
imgColor4.setImageResource(R.drawable.ic_done);
imgColor5.setImageResource(0);
setViewSubtitleIndicatorColor();
});
layoutMiscellaneous.findViewById(R.id.view_color5).setOnClickListener(v -> {
selectedNoteColor = "#01BABA";
imgColor1.setImageResource(0);
imgColor2.setImageResource(0);
imgColor3.setImageResource(0);
imgColor4.setImageResource(0);
imgColor5.setImageResource(R.drawable.ic_done);
setViewSubtitleIndicatorColor();
});

//Setting the color of the above if already available during view or update
if(alreadyAvailableNote != null && alreadyAvailableNote.getColor() != null && !
alreadyAvailableNote.getColor().trim().isEmpty()){
switch (alreadyAvailableNote.getColor()){
case "#fdbe3b" :
layoutMiscellaneous.findViewById(R.id.view_color2).performClick();
break;
case "#ff4842" :
layoutMiscellaneous.findViewById(R.id.view_color3).performClick();
break;
case "#3a52fc" :
layoutMiscellaneous.findViewById(R.id.view_color4).performClick();
break;
case "#01BABA" :
layoutMiscellaneous.findViewById(R.id.view_color5).performClick();

Page | 12
break;
}
}

//After clicking the add image layout


layoutMiscellaneous.findViewById(R.id.layout_AddImage).setOnClickListener(v -> {
bottomSheetBehaviorLayout.setState(BottomSheetBehavior.STATE_COLLAPSED);

//Getting the permission from the user to access the media to select the image
if(ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.READ_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(AddNote.this,new String[]
{Manifest.permission.READ_EXTERNAL_STORAGE},REQUEST_CODE_STORAGE_PERMI
SSION);
}
//Else if the permission is already given directly selecting the Image
else{
selectImage();
}
});

//After clicking the add url/link button

layoutMiscellaneous.findViewById(R.id.layout_AddUrl).setOnClickListener(view ->{
bottomSheetBehaviorLayout.setState(BottomSheetBehavior.STATE_COLLAPSED);
showAddUrlDialog();
});

//Functionality for deleting the note

//If there is already note available then displaying the delete note functionality
if(alreadyAvailableNote != null){
layoutMiscellaneous.findViewById(R.id.layout_deleteNote).setVisibility(View.VISIBLE);
//After clicking the delete button
layoutMiscellaneous.findViewById(R.id.layout_deleteNote).setOnClickListener(v ->{
bottomSheetBehaviorLayout.setState(BottomSheetBehavior.STATE_COLLAPSED);
showDeleteNoteDialog();
});
}

//Function to set the color of the subtitle Indicator


private void setViewSubtitleIndicatorColor(){

Drawable bg = viewSubtitleIndicator.getBackground();
if(bg instanceof GradientDrawable){

GradientDrawable gradientDrawable = (GradientDrawable) bg;


Page | 13
gradientDrawable.setColor(Color.parseColor(selectedNoteColor));

}else if(bg instanceof ColorDrawable){


viewSubtitleIndicator.setBackgroundColor(Color.parseColor(selectedNoteColor));
}
}

//Function to select the image


private void selectImage() {

Intent it = new Intent(Intent.ACTION_PICK,


MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

//Launching the activity for the activityResult Handler


addImageLauncher.launch(it);
}

//Handling the permission if the user has given the permission or not
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == REQUEST_CODE_STORAGE_PERMISSION && grantResults.length>0){
// If permission granted or given then selectImage

if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
selectImage();
}
//Otherwise displaying the toast message as permission denied
else {
Toast.makeText(this,"Permission Denied",Toast.LENGTH_SHORT).show();
}
}
}

//Function to get The path of the image from the uri


private String getPathFromUri(Uri contentUri){
String filePath;
Cursor cursor = getContentResolver().query(contentUri,null,null,null,null);

if(cursor == null){
filePath = contentUri.getPath();

}else{
cursor.moveToFirst();
int index = cursor.getColumnIndex("_data");
filePath = cursor.getString(index);
cursor.close();
}
return filePath;
Page | 14
//Function to show the add url dialog box
private void showAddUrlDialog(){
if(addUrlDialog == null){
AlertDialog.Builder builder = new AlertDialog.Builder(AddNote.this);
View v = LayoutInflater.from(this).inflate(R.layout.layout_add_url,
findViewById(R.id.layout_AddUrl_Container));
builder.setView(v);

addUrlDialog = builder.create();
if(addUrlDialog != null){
addUrlDialog.getWindow().setBackgroundDrawable(new ColorDrawable(0));
}

final EditText inpAddUrl = v.findViewById(R.id.edt_url);


inpAddUrl.requestFocus();

//After clicking the add button in the dialog box

v.findViewById(R.id.txt_Add).setOnClickListener(view -> {

if(inpAddUrl.getText().toString().trim().isEmpty()){
Toast.makeText(this,"Enter a url",Toast.LENGTH_SHORT).show();
}else if(!Patterns.WEB_URL.matcher(inpAddUrl.getText().toString()).matches()){
Toast.makeText(this, "Enter a valid url", Toast.LENGTH_SHORT).show();
}else{
txtUrl.setText(inpAddUrl.getText().toString());
layoutUrl.setVisibility(View.VISIBLE);
inpAddUrl.setText(null);
addUrlDialog.dismiss();
}
});

//After clicking the cancel button in the dialog box


v.findViewById(R.id.txt_Cancel).setOnClickListener(view -> addUrlDialog.dismiss());

addUrlDialog.show();

//Function to show the delete note dialog box


private void showDeleteNoteDialog() {
if (deleteNoteDialog == null) {
AlertDialog.Builder builder = new AlertDialog.Builder(AddNote.this);
View view = LayoutInflater.from(this).inflate(R.layout.layout_delete_note,
findViewById(R.id.layout_deleteNote_Container));
builder.setView(view);
deleteNoteDialog = builder.create();
Page | 15
if(deleteNoteDialog.getWindow() != null){
deleteNoteDialog.getWindow().setBackgroundDrawable(new ColorDrawable(0));
}
//Running the delete note functionality in thr background and redirecting to the home page
view.findViewById(R.id.txt_delete).setOnClickListener(v ->{
ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(() -> {

//Deleting the selected note or opened note


NotesDB.getDatabase(getApplicationContext()).notes_dao().deleteNote(alreadyAvailableNote);

//deleting the note


try {
// Note saved successfully, perform any required actions (e.g., update UI)
runOnUiThread(() -> {
Intent it = new Intent();
it.putExtra("isNoteDeleted",true);
setResult(RESULT_OK, it);
finish();
});
} catch (Exception e) {
// Handle the exception (e.g., show an error message)
e.printStackTrace();
}finally {
// Shutdown the executor service
service.shutdown();
}
});
});

//After clicking the cancel button in the dialog box


view.findViewById(R.id.txt_Cancel).setOnClickListener(v -> deleteNoteDialog.dismiss());
}
deleteNoteDialog.show();

}
}

Page | 16
CONCLUSION

 The integration of an advanced search feature in the Android note-taking application


revolutionizes note retrieval and organization. Users can effortlessly locate specific
notes within a vast collection, promoting efficiency, productivity, and time-saving.

 The search functionality complements existing organizational methods and enhances


the flexibility of note management. The seamless integration of the search feature in
the user interface ensures a user-friendly experience, further improving the
application's value and usability.

 With its ability to streamline information retrieval and optimize note management, the
advanced search feature significantly contributes to a productive and organized note-
taking environment.

 The development of the Android note-taking application has been a success, providing
users with a powerful tool to capture, organize, and manage their notes effectively.
The project has demonstrated the team's expertise in design, implementation, testing,
and deployment of a feature-rich mobile application.

 The note-taking application has the potential to make a significant impact on users'
productivity and organization, contributing to their success in both personal and
professional spheres.

Page | 17
REFERENCES

 Android Studio Documentation: Official documentation provided by Google for


Android Studio and its features. Available at:
https://developer.android.com/studio/intro

 Android Developers Documentation: Comprehensive documentation covering


various aspects of Android app development, including guides, API references,
samples, and best practices. Available at: https://developer.android.com/docs

 Android Studio User Guide: A detailed guide that covers the usage and features of
Android Studio, including installation, project setup, debugging, and more.
Available at: https://developer.android.com/studio/intro/studio-config

 Stack Overflow: An online community where developers ask questions and find
answers related to Android development. Available at:
https://stackoverflow.com/questions/tagged/android

 GitHub: A code hosting platform that hosts open-source Android projects. You
can explore repositories, access source code, and learn from real-world examples.
Available at: https://github.com/topics/android

Page | 18

You might also like