Saturday, December 12, 2015

Fix Joomla "Table xxxx_updates doesn't exist" Error When Installing Modules (Joomla 3.4+)

While I was installing a module to the joomla 3.4.X, I got the below error:

Table 'xxxx_updates' doesn't exist SQL=SHOW FULL COLUMNS FROM updates in joomla

And the installation failed.

Cause

The error occurs because the Joomla database table that stores available updates (named using your table prefix followed by _updates) does not exist in the site's database. In the article below the placeholder xxxx represents your database table prefix.

Safety first: BACK UP your database

Before making any change to your database, create a full backup of the database (and files). If you have shell access you can use:

mysqldump -u DB_USER -p DB_NAME > db-backup-YYYYMMDD.sql

Or use phpMyAdmin's Export feature to export the database.

Find your table prefix

Open your Joomla site's configuration.php file and look for the database prefix setting (for example public $dbprefix = 'jos_';). Replace the xxxx placeholder below with your actual prefix (for example jos or abc123).

Solution — recreate the missing updates table

If the xxxx_updates table is missing you can recreate it. You have two options:

  • Preferred: create the table only if it does not exist.
  • If a malformed table exists you can DROP it and recreate it (dangerous without backup).

Option A — create table if it does not exist (safer)

Replace xxxx_ with your table prefix and run the CREATE TABLE statement:

CREATE TABLE IF NOT EXISTS `xxxx_updates` (
  `update_id` int(11) NOT NULL AUTO_INCREMENT,
  `update_site_id` int(11) DEFAULT 0,
  `extension_id` int(11) DEFAULT 0,
  `name` varchar(100) DEFAULT '',
  `description` text NOT NULL,
  `element` varchar(100) DEFAULT '',
  `type` varchar(20) DEFAULT '',
  `folder` varchar(20) DEFAULT '',
  `client_id` tinyint(3) DEFAULT 0,
  `version` varchar(32) DEFAULT '',
  `data` text NOT NULL,
  `detailsurl` text NOT NULL,
  `infourl` text NOT NULL,
  `extra_query` varchar(1000) DEFAULT '',
  PRIMARY KEY (`update_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Available Updates';

Option B — drop and recreate (only if you are sure and have a backup)

DROP TABLE xxxx_updates;

-- then run the CREATE TABLE statement from Option A

Where to run these SQL statements

  • phpMyAdmin: open your database, go to the SQL tab, paste the SQL, and run it.
  • MySQL CLI: connect with mysql -u DB_USER -p DB_NAME and paste the statements.
  • If available, check Joomla admin: Extensions → Manage → Database (it can sometimes fix or report database schema issues).

After running the SQL

This solves the issue. Now try to install the new module — it should install successfully.

Troubleshooting

  • If you still see errors, verify the database user has CREATE and ALTER privileges.
  • Confirm the table prefix used in SQL matches the prefix from configuration.php exactly (including the trailing underscore if present).
  • Ensure your database engine supports InnoDB and your server uses utf8 charset (the CREATE statement uses ENGINE=InnoDB DEFAULT CHARSET=utf8).
  • If Joomla reports other missing schema items, check Extensions → Manage → Database and run any suggested fixes.

This procedure recreates the updates table and addresses the module installation failure caused by the missing table.

Wednesday, September 2, 2015

Kids App — Android Alphabet Learning App with Text-to-Speech (English & Kannada)

I was trying to develop an Android app for my son which will help him learn the alphabets. I thought it may be helpful to others also so I'm sharing it on Google Play: Kids Application.

Overview

Kids App is a simple alphabet learning application for Android that combines text-to-speech with image-based learning. The app uses its own local database to store images, alphabets, words and pronunciation data. It currently supports two languages (English and Kannada) and two modes of operation (Manual and Auto). This is a draft version — we plan to add more languages and features.

Main features

  • Text-to-speech pronunciation for alphabets and numbers
  • Image and word display for each alphabet
  • Local database to store user-configured images, words and pronunciations
  • Two languages supported now: English and Kannada
  • Two operation modes: Manual (tap letters) and Auto (play-through)
  • Settings to configure images (camera or gallery), words and pronunciations

Languages

  • English
  • Kannada

We are going to enhance it for other languages also.

Modes of operation

Manual

Tap any alphabet to see the associated word and image and hear the pronunciation. For example: A for Apple.

Auto

The app automatically walks through all the alphabets and numbers, showing each item and pronouncing it without user tapping.

Configuration (customization)

The best part of this application is the ability for the user to configure their own word, image and pronunciation for each alphabet. For example, if your child's name is Krishna, you can set that name, an image and pronunciation for the letter K.

How to configure:

  1. Open the app and tap the menu button on the alphabet screen.
  2. Select "Configure".
  3. Choose an image from the camera or gallery, set the word, and provide pronunciation if needed.
  4. Save — the data is stored in the app database. To revert to defaults, use the "SetDefault" option.

Screenshots

These are the original screenshots from the post (kept as-is):

Splash and selection screen

Mode and language selection

Manual mode: alphabet screen

Example: A for Apple (image + TTS)

Numbers view

Configure menu and options

Configure: set image and word

Auto mode walkthrough

Kannada alphabet screen

Kannada: examples

Additional Kannada screen

App icon / Google Play link

How it works (technical)

  • The core code is written in Java and the GUI is developed using XML (standard Android components).
  • The app maintains a local database with images, words and pronunciations. User changes are saved locally until the user selects the default dataset.
  • Text-to-speech leverages Android's TTS engine for pronunciation.

Download

You can download the app from Google Play: Kids App on Google Play

Roadmap / planned enhancements

  • Add more languages
  • Add additional configuration options and improvements to the UI
  • Improve accessibility and TTS language detection

Notes and contact

This is a draft version — we are planning more features. Keep watching this post for updates.

If you have feedback or feature requests, install the app from the Play Store and send feedback through the app or comment on this post.

Tuesday, August 25, 2015

Enable or Disable an Android Button at Runtime (with network check)

While I was working with an Android application for a customer, there was a use case to disable a button at runtime and enable it after some action. This is straightforward in Android. Below I show the XML for the button, how to reference it in your activity, and how to enable/disable it based on network status using a small NetworkUtil helper (link provided).

Button XML

Use a standard Button in your layout (example):

<Button
    android:id="@+id/about_button"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="64dp"
    android:text="@string/about_label" />

Reference the Button in your Activity

In onCreate(), find the button and keep a reference. Using the Button type makes intentions clearer and provides button-specific APIs:

Button aboutButton = findViewById(R.id.about_button);

Note: on older Android APIs you may need a cast, e.g. Button aboutButton = (Button) findViewById(R.id.about_button);, but with modern SDKs the generic signature is available.

Enable and disable the Button

You can enable or disable a View (including Button) using setEnabled(true/false):

  • To enable:
aboutButton.setEnabled(true);
  • To disable:
aboutButton.setEnabled(false);

Disabling a button via setEnabled(false) also prevents it from receiving click events. For improved UX you may also want to change the visual appearance (alpha, color) so users can see the disabled state:

aboutButton.setEnabled(false);
aboutButton.setAlpha(0.5f); // visual cue
// when enabling back:
aboutButton.setEnabled(true);
aboutButton.setAlpha(1f);

Remember to make UI changes on the main thread.

Enable based on network status (using NetworkUtil)

I use a small helper class NetworkUtil to check network connectivity. You can download it here:

Create an instance and call getConnectivityStatus with a Context. Example usage (corrected and formatted):

NetworkUtil net = new NetworkUtil();
int status = net.getConnectivityStatus(getApplicationContext());
if (status != 0) {
    aboutButton.setEnabled(true);
    aboutButton.setAlpha(1f);
} else {
    aboutButton.setEnabled(false);
    aboutButton.setAlpha(0.5f);
}

Notes:

  • The original article had a typo setEnabled(flase); ensure you use false.
  • The meaning of status values depends on NetworkUtil implementation. Keep your app logic consistent with that helper's return values.

Accessibility and UX considerations

  • When disabling interactive elements, ensure assistive technologies can convey the change. Consider adding content descriptions for non-textual controls and ensuring focus behavior is appropriate.
  • Adjust visual indicators (alpha, color) so users can perceive the disabled state.

Alternatives and further improvements

  • For production apps consider using Android's ConnectivityManager and NetworkCallback APIs to observe connectivity changes rather than polling.
  • In modern architectures, expose connectivity status via LiveData, Flow, or other observable streams and observe from the Activity/Fragment to update UI reactively.

NetworkUtil download link (same as above): https://sites.google.com/site/karjolblogs/downloads/NetworkUtil.java?attredirects=0&d=1

That’s it. Happy Coding..

Saturday, August 22, 2015

Android: Detect when an AdMob ad has loaded (AdListener + network check)

Overview

In some Android apps you need to take action when an AdMob ad successfully loads and a different action when it does not. This post shows how to detect both cases using AdView.setAdListener and how to avoid requesting ads when there is no network connection.

The original examples and links are preserved below, followed by a short checklist and an updated example to match newer Google Mobile Ads SDK patterns.


Detecting ad load with AdListener (original example)

Use AdView.setAdListener and override onAdLoaded() and onAdFailedToLoad(…). This is the code from the original post:

ad.setAdListener(new AdListener() {            
    @Override
    public void onAdLoaded() {
        Log.d(TAG, "Ad Received");
        //Code implementation if the ad is loaded
        ………
        ………
    }

    @Override
    public void onAdFailedToLoad(int errorcode) {
        Log.d(TAG, "Ad Not Loaded Received");
        //Code implementation if the ad is NOT loaded
        ………
        ………
    }
});

Explanation

  • onAdLoaded(): called when the ad has been successfully loaded into the AdView — put the code you want executed on success here (e.g., show the ad container).
  • onAdFailedToLoad(…): called when the ad request failed — put fallback behavior here (e.g., hide the ad container, log the error, schedule a retry).

Note: the snippet above is the original form used in the article. Later SDK versions changed the parameter type for onAdFailedToLoad; see the updated example below.


Check network connectivity before requesting ads

The article recommends checking network status before attempting to fetch ads so the app does not continuously try to fetch when offline. You can use ConnectivityManager as shown in the official Android docs: https://developer.android.com/training/basics/network-ops/managing.html

Original illustrative code from the post:

private static final String DEBUG_TAG = "NetworkStatusExample";
...
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
boolean isWifiConn = networkInfo.isConnected();

networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
boolean isMobileConn = networkInfo.isConnected();

Log.d(DEBUG_TAG, "Wifi connected: " + isWifiConn);
Log.d(DEBUG_TAG, "Mobile connected: " + isMobileConn);

The author provided a helper class NetworkUtil; you can download it here: https://sites.google.com/site/karjolblogs/downloads/NetworkUtil.java?attredirects=0&d=1

Use it like this (from the original post):

NetworkUtil net = new NetworkUtil();
int status = net.getConnectivityStatus(getApplicationContext());
if (status != 0) {
    // Code if the network connection is there
    ad.loadAd(new AdRequest.Builder().build());
    ad.setAdListener(new AdListener() {
        @Override
        public void onAdLoaded() {
            Log.d(TAG, "Ad Received");
            // code when the ad loaded
        }

        @Override
        public void onAdFailedToLoad(int errorcode) {
            Log.d(TAG, "Ad Not Loaded Received");
            // code if the ad loading is failed
        }
    });
} else {
    // Code if the network connection is NOT there
}

Required permission

To check network status at runtime you must have the following permission in AndroidManifest.xml:

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

(Ensure your NetworkUtil implementation relies on this permission.)


Updated notes for newer Google Mobile Ads SDKs

The post originates from 2015; Google Mobile Ads SDK APIs have evolved. Two practical points to add for modern readers:

  • Initialize the Mobile Ads SDK early in your app (for example in Application.onCreate()):
// Example initialization (SDK versions may vary)
MobileAds.initialize(context, initializationStatus -> { /* optional callback */ });
  • In recent SDK versions, onAdFailedToLoad has a different signature and provides richer error information (for example via LoadAdError). Here is an example that shows both an updated listener and how to inspect the error for troubleshooting:
// Updated example (SDK may require different imports; check your SDK docs)
adView = findViewById(R.id.adView);
MobileAds.initialize(this, initializationStatus -> {});
AdRequest adRequest = new AdRequest.Builder().build();

adView.setAdListener(new AdListener() {
    @Override
    public void onAdLoaded() {
        Log.d(TAG, "Ad Received");
        // show ad view or update UI
    }

    @Override
    public void onAdFailedToLoad(LoadAdError adError) {
        Log.d(TAG, "Ad Not Loaded Received: " + adError.toString());
        // Inspect adError.getCode() or adError.getMessage() for debugging
        // hide ad view or implement retry/backoff
    }
});

adView.loadAd(adRequest);

Refer to the official Google Mobile Ads documentation for the SDK version you use (the original article linked the AdView docs: https://developers.google.com/android/reference/com/google/android/gms/ads/AdView).


Practical tips and recommended behavior

  • Hide the ad container when no ad is available to avoid empty space in your UI.
  • Implement exponential backoff for retries rather than continuous immediate retries.
  • Log errors with enough detail to diagnose (error code/message) but avoid leaking sensitive user data.
  • Ensure you comply with AdMob policies when changing ad behavior.

References and downloads


Final notes

That’s it. Happy Coding..

Friday, August 21, 2015

Integrating Google AdMob Banner Ads in Android (Step‑by‑Step)

I was wondering how to integrate Ads from Google in my Android applications. AdMob is a widely used mobile advertising platform that you can integrate with your Android app fairly easily.

In this post you will learn how to show AdMob banner ads in your Android application. This write‑up is divided into three parts:

  • Getting an Ad Unit ID from the AdMob site
  • Installing Google Play Services in the Android SDK (Eclipse instructions as originally used)
  • Integrating AdSense/AdMob code into your Android app

Note: this article preserves the original Eclipse/SDK Manager workflow used when it was written. Most developers today should use Android Studio and the Google Mobile Ads SDK via Gradle. See the “Modern tooling” note at the end for guidance.

1) Getting Ad Unit Id from the AdMob site

  1. Go to the AdMob site: https://www.google.com/admob/
  2. Create a new account (or log in if you already have one).
  3. Select the “Monetize new app” option.
  4. Search your Android application (from Google Play) or add the app details manually.

AdMob step 1

  1. After filling the app information, AdMob shows setup instructions and lets you create an ad unit and get the Ad Unit ID.

AdMob select app

  1. Your app will be added in AdMob. In the Monetize tab you can select the app, create a banner ad, and copy the Ad Unit ID (it looks like):
ca-app-pub-50xxxx69xxxxxxxx/34xxxxxxxx
  1. You will use this Ad Unit ID in your project later.

2) Installing Google Play Services in Android SDK (Eclipse era instructions)

These steps describe the older Eclipse + SDK Manager workflow used when this post was written.

  1. Open Eclipse and go to Window -> SDK Manager.

SDK Manager

  1. In the packages list select Extras -> check Google Play Services and install it.

Install Google Play Services

  1. Import the Google Play Services project/library into your workspace.
  2. Add the Google Play Services library to the project where you want to integrate AdMob.

Add library to project

3) Integrating AdSense / AdMob code into the Android app

  1. Open your layout XML and add the Ads XML namespace (required to use ads: attributes):
xmlns:ads="http://schemas.android.com/apk/res-auto"
  1. Add an AdView to the layout. Example:
<com.google.android.gms.ads.AdView
    android:id="@+id/adView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    ads:adSize="BANNER"
    ads:adUnitId="YOUR_AD_UNIT_ID" />
  1. In your Activity Java file initialize the AdView object:
AdView ad = (AdView) findViewById(R.id.adView);
  1. Load an ad from Google:
ad.loadAd(new AdRequest.Builder().build());
  1. Modify AndroidManifest.xml: add required permissions, metadata for Google Play Services, and the AdActivity entry.

Add permissions:

<!-- Used to request banner ads. -->
<uses-permission android:name="android.permission.INTERNET" />

<!-- Used to avoid sending an ad request if there is no connectivity. -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Add Google Play Services metadata (inside ):

<meta-data
    android:name="com.google.android.gms.version"
    android:value="@integer/google_play_services_version" />

Add the AdActivity which is required to show ad overlays:

<activity android:name="com.google.android.gms.ads.AdActivity"
    android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" />

The original article includes a sample manifest; here is the final manifest excerpt reproduced for reference:

xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.marutsoft.sudoku"
    android:versionCode="3"
    android:versionName="1.3">

    <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19"/>

    <!-- Used to request banner ads. -->
    <uses-permission android:name="android.permission.INTERNET" />

    <!-- Used to avoid sending an ad request if there is no connectivity. -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

        <activity android:name="com.marutsoft.sudoku.Splash"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- Activity required to show ad overlays. -->
        <activity android:name="com.google.android.gms.ads.AdActivity"
            android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" />

    </application>

</manifest>

Now run your application and check that the Google ad is shown in the Activity where you have added it. Please note you need to have internet connectivity.

Also you can add code to check the availability of connectivity and then load the ad — we will add that part in my next blog.

That’s it. Happy Coding..


Modern tooling note (recommended)

This article preserves the original Eclipse instructions. If you are using Android Studio (recommended):

  • Use the Google Mobile Ads SDK via Gradle (implementation 'com.google.android.gms:play-services-ads:…') and follow current AdMob docs.
  • Newer SDKs require an application-level AdMob App ID meta‑data entry in AndroidManifest.xml and explicit MobileAds.initialize(…) in your application code before loading ads. Also always use test ads or register test device IDs while developing.

If you want, I can provide a modern, Android Studio + Gradle version of these steps with updated code samples and a short checklist for publishing with AdMob.

Thursday, August 20, 2015

How to Upload and Make a Downloadable ZIP File in Blogger (Using Google Sites)

I wanted to make some files available to download for my readers. Blogger does not provide native attachments, but you can host files elsewhere and link to them from your blog. Below I show how I used Google Sites and the File Cabinet page template to host files and then link to them from a Blogger post.

Quick summary

Host the file on Google Sites using the File Cabinet page template, right-click the Download link to copy the file URL, then paste that URL into your Blogger post as a link (example below).

What you need

  • A Google account
  • A Google Site (create one if you don’t have it)
  • The file(s) you want readers to download (ZIP, PDF, etc.)

Steps

1. Go to Google Sites

Login with your Google account. If you don’t have a Google Site yet, create one using the CREATE button.

2. Create a new site

Choose a template, fill in the site name and location, complete the CAPTCHA if prompted, and click CREATE.

3. Add a new page using the File Cabinet template

Create a new page and select the File Cabinet page template (this template is designed to host downloadable files).

File cabinet template image

4. Upload files

Use the File Cabinet page controls to add the files you want to provide for download.

Upload files image

5. Copy the file link

After uploading, locate the Download link for the file. Right-click the Download link and choose "Copy link address" to copy the direct URL to the file.

Copy link address image

6. Add the link to your Blogger post

In the Blogger post editor, add a link to the text where readers will click to download. You can paste the URL directly using the editor's link tool, or use raw HTML like this:

<a href="PASTE_COPIED_LINK_HERE">Download ZIP</a>

If your editor supports it, select a descriptive anchor text such as "Download ZIP — contains sample code".

7. Publish and test

Publish your Blogger post and click the link to confirm the file downloads correctly. If users report access issues, check the sharing/permission settings on the Google Site (make sure the file/page is publicly accessible if you want anyone to download it).

Helpful screenshots

Create site screenshot

Created file cabinet screen

Notes and alternatives

  • Google Sites UI may change over time — if you cannot find a File Cabinet template, look for a page template that supports file uploads or use another file-hosting service.
  • As an alternative, you can host files in Google Drive or another file host and link to them from Blogger. If you use a different host, be sure to verify public access permissions before publishing.

That’s it. Happy Coding..

Thursday, August 13, 2015

MySQL: Query by Month & Day in PHP — Find Today's Birthdays and Anniversaries

While we were working on a web portal, one of the use cases was to send greeting emails to members on their birthday and anniversaries.

Problem

We needed to get all email IDs from the database whose birthday or anniversary is today. The script runs from a cron job every morning at 9:00. Birth and anniversary dates in the database are stored in YYYY-MM-DD format. If you compare the full date with today (including year) you won't get matches because the years differ.

Simple idea

Query only by month and day. First, get today's month and day in PHP (without the year), then match the date column in the database by month-day.

Original code (as published)

The original article used this approach. (Note: this preserves the author's original example.)

//Setting the time zone
 date_default_timezone_set("Asia/Kolkata");

//Get today's date without year
 $today=date('m-d');
 echo  $today;

//add "%-" to the today's date in the place of year
 $today1= "%-".$today;
 echo $today1;

//Now write the SQL query using LIKE statement

//Note members is the table and dob&anniversary are cloumns.

$query_res="SELECT fname,email FROM `members` WHERE `dob` LIKE '$today1' or `anniversary` LIKE '$today1'";
$result_res=mysql_query($query_res);


while($row_res=mysql_fetch_array($result_res))
{
//code to send the email
}

Why this works

Dates stored as 'YYYY-MM-DD' will end with '-MM-DD'. By prepending '%-' to the month-day string you match the tail of the date string. Example: for today = '08-21', '%-08-21' matches '1987-08-21' or '2010-08-21'.

Important notes and improvements (do this instead)

  1. Deprecated API: The original code uses the old mysql_* API. These functions are removed in modern PHP versions. Use mysqli or PDO with prepared statements.
  2. Performance: Using a function or LIKE on a date column prevents MySQL from using an index. On large tables this can become slow. Consider storing a computed month-day column (or separate month and day columns) that you can index, or use a generated (virtual/stored) column in MySQL 5.7+.
  3. Correct SQL alternatives: Rather than string matching with LIKE, use DATE_FORMAT or the MONTH()/DAY() functions for clarity.
  4. Edge cases: Decide how to handle Feb 29 birthdays on non-leap years (send on Feb 28 or skip). Also confirm server timezone vs. PHP timezone.
  5. Security: Even though this query comes from server-side logic, always prefer prepared statements to avoid injection risks if you later introduce user input.

Recommended SQL approaches

Option A — DATE_FORMAT (clear and direct):

SELECT fname, email
FROM members
WHERE DATE_FORMAT(dob, '%m-%d') = '08-21'
   OR DATE_FORMAT(anniversary, '%m-%d') = '08-21';

Option B — MONTH() and DAY():

SELECT fname, email
FROM members
WHERE MONTH(dob) = 8 AND DAY(dob) = 21
   OR MONTH(anniversary) = 8 AND DAY(anniversary) = 21;

Both of these use functions on the column (so they will not use a plain index on the date column). To improve performance, add a computed/generated column or store month/day separately and index that column.

Modern, secure PHP example using PDO and DATE_FORMAT

// Set timezone
date_default_timezone_set('Asia/Kolkata');

// Get today's month-day
$md = date('m-d'); // e.g. '08-21'

// Using PDO and a parameterized query with DATE_FORMAT
$dsn = 'mysql:host=DB_HOST;dbname=DB_NAME;charset=utf8mb4';
$user = 'DB_USER';
$pass = 'DB_PASS';

try {
    $pdo = new PDO($dsn, $user, $pass, [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    ]);

    $sql = "SELECT fname, email FROM members
            WHERE DATE_FORMAT(dob, '%m-%d') = :md
               OR DATE_FORMAT(anniversary, '%m-%d') = :md";

    $stmt = $pdo->prepare($sql);
    $stmt->execute([':md' => $md]);

    while ($row = $stmt->fetch()) {
        // code to send the email
        // $row['fname'], $row['email']
    }
} catch (PDOException $e) {
    // handle error (log it)
    error_log($e->getMessage());
}

Example using a computed column for better performance

If you have MySQL 5.7+ you can create a generated column and index it:

ALTER TABLE members
  ADD COLUMN md CHAR(5) GENERATED ALWAYS AS (DATE_FORMAT(dob, '%m-%d')) VIRTUAL,
  ADD INDEX (md);

Then query with an equality on md (this can use the index):

SELECT fname, email FROM members WHERE md = '08-21';

Or maintain a small VARCHAR column populated at insert/update time with the month-day to get an indexable column on older MySQL versions.

Handling Feb 29

Decide whether Feb 29 birthdays should receive greetings on Feb 28 during non-leap years. Implement that logic in PHP if desired:

$md = date('m-d');
if ($md === '02-28' && !date('L')) { // not a leap year
    // also include '02-29' birthdays
}

Cron and timezone

  • Make sure the server timezone and PHP timezone are correct for your audience. The script will use PHP's timezone setting when calling date().
  • Cron runs in the system timezone by default — ensure alignment or use UTC.

Final notes

  • Keep the original simple approach if your table is small and traffic is low. For production systems, prefer PDO/mysqli and consider an indexed computed column for scalability.

Happy Coding..

Wednesday, August 12, 2015

How to Determine Connectivity Status in Android — ConnectivityManager & NetworkCapabilities

While developing Android applications, a common use case is to schedule regular updates of application data from Internet resources, cache data, or execute long-running downloads. But if you aren't connected to the Internet, or the connection is too slow to complete your download, you should avoid waking the device or starting a network operation. So before you trigger any of these activities you need to check the connectivity status.

You can use the ConnectivityManager to check that you're actually connected to the Internet, and if so, what type of connection is in place (Wi‑Fi, cellular, ethernet, etc.). The Android docs are here: https://developer.android.com/reference/android/net/ConnectivityManager

Permissions

Make sure the following permission is declared in AndroidManifest.xml so your app can query connectivity state:

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

Legacy example (NetworkInfo)

The following snippet shows how to use ConnectivityManager to query the active network and determine if it has connectivity. This is the original/legacy approach and uses NetworkInfo (deprecated in API 29):

ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();

You can also check the type of the active network to determine whether it is Wi‑Fi:

boolean isWiFi = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;

Notes about the legacy approach:

  • NetworkInfo and isConnectedOrConnecting were commonly used in older Android versions, but NetworkInfo is deprecated starting in API level 29. Prefer the modern NetworkCapabilities approach on newer devices.

Modern approach (API 29+): NetworkCapabilities

On Android Q (API 29) and later, use NetworkCapabilities and getActiveNetwork() to inspect the currently active network in a more accurate way. NetworkCapabilities lets you check both transport type and capabilities such as NETCAPABILITYINTERNET and NETCAPABILITYVALIDATED.

ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
Network network = cm.getActiveNetwork(); // may be null
NetworkCapabilities nc = cm.getNetworkCapabilities(network);

boolean hasInternet = nc != null && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
boolean validated = nc != null && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
boolean isWifi = nc != null && nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);

Explanation:

  • NETCAPABILITYINTERNET means the network can reach the Internet in principle.
  • NETCAPABILITYVALIDATED indicates the platform has validated that the network can actually reach the Internet (often more useful to decide whether to attempt network IO).
  • Use hasTransport(…) to detect TRANSPORTWIFI, TRANSPORTCELLULAR, TRANSPORTETHERNET, TRANSPORTVPN, etc.

Listening for changes: registerNetworkCallback

If you need to be notified of connectivity changes (rather than polling), register a NetworkCallback:

NetworkRequest request = new NetworkRequest.Builder()
        .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
        .build();

ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback() {
    @Override
    public void onAvailable(Network network) {
        // network became available
    }

    @Override
    public void onLost(Network network) {
        // network lost
    }
};

cm.registerNetworkCallback(request, callback);
// Remember to unregister when appropriate: cm.unregisterNetworkCallback(callback);

Testing and troubleshooting

  • In the emulator you can simulate network conditions or disable the network.
  • Use adb to toggle airplane mode or modify network rules if needed.
  • Prefer checking NETCAPABILITYVALIDATED when you need a reliable indication that the network can reach the public Internet.

Summary

  • The original ConnectivityManager + NetworkInfo approach works on older devices but is deprecated (API 29+).
  • Use NetworkCapabilities.getNetworkCapabilities(getActiveNetwork()) and check capabilities and transports on modern Android.
  • Always declare ACCESSNETWORKSTATE in the manifest.

It's also possible to determine the type of Internet connection currently available. Device connectivity can be provided by mobile data, WiMAX, Wi‑Fi, and ethernet connections. By querying the type of the active network you can adjust behavior (for example, refresh rate or large downloads) based on bandwidth.

If "isWiFi" is true then the device is using Wi‑Fi connection. That's it. Happy coding.

References:

Wednesday, June 24, 2015

Convert date strings to MySQL DATE in PHP — strtotime() and DateTime examples

I was working on a Web portal, where there was a use case to import the csv or xls to a MySql database. In the database there was a field for date with the date data type. And from the xls or csv when we are importing, it imports as the string. So when you are trying to insert a string or text in date data type, it adds as 0000-00-00 which is wrong.

For that, to insert it correctly we need to convert the date string to date format before inserting.

Consider the below csv file to be imported. Dob (Date of Birth) is the column that contains the date.

CSV date example image

First row is the header. Now the content of the DOB, DOJ and Anniversary columns has to be converted to date format. Below is the code to be considered to convert it.

Quick solution (original approach)

//For DOB

$time = strtotime($data[7]);
$data[7] = date('Y-m-d', $time);

// For DOJ

$time = strtotime($data[8]);
$data[8] = date('Y-m-d', $time);

//For Anniversary

$time = strtotime($data[11]);
$data[11] = date('Y-m-d', $time);

strtotime(string) is the function that converts the string to time format. Now this has to be converted to required date format. That can be done using date(format, time) function.

Format you can use the required format. Here I am using yyyy-mm-dd format for that we can use Y-m-d. Now the $data[7], $data[8] and $data[11] contains the date in date datatype and also in yyyy-mm-dd format.

That's it. Happy Coding


Explanation and important checks

  • strtotime() returns FALSE on failure. If you pass that FALSE to date('Y-m-d', $time), PHP converts it to 1970-01-01 or you may end up inserting an incorrect value — your original symptom of 0000-00-00 usually happens when MySQL receives an invalid date string.
  • Always check the return value before formatting.

Example with checks:

// Example check before formatting
$time = strtotime($data[7]);
if ($time === false || empty($data[7])) {
    // handle invalid or empty input: set to NULL or skip
    $data[7] = null; // or use a default
} else {
    $data[7] = date('Y-m-d', $time);
}

Safer approach: DateTime and createFromFormat()

strtotime() works for many common formats, but if your CSV uses a specific format (for example dd/mm/yyyy or mm-dd-yyyy), prefer DateTime::createFromFormat() so you can parse deterministically.

Example parsing a dd/mm/yyyy input and handling failure:

$dateString = trim($data[7]); // e.g. "31/12/1980"
if ($dateString === '') {
    $data[7] = null; // treat empty as NULL in DB
} else {
    $dt = DateTime::createFromFormat('d/m/Y', $dateString);
    $errors = DateTime::getLastErrors();
    if ($dt === false || $errors['warning_count'] > 0 || $errors['error_count'] > 0) {
        // parsing failed — fallback or log
        // try a fallback with strtotime:
        $time = strtotime($dateString);
        if ($time !== false) {
            $data[7] = date('Y-m-d', $time);
        } else {
            $data[7] = null; // or flag this row for manual review
        }
    } else {
        // convert to MySQL DATE format
        $data[7] = $dt->format('Y-m-d');
    }
}

This approach avoids ambiguous parsing and is more robust when you know the input format.

Inserting into MySQL safely (use prepared statements)

Don't concatenate date strings into SQL. Use parameterized queries. Example using PDO inserting a DATE (or NULL):

// assume $pdo is a configured PDO instance
$sql = "INSERT INTO people (name, dob, doj, anniversary) VALUES (:name, :dob, :doj, :anniv)";
$stmt = $pdo->prepare($sql);

// $data[7], $data[8], $data[11] now contain either 'Y-m-d' strings or null
$stmt->execute([
    ':name' => $data[0],
    ':dob' => $data[7],      // PDO will convert null to SQL NULL
    ':doj' => $data[8],
    ':anniv' => $data[11]
]);

If you must use mysqli, use prepared statements similarly.

Handling multiple input formats

  • If the CSV may contain multiple date formats, implement a normalization function:
  • Try DateTime::createFromFormat for a list of expected formats.
  • Fallback to strtotime().
  • If still failing, log the row and keep it for manual review.

Example helper:

function normalizeDateToYmd($input, array $formats = ['d/m/Y', 'm/d/Y', 'Y-m-d']) {
    $s = trim($input);
    if ($s === '') return null;
    foreach ($formats as $fmt) {
        $dt = DateTime::createFromFormat($fmt, $s);
        $errors = DateTime::getLastErrors();
        if ($dt !== false && $errors['warning_count'] === 0 && $errors['error_count'] === 0) {
            return $dt->format('Y-m-d');
        }
    }
    // fallback to strtotime
    $t = strtotime($s);
    if ($t !== false) return date('Y-m-d', $t);
    return null; // unable to parse
}

Edge cases and tips

  • Empty or invalid date fields: insert SQL NULL instead of '0000-00-00'.
  • Timezones: DATE in MySQL has no timezone, but if your CSV has times or timezone offsets, normalize before truncating.
  • Excel dates: XLS/XLSX may export dates as Excel serial numbers. Use a library (e.g., PhpSpreadsheet) and convert Excel date serials to PHP dates.
  • Logging: collect rows with unparseable dates and report them rather than silently inserting NULL.
  • Input sanitation: always trim input and remove non-printable characters before parsing.

References

That's it. Happy Coding

Thursday, June 11, 2015

Essential Eclipse IDE Keyboard Shortcuts — Windows & Linux (Cheat Sheet)

Editors are an integral part of programming. There are a lot of editors available; Eclipse has been a widely used Java IDE. Shortcuts make life much easier when you are working with any IDE. Below is a collected cheat sheet of the most useful Eclipse keyboard shortcuts for Windows and Linux. (Mac OS typically uses the Cmd key instead of Ctrl.)

Note: This page lists the shortcuts as the author wrote them. If you rely on a specific Eclipse release, verify shortcuts in your Eclipse key preferences.

Table of contents

Notes

  • Shortcuts below are given for Windows and Linux. On macOS, replace Ctrl with Cmd where applicable.
  • The list is presented in the same grouping the author used so you can jump to categories quickly.

1. Manage Files and Projects

  • Ctrl+N : Create new project using the Wizard
  • Ctrl+Alt+N : Create new project, file, class, etc.
  • Alt+f, then . : Open project, file, etc.
  • Ctrl+Shift+R : Open Resource (file, folder or project)
  • Alt+Enter : Show and access file properties
  • Ctrl+S : Save current file
  • Ctrl+Shift+S : Save all files
  • Ctrl+W : Close current file
  • Ctrl+Shift+W : Close all files
  • Ctrl+P : Print the file
  • F5 : Refresh content of selected element with local file system

2. Editor Window

Focus/cursor must be in the editor window for these to work.

  • F12 : Jump to Editor Window
  • Ctrl+PageDown / Ctrl+PageUp : Switch to next editor / previous editor
  • Ctrl+M : Maximize or minimize current editor window (also works for other windows)
  • Ctrl+E : Show list of open editors (use arrow keys and Enter to switch)
  • Ctrl+F6 / Ctrl+Shift+F6 : Show list of open editors; switches immediately upon release of Ctrl
  • Alt+← / Alt+→ : Go to previous / next editor window
  • Alt+- : Open editor window option menu
  • Ctrl+F10 : Show view menu (features available on left vertical bar: breakpoints, bookmarks, line numbers, …)
  • Ctrl+F10, then n : Show or hide line numbers
  • Ctrl+Shift+Q : Show or hide the diff column on the left (changes since last save)

3. Navigate in Editor

  • Home / End : Jump to beginning / end of indentation. Press Home twice to jump to beginning of line
  • Ctrl+Home / Ctrl+End : Jump to beginning / end of source
  • Ctrl+← / Ctrl+→ : Jump one word left / one word right
  • Ctrl+Shift+↓ / Ctrl+Shift+↑ : Jump to previous / next method
  • Ctrl+L : Jump to line number. (To hide/show line numbers: Ctrl+F10 then select 'Show Line Numbers')
  • Ctrl+Q : Jump to last location edited
  • Ctrl+. / Ctrl+, : Jump to next / previous compiler syntax warning or error
  • Ctrl+Shift+P : With a bracket selected: jump to the matching bracket
  • Ctrl+[+] / Ctrl+- on numeric keypad : Collapse / expand current method or class
  • Ctrl+[/] / Ctrl+* on numeric keypad : Collapse / expand all methods or classes
  • Ctrl+↓ / Ctrl+↑ : Scroll editor without changing cursor position
  • Alt+PageUp / Alt+PageDown : Next sub-tab / previous sub-tab
  • Ctrl+F7 : Next View
  • Ctrl+Shift+F7 : Previous View
  • Ctrl+F8 : Next Perspective
  • Ctrl+Shift+F8 : Previous Perspective
  • Ctrl+. : Go to the next problem / error
  • Ctrl+, : Go to the previous problem / error

4. Select Text

  • Shift+→ / Shift+← : Expand selection by one character right / left
  • Ctrl+Shift+→ / Ctrl+Shift+← : Expand selection to next / previous word
  • Shift+↓ / Shift+↑ : Expand selection by one line down / up
  • Shift+End / Shift+Home : Expand selection to end / beginning of line
  • Ctrl+A : Select all
  • Alt+Shift+↑ : Expand selection to current element (e.g., current one-line expression or content within brackets)
  • Alt+Shift+← / Alt+Shift+→ : Expand selection to next / previous element
  • Alt+Shift+↓ : Reduce previously expanded selection by one step

5. Edit Text

  • Ctrl+C / Ctrl+X / Ctrl+V : Copy, Cut and Paste
  • Ctrl+Z : Undo last action
  • Ctrl+Y : Redo last (undone) action
  • Ctrl+D : Delete line
  • Alt+↑ / Alt+↓ : Move current line or selection up or down
  • Ctrl+Alt+↑ / Ctrl+Alt+↓ : Duplicate current line or selection up or down (note: on some Windows setups these shortcuts may rotate the screen)
  • Ctrl+Delete : Delete next word
  • Ctrl+Backspace : Delete previous word
  • Shift+Enter : Enter line below current line
  • Shift+Ctrl+Enter : Enter line above current line
  • Insert : Toggle between insert and overwrite mode
  • Shift+Ctrl+Y : Change selection to all lower case
  • Shift+Ctrl+X : Change selection to all upper case

6. Search and Replace

  • Ctrl+F : Open find and replace dialog
  • Ctrl+K / Ctrl+Shift+K : Find previous / find next occurrence of search term (close find window first)
  • Ctrl+H : Search workspace (Java Search, Task Search, and File Search)
  • Ctrl+J / Ctrl+Shift+J : Incremental search forward / backwards (type search term after pressing Ctrl+J)
  • Ctrl+Shift+O : Open a resource search dialog to find any class
  • Ctrl+J : Incremental search without popup dialog; press Ctrl+J to find the next match
  • Ctrl+Shift+G : In the Java editor, search for references in the workspace
  • Ctrl+Shift+P : Select the matching bracket (cursor needs to be before or after a bracket)

7. Indentations and Comments

  • Tab / Shift+Tab : Increase / decrease indent of selected text
  • Ctrl+I : Correct indentation of selected text or current line
  • Ctrl+Shift+F : Autoformat all code in editor using code formatter
  • Ctrl+/ : Comment / uncomment line or selection (adds //)
  • Ctrl+Shift+/ : Add block comment around selection (adds /* ... */)
  • Ctrl+Shift+\ : Remove block comment
  • Alt+Shift+J : Add element comment (adds /** ... */)

8. Editing Source Code

  • Ctrl+Space : Opens Content Assist (show available methods, fields, etc.)
  • Ctrl+1 : Open Quick Fix and Quick Assist
  • Alt+/ : Propose word completion (after typing at least one letter; press repeatedly to cycle options)
  • Ctrl+Shift+Insert : Deactivate or activate Smart Insert Mode (automatic indentation, automatic brackets, etc.)

9. Code Information

  • Ctrl+O : Show code outline / structure
  • F2 : Open class, method, or variable information (tooltip text)
  • F3 : Open Declaration — jump to declaration of selected class, method, or parameter
  • F4 : Open Type Hierarchy window for selected item
  • Ctrl+T : Show / open Quick Type Hierarchy for selected item
  • Ctrl+Shift+T : Open Type in Hierarchy
  • Ctrl+Alt+H : Open Call Hierarchy
  • Ctrl+U : Find occurrences of expression in current file
  • Ctrl+move over method : Open Declaration or Implementation (hover and Ctrl+click behavior)

10. Refactoring

  • Alt+Shift+R : Rename selected element and all references
  • Alt+Shift+V : Move selected element to other class or file (with complete method or class selected)
  • Ctrl+Shift+C : Change method signature (with method name selected)
  • Alt+Shift+M : Extract selection to method
  • Alt+Shift+L : Extract local variable (create and assign a variable from a selected expression)
  • Alt+Shift+I : Inline selected local variables, methods, or constants if possible

11. Run and Debug

  • Ctrl+F11 : Save and launch application (Run)
  • F11 : Debug
  • F5 : Step Into function
  • F6 : Next step (line by line)
  • F7 : Step out
  • F8 : Resume / Skip to next Breakpoint

12. Others

  • Ctrl+F7 / Ctrl+Shift+F7 : Switch forward / backward between views (panels)
  • Ctrl+F8 / Ctrl+Shift+F8 : Switch forward / backward between perspectives
  • Ctrl+P : Print
  • F1 : Open Eclipse Help
  • Shift+F10 : Show context menu (right click)
  • Ctrl+3 : Quick Access — focus the Quick Access box to execute any Eclipse command
  • Ctrl+Shift+O : Organize imports
  • Alt+Shift+S then R : Generate getter and setter methods
  • Ctrl+Space : Type assist (Content Assist)
  • Alt+Shift+Z : Enclose block in try-catch
  • Shift+F2 : Show Javadoc for current element

Last updated: (replace with actual date when you update this page)

If you want this as a printable one-page cheat sheet, consider generating a PDF from this page or linking to a downloadable image. If you customize or rebind keys in Eclipse, set a note or link to your key-bindings guide under the editor preferences.

Saturday, May 30, 2015

How to reference XML views in an Android Fragment (findViewById examples)

While developing an Android application using an Activity, we typically reference XML elements with findViewById like this:

TextView name = (TextView) findViewById(R.id.Config_name);

This works when your class extends Activity, because Activity provides findViewById. When your class extends Fragment, calling findViewById directly on the Fragment will not compile — the method isn't available on Fragment.

How to reference views from a Fragment

You can still use findViewById from a Fragment, but you must call it on the fragment's root view (after the layout has been inflated). There are two common ways to do this:

1) Use getView() (after the view is created):

TextView name = (TextView) getView().findViewById(R.id.Config_name);

Note: getView() returns the Fragment's root view and is only non-null after the view has been created (for example, after onCreateView returns and typically in or after onViewCreated). Calling getView() too early can return null.

2) Use the view returned by inflater when you inflate the layout in onCreateView:

View myFragmentView = inflater.inflate(R.layout.MyLayout, container, false);
TextView name = (TextView) myFragmentView.findViewById(R.id.Config_name);

This approach is explicit and safe because you are using the view object you just inflated.

Minimal onCreateView example

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View root = inflater.inflate(R.layout.MyLayout, container, false);
    TextView name = (TextView) root.findViewById(R.id.Config_name);
    // initialize other views here
    return root;
}

Or, using onViewCreated (the view is already created and attached):

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    TextView name = (TextView) view.findViewById(R.id.Config_name);
}

Notes and tips

  • Always make sure you access views after the layout is inflated (onCreateView/onViewCreated) to avoid NullPointerExceptions.
  • The examples above are Java; in Kotlin you can use view.findViewById(R.id.Config_name) or prefer View Binding for safer, null-safe access.
  • Modern Android projects commonly use View Binding or Kotlin view binding delegates instead of manual findViewById — consider adding a View Binding example if you update this post later.

That's it. Use these patterns for TextView or any other view in your fragment. Hope this helps. Happy Coding.

Friday, May 29, 2015

How to Convert an Android Activity to a Fragment — Step-by-Step

Earlier I developed an android application using the Activity. But now the trend is to develop the android application using the Fragments. So I thought of converting the Activity based android application to Fragment based Android application. Earlier I thought it’s very difficult to do it. But It’s very simple.

Overview

Here are the steps how we convert an activity to a Fragment:

Prerequisite

  • Basic knowledge of Android Activities and Fragments.
  • If you are using the Support Library, the article uses android.support.v4.app.Fragment types as shown below. Newer projects may use the AndroidX equivalents (androidx.fragment.app.Fragment).

Steps

  1. First we need to import the package: FragmentActivity of Support V4 app package:
Import android.support.v4.app.FragmentActivity;
  1. Change the extends Activity to extends Fragment. Eg:
public class HomeFragment extends Fragment{

}
  1. Add the method onCreateView and move everything from onCreate of Activity to onCreateView except super.onCreate() and setContentView()
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
    View v = null;
    v = inflater.inflate(R.layout.fragment_home, parent, false);

    // Content of previous onCreate() here
    // ...

    // Don't use this method, it's handled by inflater.inflate() above :
    // setContentView(R.layout.fragment_home);

    return v;
}
  1. Remove method onCreate().

  2. Everywhere you access the Activity with "this" or just something or "this.something" replace with super.getActivity(). or use the value saved in the onCreateView

Example:

// Before (in Activity)
Intent i = getIntent();

// In Fragment
Intent i = super.getActivity().getIntent();

That’s it. Happy Coding…

Wednesday, May 20, 2015

How to integrate WhatsApp with an Android app or website — prefill messages using whatsapp://

We can integrate WhatsApp with an Android app in two ways:

Methods

  1. Using the Android Intent system (covered in my previous post: http://karjol-gt.blogspot.in/2015/05/how-to-share-media-or-message-text-with.html).
  2. Using the custom URL scheme provided by WhatsApp.

We will discuss the second option in this post.

WhatsApp custom URL scheme (website or app)

WhatsApp provides a custom URL scheme to interact with the app. If you have a website and want to open a WhatsApp chat with a pre-defined message, you can use WhatsApp’s custom URL scheme.

Opening whatsapp://send?text= followed by the text to send will open WhatsApp, allow the user to choose a contact, and prefill the input field with the specified text.

Example (on a website)

Use a normal anchor tag. The message must be URL-encoded (spaces become %20, etc.). Example:

<a href="whatsapp://send?text=Hello%20World!">Hello, world!</a>

When the user clicks this link, WhatsApp (if installed) opens, the user selects a contact, and the predefined text "Hello World!" appears in the chat input.

Notes and compatibility

  • URL-encode the message text. Unencoded spaces and special characters may break the URL.
  • This method relies on the whatsapp:// custom scheme and therefore requires the WhatsApp app to be installed on the device. Behavior can vary by platform, browser, and WhatsApp version. Test on the target devices and browsers.
  • Consider adding a fallback for environments where the whatsapp:// scheme is unsupported (for example, conditionally offering the WhatsApp FAQ or guiding users to install WhatsApp).

Summary

That’s it. Happy Coding…

Reference

Tuesday, May 19, 2015

Share Text and Media with Social Apps in Android — Intent examples and best practices

I was developing an android application for a customer. One requirement was to share some media and text with the installed social Android apps like Google+, Email, Gmail, Facebook, Drive, Messaging, WhatsApp etc. This post shows how to share predefined text and media from your app.

Overview

In Android you can share text or media with other installed apps using Intents. Below I demonstrate a simple example (sharing a predefined text) from our Panchanga app. I show the original minimal code used in the app and then give recommended, modern improvements (chooser, file sharing, FileProvider, and package checks).

Create the menu item

The original app added a menu item called "Share". The minimal code used was:

MenuItem share;

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);

    share = menu.add("Share");
    share.setIcon(R.drawable.share);
    share.setOnMenuItemClickListener(this);

    return true;
}

Note: share.png was added to the drawable folder.

Implement the onMenuItemClickListener (original example)

This is the original minimal onMenuItemClick implementation in the article:

public boolean onMenuItemClick(MenuItem menuItem) {

    if (menuItem == share) {
        Intent sendIntent = new Intent();
        sendIntent.setAction(Intent.ACTION_SEND);
        sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
        sendIntent.setType("text/plain");
        startActivity(sendIntent);
    }

    return true;
}

Here, the system picks all the social apps installed on the device and shows them in the chooser. You can select the required app to send. The text "This is my text to send." is what is sent to other apps.

Below are the images from the original article showing the share chooser and examples:

share1

share2

share3

Share only with a specific app (original note)

If you want to target only a specific app instead of showing a chooser, you can call setPackage on the Intent. Example from the original article:

sendIntent.setPackage("com.whatsapp");

The article linked to the Intent.setPackage docs: http://developer.android.com/reference/android/content/Intent.html#setPackage(java.lang.String)

"com.whatsapp" is the package name of WhatsApp; use the package name of the app you want to target.


Recommended improvements and modern best practices

Keep the original minimal examples (above) for reference, but use these improvements for production apps.

1) Always use a chooser so the user sees a consistent share sheet

Replace startActivity(sendIntent) with:

startActivity(Intent.createChooser(sendIntent, "Share via"));

This forces the chooser UI and avoids launching a default app unexpectedly.

2) If targeting a specific package, check that the package exists first

PackageManager pm = getPackageManager();
if (pm.getLaunchIntentForPackage("com.whatsapp") != null) {
    sendIntent.setPackage("com.whatsapp");
    startActivity(sendIntent);
} else {
    // App not installed — fall back to chooser
    startActivity(Intent.createChooser(sendIntent, "Share via"));
}

Wrap startActivity in try/catch(ActivityNotFoundException) as a final fallback.

3) Sharing files (images, PDFs) — use EXTRA_STREAM and FileProvider on Android N+

When sharing a file (image, PDF, etc.) use a content:// URI and FileProvider for API 24+ to avoid FileUriExposedException.

Example (sharing a single image):

File file = new File(getFilesDir(), "shared_image.jpg");
Uri contentUri = FileProvider.getUriForFile(context, "your.package.name.fileprovider", file);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
shareIntent.setType("image/jpeg");
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(shareIntent, "Share image"));

You must declare a FileProvider in your AndroidManifest.xml and add a file_paths.xml resource describing the shared paths. See the official docs for details: https://developer.android.com/reference/androidx/core/content/FileProvider

4) Sharing multiple files

Use ACTIONSENDMULTIPLE with an ArrayList in EXTRA_STREAM:

ArrayList<Uri> uris = new ArrayList<>();
// add multiple content URIs
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
shareIntent.setType("image/*");
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(shareIntent, "Share images"));

5) Attach subject or title when appropriate

For email apps, add EXTRASUBJECT and/or EXTRATITLE:

sendIntent.putExtra(Intent.EXTRA_SUBJECT, "Check out Panchanga");
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");

Note: some apps (notably Facebook) ignore prefilled text in shared content due to their platform policy.

6) MIME types and behaviour

Set the right MIME type: text/plain for text, image/* for images, application/pdf for PDFs. A wrong MIME type may hide some target apps from the chooser.

7) Runtime permissions

If the files you want to share are on external storage, ensure you handle runtime permissions (READEXTERNALSTORAGE) on Android 6.0+.

8) Troubleshooting and UX notes

  • If the chooser shows no apps, check the MIME type and ensure there is at least one app that handles the action and MIME type.
  • If you target a specific package and the app is not installed, handle it by notifying the user or falling back to the chooser.

Conclusion

The original minimal example is valid for sharing simple text. For robust production behavior across Android versions, add a chooser, handle URIs with FileProvider, set correct MIME types, and guard setPackage with a PackageManager check. That will give a safer and more consistent user experience.

Happy Coding!

Sudoku Game Development in Android — Features & Google Play Link

Greetings of the Day!!!

When I was learning Android, I thought of developing a game. The easiest was a Sudoku game. And when I was reading an Android book I saw a basic example of the game and thought of using it and building on top of it. So I started it and completed it for a single game. But I did not share it with anybody. When I was cleaning up the things today I saw that game and thought of sharing it.

Overview

I extended the basic example into a small Android Sudoku app with multiple levels, game persistence, and an in-app Settings screen. The app opens with the previous settings and can remember and resume the last-in-progress game.

Features

  • Levels: Easy, Medium and Hard
  • Multiple puzzles per level; when you select a level the app randomly picks a puzzle for you to play
  • Resume: the app remembers the current game state so you can leave mid-way and continue later
  • Settings: options to show hints and to play music; settings are stored using SharedPreferences so they persist across app restarts

Technical notes

  • Level selection: the app presents predefined puzzles grouped by difficulty and randomly selects a puzzle from the chosen level.
  • Persistence: current game state is saved so a paused or interrupted game can be resumed. Settings (hints, music) are implemented with SharedPreferences so they persist when the app is closed and reopened.

(If you want more developer-focused detail — e.g., code snippets showing how game state is serialized or how SharedPreferences are used — I can add minimal, copy-paste-ready examples.)

Screenshots

aboutpng

splash

main

Capture

level

settings

Download

You can download the game from Google Play:

https://play.google.com/store/apps/details?id=com.marutsoft.sudoku

Notes and next steps

  • This post is a short introduction and screenshots from the app. If you want a follow-up developer post, I can add concrete implementation details: puzzle storage format, random selection algorithm, how I save and restore game state, and code showing SharedPreferences usage for settings. Tell me which part you want first and I will publish a technical walk-through.

Tuesday, May 12, 2015

Change TabHost Tab Colors in Android — Set Selected & Unselected Colors

Introduction

In Android you can change the color of TabHost tabs. By default the TabHost appearance is grey. In this example the author changes the unselected tab color to #A45D0A (dark orange / brown tone) and the selected tab color to #A42C0A (dark red).

This article shows how to initialize tabs (each associated with a ListView in the original example), set initial colors, and update colors inside an onTabChanged listener.

Prerequisites

  • A layout that contains a TabHost (for example, with id R.id.TabHost01).
  • A helper method getTabIndicator(Context, String, Drawable) used in the original example to create a tab indicator view — keep your implementation of that helper.

Code example (corrected and formatted)

// Required imports
import android.graphics.Color;
import android.widget.TabHost;
import android.widget.TabWidget;
import android.widget.TabHost.OnTabChangeListener;

// ... inside your Activity / Fragment where popupView is available:
final TabHost tabs = (TabHost) popupView.findViewById(R.id.TabHost01);
tabs.setup();

// Optional: show dividers and custom divider drawable
tabs.getTabWidget().setShowDividers(TabWidget.SHOW_DIVIDER_MIDDLE);
tabs.getTabWidget().setDividerDrawable(R.drawable.custom_tab_indicator_divider);

// Create tab 1
TabHost.TabSpec tab1 = tabs.newTabSpec("tab1");
tab1.setContent(R.id.listView01);
tab1.setIndicator(getTabIndicator(tabs.getContext(), "Dialed", getResources().getDrawable(R.color.white)));
tabs.addTab(tab1);

// Create tab 2
TabHost.TabSpec tab2 = tabs.newTabSpec("tab2");
tab2.setContent(R.id.listView02);
tab2.setIndicator(getTabIndicator(tabs.getContext(), "Missed", getResources().getDrawable(R.color.white)));
tabs.addTab(tab2);

// Create tab 3
TabHost.TabSpec tab3 = tabs.newTabSpec("tab3");
tab3.setContent(R.id.listView03);
tab3.setIndicator(getTabIndicator(tabs.getContext(), "Received", getResources().getDrawable(R.color.white)));
tabs.addTab(tab3);

// Set initial colors: first tab selected color, others unselected
for (int i = 0; i < tabs.getTabWidget().getChildCount(); i++) {
    if (i == 0)
        tabs.getTabWidget().getChildAt(i).setBackgroundColor(Color.parseColor("#A42C0A")); // selected
    else
        tabs.getTabWidget().getChildAt(i).setBackgroundColor(Color.parseColor("#A45D0A")); // unselected
}

// Handle tab changes
tabs.setOnTabChangedListener(new OnTabChangeListener() {
    @Override
    public void onTabChanged(String tabId) {
        // Reset all tabs to unselected color
        for (int i = 0; i < tabs.getTabWidget().getChildCount(); i++) {
            tabs.getTabWidget().getChildAt(i).setBackgroundColor(Color.parseColor("#A45D0A")); // unselected
        }

        // Set the currently selected tab color
        tabs.getTabWidget().getChildAt(tabs.getCurrentTab()).setBackgroundColor(Color.parseColor("#A42C0A")); // selected
    }
});

Notes and explanations

  • The original article used #A45D0A for unselected tabs and #A42C0A for the selected tab. These hex values are preserved above.
  • The helper method getTabIndicator(…) used in setIndicator(…) is not included in the original post — keep your implementation or replace with a standard TextView/ImageView as needed.
  • The code corrects several small issues from the original post (case-sensitive method names and inconsistent variable names). For example, Color.parseColor must be used (not parsecolor), and the listener should reference the same TabHost variable (tabs.getCurrentTab()).

Best practices and improvements to consider

  • Use color resources (res/values/colors.xml) instead of hard-coded hex values:
<color name="tab_selected">#A42C0A</color>
<color name="tab_unselected">#A45D0A</color>

Then use ContextCompat.getColor(context, R.color.tabselected) or getResources().getColor(R.color.tabselected, null) on newer APIs.

  • Prefer using a selector drawable for tab backgrounds instead of changing background color in code. A selector makes state handling simpler and moves styling into XML.

  • Consider modern alternatives: TabHost is an older pattern. For new apps, use TabLayout with ViewPager or ViewPager2 (from the Material components / AndroidX) for better integration and styling.

  • Accessibility: ensure tabs have readable text (high contrast) and consider contentDescription when tabs are primarily icon-based.

  • On API 23+ use ContextCompat.getColor(context, … ) or ResourcesCompat to avoid deprecated calls.

Conclusion

Now populate the data for the ListViews associated with each tab. That’s it — Happy Coding..

Saturday, May 9, 2015

SRSM Panchanga — Manmatha Naam Samvastara data added (Android) – Download & Screenshots

Greetings of the day!!!

Summary

First of all, sorry for the delay in updating the Panchanga app with Manmatha naam data. And thanks to all those who reminded me — I received more than 100 emails requesting the Manmatha naam samvastara update. Earlier I used to get the soft copy of the Panchanga from SRSMutt at least two months before Ugadi; this time they did not send it due to technical issues, so I had to convert the data manually.

What changed

  • Manmatha naam samvastara Panchanga data has been added to the SRSM Panchanga Android app.
  • As of now only the English version of the app is updated. The Kannada version is in progress and will be made available soon.

Where to download

You can download the app from Google Play:

SRSM Panchanga — https://play.google.com/store/apps/details?id=com.sarga.simplecal

(Click the link above to open the Play Store on your device.)

Quick install steps

  • Open the Play Store link on your Android device.
  • Tap Install.
  • After installation, open the app and verify the Panchanga data under the Manmatha naam samvastara section.

Screenshots

Below are some of the app screenshots showing the updated data and features.

SRSM Panchanga screenshot 1

SRSM Panchanga screenshot 2

SRSM Panchanga screenshot 3

SRSM Panchanga screenshot 4

SRSM Panchanga screenshot 5

SRSM Panchanga screenshot 6

SRSM Panchanga screenshot 7

SRSM Panchanga screenshot 8

SRSM Panchanga screenshot 9

SRSM Panchanga screenshot 10

SRSM Panchanga screenshot 11

SRSM Panchanga screenshot 12

SRSM Panchanga screenshot 13

SRSM Panchanga screenshot 14

SRSM Panchanga screenshot 15

SRSM Panchanga screenshot 16

Notes & feedback

  • The Kannada version is in progress and will be released when the Kannada data is ready.
  • If you face issues after installing, please reply to the original post's contact email or use the blog's contact form.

Changelog (brief)

  • Added: Manmatha naam samvastara data (English app release).
  • Pending: Kannada language release (work in progress).

Thank you for your patience and for the many reminders and emails — they helped prioritize this update.

--

(Author)

Friday, May 8, 2015

Add a Custom Title Bar to an Android App (Theme-based, step-by-step)

I was developing a quiz app for a customer. And the requirement was to have a custom header / title for the application that’s horizontally center-aligned on the display. This article shows how to set a custom window title using theme styles, a custom layout, and activity code.

Prerequisites

  • Basic Android project knowledge.
  • Android project — example project named "Quiz" in this article.
  • Files we will touch or create:
  • res/values/styles.xml
  • res/values/colors.xml
  • res/values/themes.xml
  • res/layout/header.xml (custom title layout)
  • AndroidManifest.xml
  • MainActivity.java (or the activity where you want the custom title)

1) Create / update styles.xml

Add the style(s) you want to use for your custom title to res/values/styles.xml. (The original article showed the styles as an image — keep that image below as a visual reference.)

styles example

(If styles.xml is missing in your project, create res/values/styles.xml and add the relevant style tags.)

2) Add colors (colors.xml)

Create res/values/colors.xml and add the color resources you will use in the title / theme. The original colors.xml content was provided as an image (kept below):

colors example

3) Add / update themes.xml

Add the theme that references your custom title style or window features in res/values/themes.xml. The article’s example theme content is available as an image here:

theme example

Make sure the style you created is referenced from the final theme applied to your activity or application.

4) Apply the theme in AndroidManifest.xml

Apply the theme to the whole application or to specific activities in AndroidManifest.xml. The manifest snippet from the original article is included below as an image for reference:

manifest snippet

5) Create the custom title layout (header.xml)

Create a layout resource (for example res/layout/header.xml) that contains the controls you want in the title bar. You can include text, images, logos, or other controls. The original article’s example layout (only text in this case) is shown below as an image:

header layout example

(Another preview of the header layout in the original article:)

header layout example 2

6) Add the code in your Activity's onCreate()

In your activity's onCreate() (e.g., MainActivity.java), add the code required to enable and set the custom window title. The exact code used in the original article was provided as an image — kept below:

activity onCreate snippet

The article’s final run screenshot (customized title bar on top) is below:

final result preview

Troubleshooting

If you forget any of the steps above you may see a runtime exception like this in logcat:

Caused by: android.util.AndroidRuntimeException:
You cannot combine custom titles with other title features

To fix this, add the following in your theme (themes.xml) to disable default title features so the custom title can be used:

<item name="android:windowNoTitle">true</item>

Alternatively, remove the activity-level theme that includes a title bar (for that particular activity) from AndroidManifest.xml. The original article lists this example manifest attribute used in some cases:

android:theme="@android:style/Theme.Black.NoTitleBar"

Notes and recommendations

  • Keep the images above as visual references, but add textual code blocks (as I’ve suggested in the "Troubleshooting" section) for each code example so readers can copy-paste. In the original post many code examples were only images — that should be corrected.
  • For new projects consider using the AppCompat Toolbar (androidx.appcompat.widget.Toolbar) as the recommended approach. The custom window title method is useful for legacy projects or specific use cases.

That’s it. Happy Coding…