Gradle: Working with multi app projects in Android Studio

In this tutorial I wanted to share how is my project organized to work with multiple apps and libraries.




I have the following settings.gradle in the root of my Project:

include ':app'
include ':appBookShelf'
include ':appNFC'
include ':appUnitConverter'
include ':appUserPreferences'
include ':libraries:ListViewSwipeActivity'



Please note that I perpend my app names with "app.." to keep them organized, I also have a folder "libraries" where I keep the code of my submodules.

Here is my folder structure:


CIT299 $ t
.
├── CIT299.iml
├── app
│   ├── app.iml
│   ├── build
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src
├── appBookShelf
│   ├── build
│   ├── build.gradle
│   └── src
├── appNFC
│   ├── build
│   ├── build.gradle
│   └── src
├── appUnitConverter
│   ├── appUnitConverter.iml
│   ├── build
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src
├── appUserPreferences
│   ├── build.gradle
│   └── src
├── build.gradle
├── gradle
│   └── wrapper
├── gradle.properties
├── gradlew
├── gradlew.bat
├── libraries
│   └── ListViewSwipeActivity
├── local.properties
└── settings.gradle



As an Amazon Associate I earn from qualifying purchases.

Gradle: Working with multi app projects in Android Studio

In this tutorial I wanted to share how is my project organized to work with multiple apps and libraries.



As an Amazon Associate I earn from qualifying purchases.

Maven: updating version on Mac

In this tutorial we will discuss upgrading Maven on Mac OS X.



As an Amazon Associate I earn from qualifying purchases.

Maven: updating version on Mac

In this tutorial we will discuss upgrading Maven on Mac OS X.




While trying building with Maven I was getting errors related to version number (below 3.1) 

mvn install
Error: Could not find or load main class org.codehaus.plexus.classworlds.launcher.Launcher

To update my maven I have to do the following sequence of steps.

$ mvn -version

Apache Maven 3.0.5 (r01de14724cdef164cd33c7c8c2fe155faf9602da; 2013-02-19 07:51:28-0600)


I had to uninstall the older version 3.0

$ brew uninstall maven30

Uninstalling /usr/local/Cellar/maven30/3.0.5...


Trying to install newest I noticed that I tried it before, but it was not linked

$ brew install maven

Warning: maven-3.2.3 already installed, it's just not linked


The easiest way to fix that is to uninstall and install again:

$ brew uninstall maven

Uninstalling /usr/local/Cellar/maven/3.2.3...
$ brew install maven

==> Downloading http://www.apache.org/dyn/closer.cgi?path=maven/maven-3/3.2.3/binaries/apache-maven-3.2.3-bin.tar.gzAlready downloaded: /Library/Caches/Homebrew/maven-3.2.3.tar.gz
🍺  /usr/local/Cellar/maven/3.2.3: 76 files, 8.0M, built in 3 seconds
uki@ CNH_PROD $ mvn -version
Apache Maven 3.2.3



As an Amazon Associate I earn from qualifying purchases.

Maven: installing Android SDK

In order to compile Android project using Maven you have to instal Android SDK to your Maven repository.


$ git clone https://github.com/mosabua/maven-android-sdk-deployer.git
Cloning into 'maven-android-sdk-deployer'...
remote: Counting objects: 3198, done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 3198 (delta 3), reused 6 (delta 3)
Receiving objects: 100% (3198/3198), 435.92 KiB | 0 bytes/s, done.
Resolving deltas: 100% (1585/1585), done.
Checking connectivity... done.

$ cd maven-android-sdk-deployer/


As an Amazon Associate I earn from qualifying purchases.

Maven: installing Android SDK

In order to compile Android project using Maven you have to instal Android SDK to your Maven repository.


$ git clone https://github.com/mosabua/maven-android-sdk-deployer.git
Cloning into 'maven-android-sdk-deployer'...
remote: Counting objects: 3198, done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 3198 (delta 3), reused 6 (delta 3)
Receiving objects: 100% (3198/3198), 435.92 KiB | 0 bytes/s, done.
Resolving deltas: 100% (1585/1585), done.
Checking connectivity... done.

$ cd maven-android-sdk-deployer/


As an Amazon Associate I earn from qualifying purchases.

Android NFC

In this tutorial we will create a simple NFC app as a new project from scratch.


As an Amazon Associate I earn from qualifying purchases.

Android NFC

In this tutorial we will create a simple NFC app as a new project from scratch.

Step: Create and new Project "NFC" (not Module)



Set minimum version to Eclair API v7



Select FragmentActivity (most common you will use)





Name the Activity "MainActivity"



inspect settings.gradle

include ':app'


inspect local.properties (specific to locatin of your Android SDK directory)

sdk.dir=/Users/uki/Documents/Dropbox/Android/android-sdk-macosx


inspect gradle.properties

- no configuration

inspect build.gradle

note that gradle plugin is newer that in project created last week

classpath 'com.android.tools.build:gradle:0.12.2'


inspect NFC/app/build.gradle

notice the newest versions of tools API 21 - Lollipop


apply plugin: 'com.android.application'
android {
    compileSdkVersion 21
    buildToolsVersion "21.0.2"
    defaultConfig {
        applicationId "com.chicagoandroid.nfc"
        minSdkVersion 7
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.0'
}

Step: run the app


everything should work without any changes.


Step: open NFC/app/src/main/AndroidManifest.xml


  • Add permission within <application> tag to allow use of NFC
  • Add feature if you want your app to be available only to phones with NFC


        <uses-permission android:name="android.permission.NFC" />
        <uses-feature
            android:name="android.hardware.nfc"
            android:required="true" />
    </application>


Alternatively to uses-feature you will be able to check if device supports NFC in runtime getDefaultAdapter() is null.

Step: change minSdkVersion

  • change to API 9 if you want basic NFC support
  • change to API 10 is you want full support
  • change to API 14 to take advantage of newest API and Android Beam (device-to-device)

Previously we would set AndroidManifest.xml 
        <uses-sdk android:minSdkVersion="14"/>
You can test run the app, even using version 21 and it will not have an effect.

Since we build with build.gradle we will change it there:

apply plugin: 'com.android.application'
android {
    compileSdkVersion 21
    buildToolsVersion "21.0.2"
    defaultConfig {
        applicationId "com.chicagoandroid.nfc"
        minSdkVersion 14
...

Step: add NFC intent filter

               <action android:name="android.nfc.action.NDEF_DISCOVERED" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="text/plain" />
            </intent-filter>

Run project and try to scan a tag.  The app does not pick it up.

Step: tech-list.xml resource

  • add new directory src/main/res/xml
  • add new file tech_list.xml


<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.IsoDep</tech>
        <tech>android.nfc.tech.NfcA</tech>
        <tech>android.nfc.tech.NfcB</tech>
        <tech>android.nfc.tech.NfcF</tech>
        <tech>android.nfc.tech.NfcV</tech>
        <tech>android.nfc.tech.Ndef</tech>
        <tech>android.nfc.tech.NdefFormatable</tech>
        <tech>android.nfc.tech.MifareClassic</tech>
        <tech>android.nfc.tech.MifareUltralight</tech>
    </tech-list>
</resources>


Run project and try to scan a tag. 





As an Amazon Associate I earn from qualifying purchases.

Android: reinstalling several APKs from single folder

In this tutorial we will install multiple APKs from your local computer to Android device using ADB connection.

echo "                    ██╗"
echo "██╗   ██╗ ██╗   ██╗ ╚═╝"
echo "██║   ██║ ██╚═██╗═╝ ██╗"
echo "██║   ██║ ████══╝   ██║"
echo "██║   ██║ ██║╚██╗   ██║"
echo "████████║ ██║  ╚██╗ ██║"
echo "╚═══════╝  ╚╝   ╚═╝ ╚═╝"
echo

# Install new APKs
for apk in $(ls *.apk)
do
    echo "Installing $apk"
    echo
    adb install -r "$apk"
done



As an Amazon Associate I earn from qualifying purchases.

Android: reinstalling several APKs from single folder

In this tutorial we will install multiple APKs from your local computer to Android device using ADB connection.

echo "                    ██╗"
echo "██╗   ██╗ ██╗   ██╗ ╚═╝"
echo "██║   ██║ ██╚═██╗═╝ ██╗"
echo "██║   ██║ ████══╝   ██║"
echo "██║   ██║ ██║╚██╗   ██║"
echo "████████║ ██║  ╚██╗ ██║"
echo "╚═══════╝  ╚╝   ╚═╝ ╚═╝"
echo

# Install new APKs
for apk in $(ls *.apk)
do
    echo "Installing $apk"
    echo
    adb install -r "$apk"
done



As an Amazon Associate I earn from qualifying purchases.

ChildrenTV story

ChildrenTV is a mobile app that provides an impressive collection of new and old classic cartoons that you can filter by language and age category.

“The original idea came to me while I was inspired by seeing my daughter search and watch her favorite YouTube cartoons.  So we decided to create ChildrenTV mobile app, a cute and useful application that makes the process of teaching foreign languages an interactive session for both parents and kids."- said Uki D. Lucas, ChildrenTV founder.


Over the past 3 years, his mobile development company CyberWalkAbout.com has worked to develop the ChildrenTV  application and has continuously updated its content. Praised for its successful combination of beautiful graphics and educational content, the title gained a huge popularity on the Android an iOS markets and received positive feedback. The app integrates with the existing web site YouTube and streams live hundreds of safe videos that can be easily filtered by language and age category.




With more than 1,000 videos and growing, the app provides a fun way to keep kids both occupied and educated during long car rides as well as babysit them at home.  Cute and colorful graphics, an array of entertaining cartoons in 10 languages, together with a kid-friendly interface make ChildrenTV a great addition to a children’s mobile library. Also, as a parent you can brush up on a foreign language skills using this app, too!
 
We have lot of users from different countries, speaking MANY LANGUAGES, since it is almost impossible to find favorite videos in so many languages we ask you to help us, your and other kids will be thankful. Please suggest videos that your kids like, and we will do our best to make them available in the Children TV apps  http://bit.ly/ChildrenTV_YouTube_form



As an Amazon Associate I earn from qualifying purchases.

Lever Action Rifle Calibers

Recently, I have been thinking about a new lever-action rifle. The appeal of these late 1800 models is that they are great, very light (5lbs) for backpacking and pack enough punch for anything you need in the woods/bush. Lever action rifles, comparing to heavy (~8.5lbs) bolt action calibers (.30-06, 7.62x54R) we normally shoot are far more maneuverable in the thicket and honestly safer with the heavy animals like a boar, elk or moose because of their  10+1 capacity and rapid fire ability.



I have been thinking about the caliber I would like to pick up, here are the options I considered. Please be aware that I reload my ammo and I am not planning to pay $2 per round of Buffalo Bore. Also, I don't like revolvers so there is no appeal for me of carrying a matching hand piece, I like my 1911 .45 ACP just fine for "personal" defense.


  • .38 Special / .357 Magnum - while it would be a great caliber for fun plinking and smaller game and home-defense I decided that I need to rule it out because it is definitely not a boar caliber, an important criterium for me.
  • .44-40 Winchester - this is the grandpa of all lever-action cartridges and while it is plenty powerful and honestly cool, it is not recommended as a boar load.
  • .44 Special / .44 Magnum - this combination is easy to buy (or reload) with many options available (305gr.@1,325fps/1,189ft-lbs.). The .44 Special is a great round for plinking and self defense, .44 magnum is designed for hunting and it is a good boar load (deer and everything else smaller).  I have a feeling that this combination is the best for lever action rifle
  • .45 Colt - honestly I wanted this one the most, especially that I already reload .45 ACP which share similar tooling. The .45 Colt while most of the time weak, can have very powerful +P options from DoubleTap (335 gr.,1605 fps, 1916 ft. lbs. in 16 inch barrel).
  • .454 Casull caliber that does all that .44 and .45 Colt can, but on average has much more power (360gr.@1,425fps/1,623ft-lbs.), the cartridge is still SHORT enough in length so you can carry many of them. What is most important you can shoot .45 Colt out of .454 Casull chambering rifle, all you have to do is clean the chamber after you do to wipe the carbon deposits before you use .454 round again. I would have to make some extra-light loads (250 gr. & TrailBoss@1,100fps) for it for plinking and I would have the LIGHT, MEDIUM and HEAVLY rifle in one package. This way I can shoot regular load .45 Colt for 80% of my needs and have .454 for boar hunting and for the Yukon/Alaska trip I dream about.
  • .45-70 Government - It is definitely plenty of gun (430gr.@1,925fps/3,537ft-lbs.) for ALL dangerous animals in the back country (boar, bear, moose, bison, mountain lion). The problem with this round is that it is HUGE and takes the valuable space in the magazine tube of the rifle
  • .30-30 - This is a great and proven lever action rifle cartridge, but similarly to .45-70 I feel that it is too long and takes too much space. 






Rifle Models I like in order of my preference:



  • .454 Casul R92 Carbine Lever Action Rifle, 16" Round Barrel, LOA 34", 4.8 lbs, 8+1 tubular magazine, $742.20, 0 available, #R92-68016
  • .454 Casull Rossi R92 Blue Lever Action Rifle, 20" Round Barrel, LOA 37.5", 10+1 tubular magazine, $665 - 0 available #R92-68001 
  • .45 Colt R92 Large Loop Lever Action Rifle, 4.8 lbs, 16" Round Barrel, Blue, LOA 34", Saddle Ring, 8+1 tubular magazine, $635.08, 7 available, #R92-57006
  • .45 Colt, 16" Round Barrel, 8+1 tubular magazine,  #R92-57008 $624 - 15 available
  • .45 Magnum R92 Carbine Lever Action Rifle, 16" Round Barrel, 8+1 tubular magazine, LOA 34", 4.8 lbs,,  $624 - 22 available l #R92-55008

~

Please VISIT the following websites:



































As an Amazon Associate I earn from qualifying purchases.

Groovy on Android

Android developers are already using Groovy in many places AROUND Android, for example in Gradle build scripts. Now the dream of using Groovy as primary language for Android is a little closer to realization! See what is cooking.


http://melix.github.io/blog/2014/06/grooid.html

also a good interview with Cédric Champeau, Senior Software Engineer working on Groovy for SpringSource/Pivotal here:

http://www.infoq.com/news/2014/06/groovy-android


As an Amazon Associate I earn from qualifying purchases.

Groovy on Android

Android developers are already using Groovy in many places AROUND Android, for example in Gradle build scripts. Now the dream of using Groovy as primary language for Android is a little closer to realization! See what is cooking.



As an Amazon Associate I earn from qualifying purchases.

Installing Maven

After few years of not needing it, I came back to Maven, reason being that I cannot use Gradle for reasons beyond my control and Ant does not describe complex projects structures required.


As an Amazon Associate I earn from qualifying purchases.

Installing Maven

After few years of not needing it, I came back to Maven, reason being that I cannot use Gradle for reasons beyond my control and Ant does not describe complex projects structures required.


Getting new version of Maven


$ brew install maven
==> Downloading ....
/usr/local/Cellar/maven/3.2.3:
$ mvn -version

Apache Maven 3.2.3
$ which mvn
/usr/local/bin/mvn


Setting M2_HOME


$ echo $M2_HOME
# nada


I added the following in my ~/.profile




# Maven - updated: Oct 20, 2014
export MAVEN_HOME=/usr/local/Cellar/maven/3.2.3/
export PATH=${PATH}:${MAVEN_HOME}/bin
export M2_HOME=/usr/local/Cellar/maven/3.2.3/
export PATH=${PATH}:${M2_HOME}/libexec


and run:

$ echo $M2_HOME
/usr/local/Cellar/maven/3.2.3/



As an Amazon Associate I earn from qualifying purchases.

Bash: GIT repetitive tasks

I have too many GIT repos to remember that I need to keep updated, to do that I have a script that updates what I need.



As an Amazon Associate I earn from qualifying purchases.

Bash: GIT repetitive tasks

I have too many GIT repos to remember that I need to keep updated, to do that I have a script that updates what I need.




function git_do() {
echo
if [ -z "$1" ]
then
echo 'Please provide a directory name e.g. do my_directory_here'
exit 0
fi
cd $1
pwd
git config --get remote.origin.url
git fetch
git checkout develop
git rebase
git status
}
clear
git_do repo1
git_do repo2/module/repo3
git_do repo2/module/repo4
etc.



As an Amazon Associate I earn from qualifying purchases.

Mac Daemons that hunt us

Sometimes you get annoyed by garbage other companies are trying to stuff on your computer. Motorola is one of these companies. When I connect my test DROID device the annoying popups are opened. 

This is not a conclusive solution, but a start of the longer article on the unwanted Mac Daemons that suck up your patience and CPU power.

Removing Launch services


$ launchctl list | grep moto
- 0 com.motorola.motohelperUpdater
32594 - com.motorola.motohelper
- 0 com.motorola.MDMUpdaterPlist
$ launchctl remove com.motorola.motohelper

$ launchctl remove com.motorola.motohelperUpdater


Removing unwanted Application



cd /Library/Application\ Support/
$ ls | grep Moto
MotoCast

Motorola Mobility
uki@ Application Support $ sudo rm -r MotoCast
Password:

uki@ Application Support $ sudo rm -r Motorola\ Mobility/



List of legitimate Services:


  • PTPCamera - part of the Image Capture software that MacOS uses


As an Amazon Associate I earn from qualifying purchases.

Mac Daemons that hunt us

Sometimes you get annoyed by garbage other companies are trying to stuff on your computer. Motorola is one of these companies. When I connect my test DROID device the annoying popups are opened. 

This is not a conclusive solution, but a start of the longer article on the unwanted Mac Daemons that suck up your patience and CPU power.

Removing Launch services


$ launchctl list | grep moto
- 0 com.motorola.motohelperUpdater
32594 - com.motorola.motohelper
- 0 com.motorola.MDMUpdaterPlist
$ launchctl remove com.motorola.motohelper

$ launchctl remove com.motorola.motohelperUpdater


Removing unwanted Application



cd /Library/Application\ Support/
$ ls | grep Moto
MotoCast

Motorola Mobility
uki@ Application Support $ sudo rm -r MotoCast
Password:

uki@ Application Support $ sudo rm -r Motorola\ Mobility/



List of legitimate Services:


  • PTPCamera - part of the Image Capture software that MacOS uses


As an Amazon Associate I earn from qualifying purchases.

Got Droid? - My Android (test) devices

While cleaning my office I decided to make an inventory of my Android devices.

Please note that it is NOT worth testing on anything less than API 8 Android 2.2 Froyo as it is less than 0.7% of the market share,  so it is OK to use support library v7 in all apps you are running. 
I keep my Google ION for "sentimental reasons only.


OSOS versionVersion NameAPI LEVEL% usedMakeModelCPU nameCPU MhzCPU numberflash ROMRAMCamera MpBTRadioscreen heightscreen widthscreen density dpiScreen diagonal inches
Android1.6Donut40HTCGoogle ION / Magic528132quad band unlocked3.2
Android2.2.3Froyo80.7MotorolaDROIDArm Cortex A860015128544802403.7
Android/CM2.3.3Gingerbread MR11011.4BNNookColor10246001617
Android2.3.3Gingerbread MR11011.4HTCVision / Desire Z A7272ARMv7 Scorpion80011.5Gb51252.18004802403.7
Android2.3.4Gingerbread MR11011.4MotorolaDROID2 A955OMAP 3630100018Gb51252.18544803.7
Android4.2.2Jelly Bean1720.7SamsungGT-P7510 Tab 10.1128075216010.1
Android4.1.11720.7HTCOne X11967203204.9
Android4.4.2KitKat1924.5SamsungSM-P990 Galaxy Tab 12.12560160032012.1
Android/CM4.4.4KitKat1924.5OnePlusOne A0001Snapdragon 8014192010804805.5













Android name to version to API level table


  • API 1 (no code name) 1.0  
  • API 1 (no code name) 1.1  
  • API 3 Cupcake 1.5, NDK 1
  • API 4 Donut 1.6, NDK 2
  • API 5 Eclair 2.0  
  • API 6 Eclair 2.0.1  
  • API 7 Eclair 2.1, NDK 3 - support-v7 ActionBar
  • API 8 Froyo 2.2.x  , NDK 4
  • API 9 Gingerbread 2.3 - 2.3.2  , NDK 5 - added some NFC
  • API 10 Gingerbread 2.3.3 - 2.3.7   - added full NFC
  • API 11 Honeycomb 3.0  
  • API 12 Honeycomb 3.1  , NDK 6
  • API 13 Honeycomb 3.2.x  
  • API 14 Ice Cream Sandwich 4.0.1 - 4.0.2, NDK 7 - added NFC: Android Beam
  • API 15 Ice Cream Sandwich 4.0.3 - 4.0.4 , NDK 8
  • API 16 Jelly Bean 4.1.x  
  • API 17 Jelly Bean 4.2.x  
  • API 18 Jelly Bean 4.3.x  
  • API 19 KitKat 4.4 - 4.4.4  
  • API 20 Android Wear devices
  • API 21 Lollipop 5.0 API level 21


My devices spreadsheet





As an Amazon Associate I earn from qualifying purchases.

Got Droid? - My Android (test) devices

While cleaning my office I decided to make an inventory of my Android devices.

Please note that it is NOT worth testing on anything less than API 8 Android 2.2 Froyo as it is less than 0.7% of the market share,  so it is OK to use support library v7 in all apps you are running. 
I keep my Google ION for "sentimental reasons only.


OSOS versionVersion NameAPI LEVEL% usedMakeModelCPU nameCPU MhzCPU numberflash ROMRAMCamera MpBTRadioscreen heightscreen widthscreen density dpiScreen diagonal inches
Android1.6Donut40HTCGoogle ION / Magic528132quad band unlocked3.2
Android2.2.3Froyo80.7MotorolaDROIDArm Cortex A860015128544802403.7
Android/CM2.3.3Gingerbread MR11011.4BNNookColor10246001617
Android2.3.3Gingerbread MR11011.4HTCVision / Desire Z A7272ARMv7 Scorpion80011.5Gb51252.18004802403.7
Android2.3.4Gingerbread MR11011.4MotorolaDROID2 A955OMAP 3630100018Gb51252.18544803.7
Android4.2.2Jelly Bean1720.7SamsungGT-P7510 Tab 10.1128075216010.1
Android4.1.11720.7HTCOne X11967203204.9
Android4.4.2KitKat1924.5SamsungSM-P990 Galaxy Tab 12.12560160032012.1
Android/CM4.4.4KitKat1924.5OnePlusOne A0001Snapdragon 8014192010804805.5













Android name to version to API level table


  • API 1 (no code name) 1.0  
  • API 1 (no code name) 1.1  
  • API 3 Cupcake 1.5, NDK 1
  • API 4 Donut 1.6, NDK 2
  • API 5 Eclair 2.0  
  • API 6 Eclair 2.0.1  
  • API 7 Eclair 2.1, NDK 3 - support-v7 ActionBar
  • API 8 Froyo 2.2.x  , NDK 4
  • API 9 Gingerbread 2.3 - 2.3.2  , NDK 5 - added some NFC
  • API 10 Gingerbread 2.3.3 - 2.3.7   - added full NFC
  • API 11 Honeycomb 3.0  
  • API 12 Honeycomb 3.1  , NDK 6
  • API 13 Honeycomb 3.2.x  
  • API 14 Ice Cream Sandwich 4.0.1 - 4.0.2, NDK 7 - added NFC: Android Beam
  • API 15 Ice Cream Sandwich 4.0.3 - 4.0.4 , NDK 8
  • API 16 Jelly Bean 4.1.x  
  • API 17 Jelly Bean 4.2.x  
  • API 18 Jelly Bean 4.3.x  
  • API 19 KitKat 4.4 - 4.4.4  
  • API 20 Android Wear devices
  • API 21 Lollipop 5.0 API level 21


My devices spreadsheet





As an Amazon Associate I earn from qualifying purchases.

Post Scriptum

The views in this article are mine and do not reflect those of my employer.
I am preparing to cancel the subscription to the e-mail newsletter that sends my articles.
Follow me on:
X.com (Twitter)
LinkedIn
Google Scholar

Popular Recent Posts

Most Popular Articles

apt quotation..