diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..681f41a --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,116 @@ + + + + + + + +
+ + + + xmlns:android + + ^$ + + + +
+
+ + + + xmlns:.* + + ^$ + + + BY_NAME + +
+
+ + + + .*:id + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:name + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + name + + ^$ + + + +
+
+ + + + style + + ^$ + + + +
+
+ + + + .* + + ^$ + + + BY_NAME + +
+
+ + + + .* + + http://schemas.android.com/apk/res/android + + + ANDROID_ATTRIBUTE_ORDER + +
+
+ + + + .* + + .* + + + BY_NAME + +
+
+
+
+
+
\ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/vob/scanit/PDFProcessing.kt b/app/src/main/java/com/vob/scanit/PDFProcessing.kt index 90d7fb3..05e2476 100644 --- a/app/src/main/java/com/vob/scanit/PDFProcessing.kt +++ b/app/src/main/java/com/vob/scanit/PDFProcessing.kt @@ -17,24 +17,24 @@ import java.io.* import java.util.* import kotlin.collections.ArrayList +/* The following class enables us to generate, compress and save PDF documents*/ public class PDFProcessing(context: Context) { lateinit var pdfDocument: PdfDocument val context = context - + /*makePDF() is used to create a new PDF document, start a page, write content to it and save the document*/ public fun makePDF(bitmap: Bitmap, filename: String) { - pdfDocument = PdfDocument() - + pdfDocument = PdfDocument() //create a new PDF document val compressedBitmap = compressBitmap(bitmap) val pageInfo: PdfDocument.PageInfo = PdfDocument.PageInfo.Builder(compressedBitmap.width, compressedBitmap.height, 1).create() - val page: PdfDocument.Page = pdfDocument.startPage(pageInfo) + val page: PdfDocument.Page = pdfDocument.startPage(pageInfo) //start a page val canvas: Canvas = page.getCanvas() val paint = Paint() paint.setColor(Color.parseColor("#FFFFFF")) canvas.drawBitmap(compressedBitmap, 0.0f, 0.0f, null) - pdfDocument.finishPage(page) + pdfDocument.finishPage(page) //finish the page //if (fileName.getText().toString().isEmpty()) { // Toast.makeText(context, "You need to enter file name as follow\nyour_fileName.pdf", Toast.LENGTH_SHORT).show() //} @@ -44,13 +44,14 @@ public class PDFProcessing(context: Context) { saveFileToScopedStorage(filename) } - else + else //if filename does not have .pdf extension, we append it with the extension before calling save method { //saveFile("$filename.pdf") saveFileToScopedStorage("$filename.pdf") } } + /*The following function compresses the document to a standard size*/ private fun compressBitmap(bitmap: Bitmap): Bitmap { val originalHeight = bitmap.height val originalWidth = bitmap.width @@ -73,14 +74,13 @@ public class PDFProcessing(context: Context) { return compressedBitmap } - + /* saveFile() writes the PDF document to the output stream */ fun saveFile(filename: String) { if (pdfDocument == null) { return } val root = File(Environment.getExternalStorageDirectory().absolutePath, "Scanner") - var isDirectoryCreated: Boolean = root.exists() if (!isDirectoryCreated) { isDirectoryCreated = root.mkdir() @@ -104,6 +104,8 @@ public class PDFProcessing(context: Context) { return true } + /* The following function saves the PDF file. It uses the ContentValues class to store a + * set of values that the ContentResolver can process. The put() method adds a value to the set */ // fun queryScopedStorage() : ArrayList { // val projection = arrayOf( // MediaStore.MediaColumns.DISPLAY_NAME, diff --git a/app/src/main/java/com/vob/scanit/ThemeConfig.kt b/app/src/main/java/com/vob/scanit/ThemeConfig.kt index 7bffb4b..d2961e2 100644 --- a/app/src/main/java/com/vob/scanit/ThemeConfig.kt +++ b/app/src/main/java/com/vob/scanit/ThemeConfig.kt @@ -4,6 +4,9 @@ import android.content.Context import android.content.res.Configuration import androidx.appcompat.app.AppCompatDelegate +/*This kotlin file defines the themes for the app, which allows the user to toggle between system theme, +* light theme and dark theme*/ + fun currentSystemTheme(context: Context):Int{ return when(context.resources.configuration.uiMode.and(Configuration.UI_MODE_NIGHT_MASK)){ Configuration.UI_MODE_NIGHT_NO -> 1 diff --git a/app/src/main/java/com/vob/scanit/adapters/DocumentListAdapter.kt b/app/src/main/java/com/vob/scanit/adapters/DocumentListAdapter.kt index 5f41b7a..a7a7437 100644 --- a/app/src/main/java/com/vob/scanit/adapters/DocumentListAdapter.kt +++ b/app/src/main/java/com/vob/scanit/adapters/DocumentListAdapter.kt @@ -8,28 +8,38 @@ import androidx.recyclerview.widget.RecyclerView import com.vob.scanit.R import java.io.File +/* DocumentListAdapter class extends RecyclerView.Adapter, and overrides the methods needed for the +* Adapter to work. */ class DocumentListAdapter(private val documentList: ArrayList): RecyclerView.Adapter() { + /* DocumentViewHolder class extends RecyclerView.ViewHolder. It is used to represent the items in + our list and display them. */ class DocumentViewHolder(var view: View): RecyclerView.ViewHolder(view) {} + /* The following method updates the list of documents and informs the listener*/ fun updateDocumentList(newDocumentList: List) { documentList.clear() documentList.addAll(newDocumentList) notifyDataSetChanged() } + /*The following method is called when the Adapter is created and is used to initialise the ViewHolder. + * LayoutInflater class is used to convert the xml file(adapter_pdf) to a view*/ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DocumentViewHolder { val inflater = LayoutInflater.from(parent.context) val view = inflater.inflate(R.layout.adapter_pdf, parent, false) return DocumentViewHolder(view) } + /* The function onBindViewHolder() is called for each ViewHolder and is used to bind it to the Adapter. + * We pass the data to our ViewHolder using this function*/ override fun onBindViewHolder(holder: DocumentViewHolder, position: Int) { val filename = holder.view.findViewById(R.id.filename_TV) filename.text = documentList.get(position).name } + /* getItemCount() method returns the number of items in the list that we want to display */ override fun getItemCount(): Int { return documentList.size } diff --git a/app/src/main/java/com/vob/scanit/adapters/PDFAdapter.java b/app/src/main/java/com/vob/scanit/adapters/PDFAdapter.java index f6f61b4..968182f 100644 --- a/app/src/main/java/com/vob/scanit/adapters/PDFAdapter.java +++ b/app/src/main/java/com/vob/scanit/adapters/PDFAdapter.java @@ -31,6 +31,7 @@ import java.util.Locale; import java.util.logging.Handler; +/* PDFAdapter class extends ArrayAdapter, specifying the type of data the adapter must display*/ public class PDFAdapter extends ArrayAdapter { Context context; @@ -40,6 +41,8 @@ public class PDFAdapter extends ArrayAdapter { private ImageView options_btn; Activity activity; + /*Defining a constructor that takes in arguments used to initialise the class variables + * This is required for inflating and adding data to our view */ public PDFAdapter(Context context, ArrayList fileList, Activity activity) { super(context, R.layout.adapter_pdf, fileList); this.context = context; @@ -48,11 +51,13 @@ public PDFAdapter(Context context, ArrayList fileList, Activity activity) this.searchList.addAll(this.fileList); } + /*The following method returns the view type of the item at position*/ @Override public int getItemViewType(int position) { return position; } + /*The following method returns the number of different types of views*/ @Override public int getViewTypeCount() { if (fileList.size() > 0) @@ -61,6 +66,8 @@ public int getViewTypeCount() { return 1; } + /* We override the method getView() that is called when the items are created and populated with data + * In this method, the view gets inflated if the view is new (check for null) */ @NonNull @Override public View getView(int position, @Nullable View view, @NonNull ViewGroup parent) { @@ -90,6 +97,11 @@ public void onClick(View v) { return view; } + /* In the following method, we find the file searched for by the user. + We convert the text we receive into the lowercase characters of the language in the region + where the app is being used(using Locale.getDefault()). + Using notifyDataSetChanged(), we can notify the listeners attached to our adapter about the + changes in the underlying data, so that any view reflecting this data can be refreshed accordingly*/ public void filter(String characterText) { characterText = characterText.toLowerCase(Locale.getDefault()); fileList.clear(); @@ -110,6 +122,7 @@ public void filter(String characterText) { notifyDataSetChanged(); } + /* We define a ViewHolder class to be used with our Adapter */ public class ViewHolder { TextView filename; diff --git a/app/src/main/java/com/vob/scanit/adapters/PdfAdapterRv.kt b/app/src/main/java/com/vob/scanit/adapters/PdfAdapterRv.kt index 3b699bd..6fb044f 100644 --- a/app/src/main/java/com/vob/scanit/adapters/PdfAdapterRv.kt +++ b/app/src/main/java/com/vob/scanit/adapters/PdfAdapterRv.kt @@ -15,12 +15,16 @@ import java.io.File import java.util.* import kotlin.collections.ArrayList +/* PdfAdapterRv class extends RecyclerView.Adapter and takes in arguments and a listener, + along with overriding the methods needed for the Adapter to work. */ + class PdfAdapterRv(private val context: Context, private val activity: Activity, private val fileList: ArrayList,private val pdfInterface: PdfAdapterInterface) : RecyclerView.Adapter(){ private val searchList: ArrayList = ArrayList() + /* PdfAdapterViewHolder contains all the elements that gets displayed in the recycler view */ inner class PdfAdapterViewHolder(itemView: View):RecyclerView.ViewHolder(itemView){ val fileName: TextView = itemView.findViewById(R.id.filename_TV) @@ -28,11 +32,14 @@ class PdfAdapterRv(private val context: Context, private val activity: Activity, } + /* Informs the activity when the item gets clicked */ interface PdfAdapterInterface{ fun onItemClicked(position: Int) fun onItemLongClicked(position: Int) } + /*onCreateViewHolder() is called when the Adapter is created and returns an instance of the + PdfAdapterViewHolder. In this function, we handle the onClick event by displaying a toast message*/ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PdfAdapterViewHolder { val viewHolder = PdfAdapterViewHolder( LayoutInflater.from(context).inflate(R.layout.adapter_pdf, parent, false)) @@ -44,22 +51,29 @@ class PdfAdapterRv(private val context: Context, private val activity: Activity, return viewHolder } + /*onBindViewHolder() is called for each ViewHolder and used to define the actions on it */ override fun onBindViewHolder(holder: PdfAdapterViewHolder, position: Int) { holder.fileName.text = fileList[position].name - holder.itemView.setOnClickListener{ + holder.itemView.setOnClickListener { pdfInterface.onItemClicked(position) } - holder.itemView.setOnLongClickListener{ + holder.itemView.setOnLongClickListener { pdfInterface.onItemLongClicked(position) true } } + /* getItemCount() method returns the number of items in the list that we want to display */ override fun getItemCount(): Int { return fileList.size } + /* In the following method, we find the file searched for by the user. + We convert the text we receive into the lowercase characters of the language in the region + where the app is being used (using Locale.getDefault()). + Using notifyDataSetChanged(), we can notify the listener attached to our adapter about the + changes in the underlying data, so that any view reflecting this data can be refreshed accordingly */ fun filter(characterText: String) { var characterText = characterText characterText = characterText.toLowerCase(Locale.getDefault()) diff --git a/app/src/main/java/com/vob/scanit/model/Documents.kt b/app/src/main/java/com/vob/scanit/model/Documents.kt index 0d97979..ea28cd8 100644 --- a/app/src/main/java/com/vob/scanit/model/Documents.kt +++ b/app/src/main/java/com/vob/scanit/model/Documents.kt @@ -3,6 +3,7 @@ package com.vob.scanit.model import android.net.Uri import java.util.* +/* We define a data class and specify the arguments to be passed into its constructor */ data class Documents( val id: Long, val displayName: String, diff --git a/app/src/main/java/com/vob/scanit/ui/BottomSheetDialog.java b/app/src/main/java/com/vob/scanit/ui/BottomSheetDialog.java index a2735e0..7538ca6 100644 --- a/app/src/main/java/com/vob/scanit/ui/BottomSheetDialog.java +++ b/app/src/main/java/com/vob/scanit/ui/BottomSheetDialog.java @@ -21,6 +21,8 @@ import java.io.File; +/* BottomSheetDialog implements BottomSheetDialogFragment to display a dialog with three options for the + corresponding file: Share, Delete and Rename */ public class BottomSheetDialog extends BottomSheetDialogFragment { File file; @@ -28,6 +30,7 @@ public BottomSheetDialog(File file) { this.file = file; } + /*Following function inflates the XML file to show the dialog box with the three options*/ @Override public View onCreateView(final LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @@ -40,6 +43,7 @@ public View onCreateView(final LayoutInflater inflater, @Nullable Button shareBtn = v.findViewById(R.id.share_btn); Button renameBtn = v.findViewById(R.id.rename_btn); + /*Opens a dialog box with options for the user to choose from to share the file with*/ shareBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) @@ -52,6 +56,7 @@ public void onClick(View v) } }); + /* Renames the file and dismisses the dialog */ renameBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -59,6 +64,7 @@ public void onClick(View v) { } }); + /* Deletes the file and dismisses the dialog*/ deleteBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) diff --git a/app/src/main/java/com/vob/scanit/ui/CameraSurfaceView.java b/app/src/main/java/com/vob/scanit/ui/CameraSurfaceView.java index 7509bfd..1a21dcc 100644 --- a/app/src/main/java/com/vob/scanit/ui/CameraSurfaceView.java +++ b/app/src/main/java/com/vob/scanit/ui/CameraSurfaceView.java @@ -9,6 +9,7 @@ import android.view.SurfaceView; import java.io.IOException; +/* The following class sets the surface view when the camera feature is requested by the application */ public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder surfaceHolder; @@ -16,6 +17,7 @@ public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Call private Camera camera; private int cameraType; + /*CameraSurfaceView() constructor to initialise class variables*/ public CameraSurfaceView(Context context, Camera camera, int cameraType) { super(context); this.context = context; @@ -27,6 +29,7 @@ public CameraSurfaceView(Context context, Camera camera, int cameraType) { } + /*Allows the user to have the device placed in both, portrait and landscape modes*/ @Override public void surfaceCreated(SurfaceHolder holder) { try { @@ -39,6 +42,7 @@ public void surfaceCreated(SurfaceHolder holder) { } } + /*Account for the changes in camera setting such as zooming in, modifying exposure levels, etc.*/ @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { @@ -63,10 +67,14 @@ public void surfaceChanged(SurfaceHolder holder, int format, int width, int heig } + /* The following function releases the camera when the existing preview surface gets destroyed */ @Override public void surfaceDestroyed(SurfaceHolder holder) { camera.release(); } + + /*setCameraDisplayOrientation() function allows the preview to be changed without having any effects + * on how the image gets recorded*/ public static void setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera) { Camera.CameraInfo info = diff --git a/app/src/main/java/com/vob/scanit/ui/CustomCameraPreview.kt b/app/src/main/java/com/vob/scanit/ui/CustomCameraPreview.kt index bf1f326..00440be 100644 --- a/app/src/main/java/com/vob/scanit/ui/CustomCameraPreview.kt +++ b/app/src/main/java/com/vob/scanit/ui/CustomCameraPreview.kt @@ -17,7 +17,7 @@ import androidx.appcompat.app.AppCompatActivity import com.vob.scanit.R import kotlinx.android.synthetic.main.custom_camera_preview.* - +/*CustomCameraPreview class opens the back camera and sets the camera preview surface*/ class CustomCameraPreview : AppCompatActivity() { private val TAG = "CustomCameraPreview" @@ -86,6 +86,7 @@ class CustomCameraPreview : AppCompatActivity() { } }*/ + /*When the capture button gets clicked, the image is captured*/ take_picture.setOnClickListener { onClickOrientation = mOrientation try { @@ -95,12 +96,14 @@ class CustomCameraPreview : AppCompatActivity() { } } + /*When user clicks on the close button, the preview is taken down*/ close_camera_preview.setOnClickListener { setResult(RESULT_CANCELED,Intent()) finish() } } + /*The saveBitmap() function compresses the image to a standard size*/ private fun saveBitmap(bitmap: Bitmap) : File{ return try { val tempPath = cacheDir.absolutePath+"/TempImage.jpeg" @@ -117,6 +120,7 @@ class CustomCameraPreview : AppCompatActivity() { } } + /*returns the image clicked, to the activity that called the camera*/ private val pictureCallback = Camera.PictureCallback { data, camera -> try { @@ -163,6 +167,7 @@ class CustomCameraPreview : AppCompatActivity() { } } + /*The rotate() function rotates the image by 90 degrees each time it is called */ private fun rotate(bitmap: Bitmap, degrees: Int): Bitmap { return try { val matrix = Matrix() @@ -177,6 +182,7 @@ class CustomCameraPreview : AppCompatActivity() { } } + /*Camera is released when activity gets paused, and later started again when we resume */ override fun onPause() { super.onPause() mCamera?.release() diff --git a/app/src/main/java/com/vob/scanit/ui/activities/AboutAppActivity.kt b/app/src/main/java/com/vob/scanit/ui/activities/AboutAppActivity.kt index 768c553..0e48faa 100644 --- a/app/src/main/java/com/vob/scanit/ui/activities/AboutAppActivity.kt +++ b/app/src/main/java/com/vob/scanit/ui/activities/AboutAppActivity.kt @@ -6,7 +6,7 @@ import androidx.appcompat.app.AppCompatActivity import com.vob.scanit.R - +/*Inflates the layout that contains details about the app, such as version, theme, etc.*/ class AboutAppActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/com/vob/scanit/ui/activities/DisplayPDFActivity.kt b/app/src/main/java/com/vob/scanit/ui/activities/DisplayPDFActivity.kt index 9403268..7773d12 100644 --- a/app/src/main/java/com/vob/scanit/ui/activities/DisplayPDFActivity.kt +++ b/app/src/main/java/com/vob/scanit/ui/activities/DisplayPDFActivity.kt @@ -11,7 +11,7 @@ import com.github.barteksc.pdfviewer.scroll.DefaultScrollHandle import com.vob.scanit.R import java.io.File - +/*DisplayPDFActivity class has methods that display the contents of each PDF file and provide further functionality*/ class DisplayPDFActivity : AppCompatActivity(), OnPageChangeListener, OnLoadCompleteListener { lateinit var pdfView: PDFView @@ -20,6 +20,7 @@ class DisplayPDFActivity : AppCompatActivity(), OnPageChangeListener, OnLoadComp var position: Int = -1 //lateinit var file: File + /*The following function calls the displayPDF() and passes it the filepath*/ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_display_pdf) @@ -37,6 +38,7 @@ class DisplayPDFActivity : AppCompatActivity(), OnPageChangeListener, OnLoadComp } + /*setupToolbar() sets up and displays the toolbar*/ private fun setupToolbar() { var toolbar = findViewById(R.id.pdf_view_toolbar) toolbar.setTitle(fileName) @@ -48,10 +50,12 @@ class DisplayPDFActivity : AppCompatActivity(), OnPageChangeListener, OnLoadComp supportActionBar?.setDisplayShowHomeEnabled(true); } + /*We initialise pdfView in the following function */ private fun initialiseFields() { pdfView = findViewById(R.id.pdf_viewer) } + /*displayPDF() displays the PDF file*/ private fun displayPDF(file: File) { pdfView.fromFile(file) .defaultPage(pageNumber) @@ -64,16 +68,19 @@ class DisplayPDFActivity : AppCompatActivity(), OnPageChangeListener, OnLoadComp .load() } + /*The following functions handles the activities that occur when a user swipes through the pages*/ override fun onPageChanged(page: Int, pageCount: Int) { val pageNum = page setTitle(String.format("%s %s / %s", fileName, page+1, pageCount)) } + /*When the document gets loaded, the bookmarks get displayed with a call to printBookmarksTree()*/ override fun loadComplete(nbPages: Int) { val meta = pdfView.documentMeta printBookmarksTree(pdfView.tableOfContents,"-") } + /*printBookmarksTree fetches all the bookmarks made by the user*/ private fun printBookmarksTree(tableOfContents: List, s: String) { for (item: com.shockwave.pdfium.PdfDocument.Bookmark in tableOfContents) { if (item.hasChildren()) diff --git a/app/src/main/java/com/vob/scanit/ui/activities/GenerateQRActivity.kt b/app/src/main/java/com/vob/scanit/ui/activities/GenerateQRActivity.kt index 19c0f9a..b7cb3c3 100644 --- a/app/src/main/java/com/vob/scanit/ui/activities/GenerateQRActivity.kt +++ b/app/src/main/java/com/vob/scanit/ui/activities/GenerateQRActivity.kt @@ -23,6 +23,7 @@ import java.io.IOException import java.text.DateFormat import java.util.* +/*The following class defines methods to allow users to read and generate QR codes, */ class GenerateQRActivity : AppCompatActivity() { lateinit var url_et: EditText @@ -32,6 +33,8 @@ class GenerateQRActivity : AppCompatActivity() { lateinit var saveBtn: Button lateinit var file: File + /*onCreate() function sets up the toolbar, initialises all the fields and handles functionality related + * to the user clicking on the Generate QR button or the Share button*/ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_generate_q_r) @@ -94,6 +97,7 @@ class GenerateQRActivity : AppCompatActivity() { } + /*saveQR() saves the QR generated in a folder along with the current timestamp */ private fun saveQR(bitmap: Bitmap?) { if (bitmap != null) { @@ -124,6 +128,7 @@ class GenerateQRActivity : AppCompatActivity() { } } + /*The class variables are initialised to the necessary values*/ private fun initialiseFields() { url_et = findViewById(R.id.url_et) qr_iv = findViewById(R.id.qr_IV) @@ -132,6 +137,7 @@ class GenerateQRActivity : AppCompatActivity() { saveBtn = findViewById(R.id.save_qr_button) } + /*setupToolbar() sets up the toolbar*/ private fun setupToolbar() { var toolbar = findViewById(R.id.generate_qr_toolbar) toolbar.title = "Generate QR" diff --git a/app/src/main/java/com/vob/scanit/ui/activities/MainActivity.kt b/app/src/main/java/com/vob/scanit/ui/activities/MainActivity.kt index f077c3e..f4e1f6a 100644 --- a/app/src/main/java/com/vob/scanit/ui/activities/MainActivity.kt +++ b/app/src/main/java/com/vob/scanit/ui/activities/MainActivity.kt @@ -39,7 +39,8 @@ class MainActivity : AppCompatActivity() { var sharedPreferences: SharedPreferences? = null private val SHARED_PREF = "APP_SHARED_PREF" - + /*The following function sets the app theme, loads the main XML, calls the required fragments + and provides an entry point to the Firebase SDK*/ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -101,6 +102,7 @@ class MainActivity : AppCompatActivity() { .show() } + /*setupToolbar() sets up the main toolbar that gets displayed when the app is loaded*/ private fun setupToolbar() { val toolbar = findViewById(R.id.main_toolbar) //toolbar.setTitle("ScanIt") @@ -131,6 +133,7 @@ class MainActivity : AppCompatActivity() { return super.onCreateOptionsMenu(menu) } + /* loadFragment() maintains a record of the changes in the fragment in a stack*/ private fun loadFragment(fragment: Fragment) { val transaction = supportFragmentManager.beginTransaction() transaction.replace(R.id.container, fragment) diff --git a/app/src/main/java/com/vob/scanit/ui/activities/QRBarcodeScanResultActivity.kt b/app/src/main/java/com/vob/scanit/ui/activities/QRBarcodeScanResultActivity.kt index 3f923c0..778c864 100644 --- a/app/src/main/java/com/vob/scanit/ui/activities/QRBarcodeScanResultActivity.kt +++ b/app/src/main/java/com/vob/scanit/ui/activities/QRBarcodeScanResultActivity.kt @@ -12,6 +12,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar import com.vob.scanit.R +/*QRBarcodeScanResultActivity class provides options to a user to process the data generated from the QR */ class QRBarcodeScanResultActivity : AppCompatActivity() { lateinit var scanData: String @@ -19,6 +20,7 @@ class QRBarcodeScanResultActivity : AppCompatActivity() { lateinit var shareBtn: Button lateinit var scanResultTV: TextView + /*onCreate() handles button clicks, where the user can select to share the data obtained or open it in a browser*/ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_q_r_barcode_scan_result) @@ -35,12 +37,14 @@ class QRBarcodeScanResultActivity : AppCompatActivity() { shareBtn.setOnClickListener { share() } } + /*The class variables are initialised*/ private fun initialiseFields() { openInBrowserBtn = findViewById(R.id.openInBrowser_btn) scanResultTV = findViewById(R.id.scanResult_tv) shareBtn = findViewById(R.id.share_btn) } + /*When the user chooses to open the results of the scan in the browser, the following function is called*/ private fun openInBrowser() { val isUrl: Boolean = URLUtil.isValidUrl(scanData) if (isUrl) @@ -55,6 +59,8 @@ class QRBarcodeScanResultActivity : AppCompatActivity() { } } + /*When the user chooses to share the QR data, the share() function opens an app chooser to allow the + user to choose from the options available*/ private fun share() { val sendIntent: Intent = Intent().apply { action = Intent.ACTION_SEND @@ -66,6 +72,8 @@ class QRBarcodeScanResultActivity : AppCompatActivity() { startActivity(shareIntent) } + /*When the user selects the option to open the QR data in a browser, and the data generated is not an + * URL, we display appropriate messages*/ private fun showAlertDialog() { val alert: android.app.AlertDialog.Builder = android.app.AlertDialog.Builder(this) val mView: View = layoutInflater.inflate(R.layout.filename_dialog, null) @@ -94,6 +102,7 @@ class QRBarcodeScanResultActivity : AppCompatActivity() { alertDialog?.show() } + /*setupToolbar() sets up the toolbar*/ private fun setupToolbar() { var toolbar = findViewById(R.id.showdata_toolbar) toolbar.title = "Scan Result" diff --git a/app/src/main/java/com/vob/scanit/ui/activities/ScanActivity.kt b/app/src/main/java/com/vob/scanit/ui/activities/ScanActivity.kt index d6ba5d3..7491721 100644 --- a/app/src/main/java/com/vob/scanit/ui/activities/ScanActivity.kt +++ b/app/src/main/java/com/vob/scanit/ui/activities/ScanActivity.kt @@ -21,6 +21,8 @@ import com.vob.scanit.ui.CustomCameraPreview import kotlinx.android.synthetic.main.activity_scan.* import java.io.File +/* ScanActivity class defines methods to display text from the scanned image and +* other functionality to process the images taken by the camera in the application */ class ScanActivity: AppCompatActivity() { private val TAG = "ScanIt" @@ -111,7 +113,7 @@ class ScanActivity: AppCompatActivity() { private fun readBytes(context: Context, uri: Uri): ByteArray? = context.contentResolver.openInputStream(uri)?.buffered()?.use { it.readBytes() } - + /*The following function processes the image to detect the text*/ private fun detectText(scannedImage: Bitmap?) { var firebaseVisionImage: FirebaseVisionImage = FirebaseVisionImage.fromBitmap(scannedImage!!) @@ -126,6 +128,8 @@ class ScanActivity: AppCompatActivity() { } } + /*displayTextFromImage() displays the text obtained from an image or an appropriate message when it + * cannot decipher the text in the image*/ private fun displayTextFromImage(firebaseVisionText: FirebaseVisionText) { //textView.text = "" var blockList: List = firebaseVisionText.textBlocks diff --git a/app/src/main/java/com/vob/scanit/ui/activities/SettingsActivity.kt b/app/src/main/java/com/vob/scanit/ui/activities/SettingsActivity.kt index 7e08217..6c45a9f 100644 --- a/app/src/main/java/com/vob/scanit/ui/activities/SettingsActivity.kt +++ b/app/src/main/java/com/vob/scanit/ui/activities/SettingsActivity.kt @@ -5,6 +5,7 @@ import androidx.appcompat.app.AppCompatActivity import com.vob.scanit.R import com.vob.scanit.ui.fragments.SettingsFragment +/*SettingsActivity class calls the SettingsFragment() to display the list of options available to the user*/ class SettingsActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/com/vob/scanit/ui/activities/ShowQRData.kt b/app/src/main/java/com/vob/scanit/ui/activities/ShowQRData.kt index dbd21de..05a63c9 100644 --- a/app/src/main/java/com/vob/scanit/ui/activities/ShowQRData.kt +++ b/app/src/main/java/com/vob/scanit/ui/activities/ShowQRData.kt @@ -5,6 +5,7 @@ import android.os.Bundle import android.widget.TextView import com.vob.scanit.R +/*The following class processes the data obtained from the QR*/ class ShowQRData : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -14,7 +15,6 @@ class ShowQRData : AppCompatActivity() { val tv = findViewById(R.id.tv) if (data != null) { - tv.text = data } else diff --git a/app/src/main/java/com/vob/scanit/ui/activities/SplashScreenActivity.kt b/app/src/main/java/com/vob/scanit/ui/activities/SplashScreenActivity.kt index 122e0f9..e52ebca 100644 --- a/app/src/main/java/com/vob/scanit/ui/activities/SplashScreenActivity.kt +++ b/app/src/main/java/com/vob/scanit/ui/activities/SplashScreenActivity.kt @@ -7,6 +7,7 @@ import android.os.Handler import com.rbddevs.splashy.Splashy import com.vob.scanit.R +/*SplashScreenActivity class provides animations and other customisations when the app logo is loaded*/ class SplashScreenActivity : AppCompatActivity() { lateinit var handler: Handler diff --git a/app/src/main/java/com/vob/scanit/ui/fragments/DocumentFragment.kt b/app/src/main/java/com/vob/scanit/ui/fragments/DocumentFragment.kt index cc8134b..2e9fddd 100644 --- a/app/src/main/java/com/vob/scanit/ui/fragments/DocumentFragment.kt +++ b/app/src/main/java/com/vob/scanit/ui/fragments/DocumentFragment.kt @@ -17,7 +17,8 @@ import com.vob.scanit.viewmodel.DocumentFragmentViewModel import com.vob.scanit.viewmodel.DocumentViewModelFactory import java.io.File - +/*DocumentFragment is a Fragment class and represents a reusable portion of the app's UI. We override +* the methods of the Fragment class */ class DocumentFragment : Fragment() { private lateinit var binding: FragmentDocumentBinding @@ -27,12 +28,14 @@ class DocumentFragment : Fragment() { documentListAdapter.updateDocumentList(list) } + /*onCreateView() is used to inflate the layout*/ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_document, container, false) } + /*onViewCreated() ensures the view is fully created, and is called immediately after onCreateView()*/ override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding = FragmentDocumentBinding.bind(view) diff --git a/app/src/main/java/com/vob/scanit/ui/fragments/HomeFragment.kt b/app/src/main/java/com/vob/scanit/ui/fragments/HomeFragment.kt index 6badf1a..2843134 100644 --- a/app/src/main/java/com/vob/scanit/ui/fragments/HomeFragment.kt +++ b/app/src/main/java/com/vob/scanit/ui/fragments/HomeFragment.kt @@ -47,7 +47,8 @@ import java.io.InputStream import java.util.* import kotlin.collections.ArrayList - +/*HomeFragment class handles opening the camera, checks for storage permissions, updates the list of +* documents, saves PDF files and begins scanning*/ class HomeFragment : Fragment(),PdfAdapterRv.PdfAdapterInterface { lateinit var dimView: View @@ -72,6 +73,7 @@ class HomeFragment : Fragment(),PdfAdapterRv.PdfAdapterInterface { initialiseFields(view) } + /*onCreateView() inflates the layout and called the methods along with handling button clicks*/ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val view = inflater.inflate(R.layout.fragment_home, container, false) diff --git a/app/src/main/java/com/vob/scanit/ui/fragments/OCRFragment.kt b/app/src/main/java/com/vob/scanit/ui/fragments/OCRFragment.kt index 5a06cc8..80b5933 100644 --- a/app/src/main/java/com/vob/scanit/ui/fragments/OCRFragment.kt +++ b/app/src/main/java/com/vob/scanit/ui/fragments/OCRFragment.kt @@ -40,6 +40,7 @@ import java.io.File import java.io.InputStream import java.util.* +/*OCRFragment handles all the functions related to optical character recognition*/ class OCRFragment : Fragment() { companion object{ diff --git a/app/src/main/java/com/vob/scanit/ui/fragments/QRFragment.kt b/app/src/main/java/com/vob/scanit/ui/fragments/QRFragment.kt index 8667409..7a05390 100644 --- a/app/src/main/java/com/vob/scanit/ui/fragments/QRFragment.kt +++ b/app/src/main/java/com/vob/scanit/ui/fragments/QRFragment.kt @@ -22,7 +22,8 @@ import com.vob.scanit.ui.activities.QRBarcodeScanResultActivity //import com.vob.scanit.R import com.vob.scanit.ui.activities.ShowQRData - +/*QRFragment class overrides methods that handle inflating the layout, creating the views, releasing +* camera when not in use and starts the preview surface for the camera */ class QRFragment : Fragment() { //private val REQUEST_CODE_QR_SCAN = 101 diff --git a/app/src/main/java/com/vob/scanit/ui/fragments/SettingsFragment.kt b/app/src/main/java/com/vob/scanit/ui/fragments/SettingsFragment.kt index b06a32c..f9ab3c2 100644 --- a/app/src/main/java/com/vob/scanit/ui/fragments/SettingsFragment.kt +++ b/app/src/main/java/com/vob/scanit/ui/fragments/SettingsFragment.kt @@ -16,11 +16,13 @@ import androidx.preference.SwitchPreferenceCompat import com.vob.scanit.R import com.vob.scanit.currentSystemTheme +/*We declare the class SettingsFragment that extends PreferenceFragmentCompat, which allows access to the Preference Library.*/ class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener { var sharedPreferences: SharedPreferences? = null private val SHARED_PREF = "APP_SHARED_PREF" + /*onCreatePreferences() is called during onCreate(Bundle) and supplies the preferences to the fragment*/ override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.root_preferences, rootKey) @@ -42,6 +44,8 @@ class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceClic } } + /*onPreferenceClick() gets called when a preference has been clicked, and the preference that was + * clicked is passed as an argument*/ override fun onPreferenceClick(preference: Preference?): Boolean { if (preference != null) { @@ -59,6 +63,8 @@ class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceClic return true } + /*The following method is called when a Preference gets changed by the user. The arguments passed + * in are the changed preference and the new value of the preference*/ override fun onPreferenceChange(preference: Preference?, newValue: Any?): Boolean { if (preference is SwitchPreferenceCompat) { if (preference.key == "theme_toggle") { diff --git a/app/src/main/java/com/vob/scanit/viewmodel/DocumentFragmentViewModel.kt b/app/src/main/java/com/vob/scanit/viewmodel/DocumentFragmentViewModel.kt index c0d8dcf..cf8a03e 100644 --- a/app/src/main/java/com/vob/scanit/viewmodel/DocumentFragmentViewModel.kt +++ b/app/src/main/java/com/vob/scanit/viewmodel/DocumentFragmentViewModel.kt @@ -15,11 +15,14 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File +/* DocumentFragmentViewModel is an instance of the ViewModel class that is designed to +* store data in a lifecycle aware manner (updates UI on rotation of the screen) */ class DocumentFragmentViewModel(): ViewModel() { val documents = MutableLiveData>() private var contentObserver: ContentObserver? = null + /*loadDocument() function displays the list of documents and survives configuration changes*/ fun loadDocuments() { viewModelScope.launch { val dir = File(Environment.DIRECTORY_DOCUMENTS + File.separator + "ScanIt") @@ -28,6 +31,8 @@ class DocumentFragmentViewModel(): ViewModel() { } } + /* The following suspend function obtains all the files in the given directory and returns a list + * that contains all the PDF files from the directory.*/ suspend fun getFiles(dir: File): ArrayList { var listFiles = dir.listFiles() var fileList: ArrayList = ArrayList() diff --git a/app/src/main/java/com/vob/scanit/viewmodel/DocumentViewModelFactory.kt b/app/src/main/java/com/vob/scanit/viewmodel/DocumentViewModelFactory.kt index f56805e..f56ae4d 100644 --- a/app/src/main/java/com/vob/scanit/viewmodel/DocumentViewModelFactory.kt +++ b/app/src/main/java/com/vob/scanit/viewmodel/DocumentViewModelFactory.kt @@ -5,6 +5,7 @@ import android.content.Context import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +/*DocumentViewModelFactory is an utility class that provides ViewModels for a scope*/ class DocumentViewModelFactory(): ViewModelProvider.Factory { override fun create(modelClass: Class): T { return DocumentFragmentViewModel() as T diff --git a/build.gradle b/build.gradle index c6fd8b8..d71ca27 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,6 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. +ext { + compileSdkVersion = 29 +}// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { ext.kotlin_version = '1.4.10' @@ -8,7 +10,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.1.2' + classpath 'com.android.tools.build:gradle:4.1.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.google.gms:google-services:4.0.0' // NOTE: Do not place your application dependencies here; they belong diff --git a/monscanner/build.gradle b/monscanner/build.gradle index e34473a..269d172 100644 --- a/monscanner/build.gradle +++ b/monscanner/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'com.android.library' android { //noinspection GradleCompatible compileSdkVersion 28 - buildToolsVersion "29.0.3" + buildToolsVersion '28' defaultConfig { minSdkVersion 21 diff --git a/opencv/build.gradle b/opencv/build.gradle index 13305b0..a86e074 100644 --- a/opencv/build.gradle +++ b/opencv/build.gradle @@ -29,6 +29,7 @@ android { manifest.srcFile 'AndroidManifest.xml' } } + buildToolsVersion '26' } dependencies {