Monday, May 16, 2022

Android Security - Securing Android User Data with Kotlin

 Storing user data is a key consideration for every Android app, and there a ton of different approaches to take. 

 Android Security: Protecting User Data Storage, you’ll learn to safely store your user’s data. First,  you’ll explore the different storage methods, their use cases, and security implications. 

Next, you’ll discover storing data using Android’s new Scoped Storage API. Finally, you’ll learn how to exchange files with other apps. When you’re finished with this topic , you’ll have the skills and knowledge of Android development using Kotlin needed to safely manage your user’s data. 

Topics that you will find in this  Heavy Android Demo Driven Code because I believe working demo code can give better reference.

  • Understanding Android Storage Options
  • Understanding Android Encryption Options
  • Securely Storing User Data
  • Working with Unstructured User Data
  • Securely Storing User Files
  • Securely Sharing Files with Other Apps
  • Leveraging File Providers
  • Retrieving Files in Scoped Storage
  • Retrieving Files with Storage Access Framework
  • Saving and Displaying Copied Files

We've covered quite a bit of information in a very short amount of time, so let's quickly review. User storage is an important part of a successful app, and there are a ton of options, so it's important to understand what makes sense for your particular use case. To help with that, I introduced the storage decision framework to help you determine which option is best suited for your needs. The first storage method that we examined was user data. The two forms of this are structured, such a SQLite or Room, and unstructured, such as shared preferences. 

Next, we tackled how to store user files and all of the different options that are available. We also looked at the impact of the new scoped storage approach unveiled by Google. We wrapped up the course by sharing files we created to other apps, as well as retrieving files from other apps and pulling them into our own. I hope that you found the content valuable and that you're confident in your ability to leverage user storage in your future work. If you have any questions or comments, please reach out in the course discussion below. Thanks again, and be on the lookout for other Android topic that I'll be publishing in the future.

Git Hub Account Link :
https://github.com/Abhinaw/Android-Security-User-Data/tree/master

Note: Download the code and try to integrate the concept and approach in your app. This is the best way to implement the Android Security in your local storage and User Data in local storage. So that your app can not be vulnerable with respect to Android Security Testing.


Sunday, May 15, 2022

Unit Testing with JUnit 5 and Kotlin

 Unit Testing with JUnit 5 and Kotlin JUnit 5 is the de-facto standard testing framework on the JVM. 

It is used to test application code in many areas including enterprise, desktop, and mobile applications. Unit Testing with JUnit 5 and Kotlin set up JUnit to test Kotlin code, including some of the issues you will encounter that are unique to Kotlin. First, you will see how to set up your environment to use JUnit 5 for Kotlin including setting up Gradle and Maven environments and using an IDE to run the tests. you will be introduced to Kluent, a Kotlin fluent assertions library. Then, you will see how to change assertions using this fluent syntax, as well as new, cleaner ways of writing assertions using the Kluent APIs. Finally, we will explore ‘mocking’ using MockK, a mocking framework written in and for Kotlin. When you are finished with this course, you will have the skills to test Kotlin code using JUnit and how to refactor code to make it testable.



Git Hub Account:
https://github.com/Abhinaw/UnitTest5/blob/master/README.md

You can check the working code and able to understand everything about JUnit 5 and how it works with Kotlin.


Saturday, May 14, 2022

Sample Microservices for Mobile App in Kotlin , Spring-Boot and MySQL Db.

 Sample Microservices for Mobile App in Kotlin , Spring-Boot and MySQL Db.

Complete code is in Kotlin and it is very concise and fast.
Tutorials for beginners with working code.
Easy to understand code.
Code is hosted on my GitHub
#kotlin #springboot #MVC

https://github.com/Abhinaw/resumeApi/tree/master


Sunday, January 30, 2022

What are the things to be done for the design of object oriented system?How the objects are identified?

 Steps to Analyze and Design Object-Oriented System

Object-Oriented Analysis (OOA) :

Object-Oriented Analysis (OOA) is the first technical activity performed as part of object-oriented software engineering. OOA introduces new concepts to investigate a problem.

Object-Oriented Design (OOD) :

An analysis model created using object-oriented analysis is transformed by object-oriented design into a design model that works as a plan for software creation. OOD results in a design having several different levels of modularity i.e., The major system components are partitioned into subsystems (a system-level “modular”), and data manipulation operations are encapsulated into objects (a modular form that is the building block of an OO system.).



There are various steps/stages in the analysis and design of an object-oriented system as given in below figure :

Create a Use case model : 

The first step in the analysis and design of an object-oriented system is to recognize the actors interlinked with the system. After that, create the use case and draw the use case diagram.

 Draw activity diagram (If required) : 

The activity diagram demonstrates the dynamic nature of a system by creating the flow of control from activity. An activity addresses a procedure on some class in the framework that outcomes in an adjustment of the condition of the system. The below figure shows the activity graph handling a request to convey a few products.

Draw the interaction diagram : 

An interaction diagram shows a collaboration, comprising a bunch of articles and their relationship, including the messages that might be dispatched among them. Interaction diagrams address the unique perspective of a system.

Steps for drawing interaction diagrams :

Initially, we ought to distinguish the objects for each use case.

Then we draw the sequence diagrams for each use case.

Then we draw the collaboration diagrams for each use case.

 Draw the class diagram: The class diagram is responsible for showing the relationship between the classes. There are four types of relationships available in class diagrams :

Association –

It is a semantic connection between classes. At the point when an association associates two classes, each class can send messages to the next in sequence or a collaboration diagram. They may be bi-directional or unidirectional in nature.

Dependencies –

They connect two classes and are always unidirectional in nature and display that one class, depending on the definitions of another class.

Aggregations –

They are a stronger form of association that shows the relationship between a whole and its parts.

Generalizations –

They are used to display an inheritance relationship between the two classes.

Design of Statechart diagrams : 

A statechart is utilized to show the state space of a given class, the occasion that influences progress starting with one state then onto the next, and the activity that outcome from a state change. A state change graph for a “book” in the library management system is shown below :


6. Draw component and development diagram : 

These diagrams address the static execution perspective on a system they are identified with class diagrams in that a segment ordinarily guides to at least one class, interface, or coordinated effort.

Thanks.


Mathematics , Recursion , Searching , Sorting , String and Arrays problem solutions

Problem-solving series for competitive programming. Sharing a GitHub link where you will get multiple conceptual problem solutions both efficient and non-efficient. those are basic formulas for the above-mentioned topics to solve any complex problem based on the above topics.

Git Hub URL:

https://github.com/Abhinaw/ProblemsOFProgrammingTest/tree/master/src/programming

Thursday, October 14, 2021

What's advanced algorithm?

 Emphasis is placed on fundamental algorithms and advanced methods of algorithmic design, analysis, and implementation. Techniques to be covered include amortization, randomization, fingerprinting, word-level parallelism, bit scaling, dynamic programming, network flow, linear programming, fixed-parameter algorithms, and approximation algorithms. Domains include string algorithms, network optimization, parallel algorithms, computational geometry, online algorithms, external memory, cache, and streaming algorithms, and data structures.

 Sorry, it took so long for me to get this one out! Advanced Algorithms are very complex if you are not aware of the fundamentals of DS-ALGO, The more advanced material takes quite a bit longer to produce.

While it’s not completely necessary to take Big-O Data Structures and Big-O Algorithms first, I would recommend it, even if you’ve learned this stuff before. It doesn’t cost any extra, and the refresher will really help. I won’t rehash all the Big-O complexity stuff here, because I’m assuming you’re already familiar with it. we will focus on implementing some of the more advanced algorithms that you would learn in a CS undergraduate degree and learn how you can recognize when algorithms of this sort will help you in your future career.

What’s included?

There are four modules.

Module 1 – Graph Theory

In this module, we have a brief refresher on graph data structures and implement some basic traversal algorithms like breadth and depth-first search. We also cover different types of graphs, like complete and directed graphs, and how they can be represented in code.

Module 2 – Advanced Searches

In this module, we really round out our experience with graphs. We learn about greedy algorithms, and how they can help us write faster code. We also implement a priority queue so that we can use it as we do a deep dive on Dijkstra’s algorithm. Finally, we finished the module by writing an A* search that can find its way quickly through a muddy map – similar to what you’d need to write as a game developer.

Module 3 – Dynamic Programming

In this module, we shift gears and learn about how memoization and tabulation techniques can be used to optimize various algorithms by trading memory for speed. We re-write the classic Fibonacci function using dynamic programming, as well as the super useful edit-distance algorithm. Edit distance is used in the real world to calculate the similarity in spellings between words, just like how spell-checkers work.

Module 4 – Linear Programming

In the final module, we shift the gears yet again to focus more on the mathematical side of things. Linear programming is a technique used to solve linear systems of equations, specifically optimization problems. We build from scratch a Simplex solver in any programming language that you know and use it to calculate the exact number of cookies and cakes a baker should produce in order to maximize the profit in her shop.

This is all about advanced algorithms.

Sunday, June 27, 2021

Behavioral Design Pattern - Interpreter Pattern Java

Behavioral Interpreter Design Pattern 

we're going to look at the interpreter design pattern. The interpreter pattern is a behavior pattern that you used to represent the grammar of a language. A lot of tools use this pattern when parsing various aspects of grammar. 

Let's look at some of the concepts considered when choosing this pattern.

 the concept surrounding why you would choose the interpreter pattern or that it represents grammar. This could be music notation or mathematical equations, or even another language. Compilers will use the interpreter pattern too often. 

 This goes hand in hand with representing the grammar, but we can then use it to interpret a sentence. This enables us to map out a domain-specific language. If you've ever used SQL or an XML parser, this is the exact thing that is. 

This pattern was designed to do define a language that can be interpreted to do things you'll often see an interpreter used when defining an abstract syntax tree. To examples of this in the Java API. The Java Util pattern, the pattern classes used to represent a compiled regular expression, is an incredibly powerful way to search through strings. Another representation is the java class format is an abstract-based class that is used to represent locale-sensitive content such as dates, numbers, and strings. Let's look at some of the design considerations when choosing this pattern.

 


 the design of the interpreter is quite a bit different than most of the other patterns that we've looked at. There is an abstract-based class or an abstract expression that declares an interface for executing an operation. That operation is an interpreted method. Expressions are then broken into terminal expressions, which represent a leaf of a tree or an expression that does not contain other expressions. If it does contain other expressions then it's a nonterminal expression. Nonterminal expressions represent compound expressions and continue. So we called itself a recursive tree until it finally represents a terminal expression or multiple subexpressions. 

The pieces of the UML diagram are the context, abstract expression, terminal expression, non-terminal expression, and a client.

 Example: Pattern

the pattern class used in conjunction with regular expressions is a good example of the interpreter pattern being used in the Java API. We created sentences and establish grammar for that sentence. From there, we're going to interpret the sentence and display what we parsed using the pattern. Let's look at this in life code now.

Code :

package interpreterpattern;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class InterpreterJavaAPIDemo {

public static void main(String[] args) {
String input = "Lions , and tigers , and bears! oh , my";
Pattern p = Pattern.compile("(Lions , and tigers , and bears! oh , my)");
Matcher m = p.matcher(input);
while (m.find()) {
System.out.println("Found a " + m.group() + ".");
}
}
}

Output :
Lions Bears is true

Demo Structure for real-time project implementation:

package interpreterpattern;

public class InterpreterDemo {

static Expression buildInterpreterTree() {

Expression terminal1 = new TerminalExpression("Lions");
Expression terminal2 = new TerminalExpression("Tigers");
Expression terminal3 = new TerminalExpression("Bears");

Expression alternation1 = new AndExpression(terminal2, terminal3);
Expression alternation2 = new OrExpression(terminal1, alternation1);

return new AndExpression(terminal3, alternation2);
}

public static void main(String[] args) {
// String context = "Lions";
// String context = "Tigers";
// String context = "Tigers";
//String context = "Lions Tigers";
String context = "Lions Bears";
Expression define = buildInterpreterTree();
System.out.println(context + " is " + define.interpret(context));
}
}
package interpreterpattern;

public interface Expression {

boolean interpret(String context);
}
package interpreterpattern;

public class OrExpression implements Expression {
private Expression expr1 = null;
private Expression expr2 = null;
public OrExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
@Override
public boolean interpret(String context) {
return expr1.interpret(context) || expr2.interpret(context);
}
}
package interpreterpattern;

import java.util.StringTokenizer;

public class TerminalExpression implements Expression {

private String data;

public TerminalExpression(String data) {
this.data = data;
}

@Override
public boolean interpret(String str) {
StringTokenizer st = new StringTokenizer(str);
while (st.hasMoreTokens()) {
String test = st.nextToken();
if (test.equals(data)) {
return true;
}
}
return false;
}
}
package interpreterpattern;

public class AndExpression implements Expression {

private Expression expr1 = null;
private Expression expr2 = null;

public AndExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}

@Override
public boolean interpret(String context) {
return expr1.interpret(context) && expr2.interpret(context);
}
}

Output :

Lions Bears is true

Pitfalls

Now that we've created our own interpreter, let's look at some of the pitfalls of it. If the grammar becomes very complex, it can be difficult to maintain, as you noticed in our rule example that we had you could see very quickly that if I started adding these different answers or combinations, it could become a little bit interesting to try and debug and walkthrough. So complexity can be an issue there. There is at least one class per rule, so every time we create one of our new expressions were creating another class. Complex rules will require multiple classes to define them. That's where the difficulty of maintenance can come into play. The use of other patterns might help with your specific implementation of a complex interpreter, and adding a new variant requires us to change every variant of that class. The interpreter is a little unique compared to some of the other patterns that we have looked at because it is fairly specific to the problem that we're trying to solve to better understand when we should use this or a different pattern. Let's contrast it with the visitor pattern.

Contrast to Other Patterns

To contrast the interpreter pattern. Let's compare it with the visitor. The interpreter and the visitor are very similar in structure, but a different focus on implementation. The interpreter has access to properties because it contains the object. Functions are defined as methods, and since we extend implement the base interface, each interpret function is contained within a method. One drawback is that adding new functionality changes every variant recall the demo that we coated together when we were building the expression tree and the complexity that we could get by calm compounding those expressions together, the visitor is actually very similar to the interpreter, with some slight variations. Instead of having access to the properties we need, we have to implement the observer observable functionality to gain access to those properties similar to the interpreter. Functionality is found in one place, but it is in the visitors and not in the expression objects that were building and just like the interpreter. Adding a new variant requires changing every visitor. The focus is more about whether you're adding more expressions or grammar rules or adding new visitors to interact with, and that is the main focus on choosing one over the other.

Thanks.

 

Sunday, June 20, 2021

Trapping Rain Water Problem

There is a very good question about Trapping Rain Water for arrays. Today I will give two solutions for this problem, Naive vs Efficient Solution. Let's understand the problem first.

Trapping Rain Water




So in the above example, you can only store a maximum of 6 units of water.

I/p= arr[] = {2,0,2}

o/p = 2 you can collect 2 Units of water in these bars. 

we are given an array of positive integers 

The elements are represented as Bars and the question is 

how much water you can store in this bar?

2nd Example :

arr[] = {3 , 0 , 1 , 2, 5 }

o/p = 6 

So now we are calculating that how much water we can

calculate suppose first is of height 3 units, 2nd bar

is of the height of 0 unit and so on ......

 if  you sum all the bars height collectively then 

 you will get the answer.

 Code ;

package dsalgo;

public class TrappingRainWaterProblem {
// for input = arr[] = {3,0,1,2,5}
public static void main(String[] args) {

int arr[] = {3, 0, 1, 2, 5}, n = 5;
System.out.println("Naive Solution:" + getWater(arr, n));
System.out.println("Efficient Solution : " +
getWaterEfficientSolution(arr, n)); // efficient Solution
}

/*****Naive Solution****/
public static int getWater(int arr[], int n) {
int res = 0;

for (int i = 1; i < n - 1; i++) {
int lMax = arr[i];

for (int j = 0; j < i; j++)
lMax = Math.max(lMax, arr[j]);

int rMax = arr[i];

for (int j = i + 1; j < n; j++)
rMax = Math.max(rMax, arr[j]);

res = res + (Math.min(lMax, rMax) - arr[i]);
}
System.out.println("Naive Time : " + System.nanoTime());
return res;
}

public static int getWaterEfficientSolution(int arr[], int n) {
int res = 0;

int lMax[] = new int[n];
int rMax[] = new int[n];

lMax[0] = arr[0];
for (int i = 1; i < n; i++)
lMax[i] = Math.max(arr[i], lMax[i - 1]);


rMax[n - 1] = arr[n - 1];
for (int i = n - 2; i >= 0; i--)
rMax[i] = Math.max(arr[i], rMax[i + 1]);

for (int i = 1; i < n - 1; i++)
res = res + (Math.min(lMax[i], rMax[i]) - arr[i]);

System.out.println("Efficient Time::" + System.nanoTime());
return res;
}

}

 

Output : 

Naive Time : 2745092805500

Naive Solution:6

Efficient Time::2745093880800

Efficient Solution : 6

Just increase the input array then you will see the visible difference in Naive vs. Efficient Solution.

I tried to solve it in a simplest way.