How to overcome “This site is attempting to download multiple files” dialog in android chrome

Today, I ran into the issue with Chrome (Android) with my Web Application, we allow users to download files through our web application and they can download many files one after another or bundled in a zip.

Now once user downloaded a file and tried to download another, chrome shows a message like this : (“This site is attempting to download multiple files”)

Chrome Alert

I started looking for any alternate method which can help to fix this, we use a single method to initiate all downloads so there was no option to bind separate methods to each click events, so rather we tried something else and it fixed it.

We use a form while submitting every commands to server for downloading file, I just simply added a target of this form to “_blank” everything else stayed same, the action attribute stayed same as well. This trick solved the issue, now when user initiates a download another tab opens, and it closes it automatically when download is initiated, so its not a big problem!

If you are not using a form but an ajax call, you can still do it with this way, just add a fake form on page, set action to your ajax call’s URL and submit your ajax call through this form, so it will do the same trick.

Thanks,
Vipul

facebooktwittergoogle_plusredditpinterestlinkedinmailfacebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Detect programatically if headphone or bluetooth headsets attached with Android phone

In some case you might want to detect if phone’s headphone jack is in use or bluetooth headset is attached with Phone. Sharing code here to help others. Use files linked at the end of the post and use this code for detection :

/** broadcast receiver listen the headset phone/ bluetooth headset plugged in change state event **/

AudioInOutChangeReceiver.java

public class AudioInOutChangeReceiver extends BroadcastReceiver
{
    private static final String ACTION_HEADSET_PLUG_STATE = "android.intent.action.HEADSET_PLUG";

    private BluetoothHeadset mBluetoothHeadset;


    private AudioInOutChangeReceiver(Context aContext)
    {
        Log.d(getTAG(), "AudioInOutChangeReceiver()");
    
        initiBTHeadSetConfiguration();
    }

    @Override
    public void onReceive(Context context, Intent intent) 
    {   
        // initial audio manager 
        initiAudioManager(context);
        
        final String action = intent.getAction();
        // check action should not empty
        if(TextUtils.isEmpty(action))return;
         
         //Broadcast Action: Wired Headset plugged in or unplugged.
         if (action.equals(ACTION_HEADSET_PLUG_STATE)) 
         {
             updateHeadSetDeviceInfo(context, intent);
             
    } 
    //Broadcast Action: BluetoothA2dpOff Headset plugged in or unplugged.
    else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)
                || BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)
                || BluetoothAdapter.ACTION_STATE_CHANGED.equals(action))
         {
            
            updateBTHeadSetDeviceInfo(context, intent);
         }
    }

    public void updateHeadSetDeviceInfo(Context context, Intent intent)
    {
         //0 for unplugged, 1 for plugged.
         int state = intent.getIntExtra("state", -1);
         
         StringBuilder stateName = null;
         
         //Headset type, human readable string
         String name = intent.getStringExtra("name");
         
         // - 1 if headset has a microphone, 0 otherwise, 1 mean h2w
         int microPhone = intent.getIntExtra("microphone", -1);
         
         switch (state) 
         {
           case 0:
               stateName = new StringBuilder("Headset is unplugged");
               Log.d(getTAG(),stateName.toString());
               break;
           case 1:
               stateName = new StringBuilder("Headset is plugged");
               Log.d(getTAG(),stateName.toString());
               break;
           default:
               Log.d(getTAG(), "I have no idea what the headset state is");
         }
    }

    public void updateBTHeadSetDeviceInfo(Context context, Intent intent)
    {
        if(intent != null)
        {
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if(device != null)
            {
                verifyHeadSetState(true,device);
            }
        }
    }

    private void verifyHeadSetState(boolean flag,BluetoothDevice device)
    {
        
        //TODO Wait for other wise result getting wrong 
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        int state = 0;
        HeadSetModel btheasetdmodel = null;
        if(flag)
        {
            // STATE_DISCONNECTED   0
            // STATE_CONNECTED      2
            
            // STATE_CONNECTING     1
            // STATE_DISCONNECTING  3
            
            state = mBluetoothHeadset.getConnectionState(device);
            Log.d(getTAG(), "State :" + state);
        }
        else
        {
            AudioManager am = getAudioManager();
            state = (am.isBluetoothA2dpOn() == true) ? 1 : 0;
        }
        
        switch (state) 
        {
            case 0:
            {
                Log.d(getTAG(), "isBluetoothA2dpOff()");
                btheasetdmodel= new HeadSetModel().setState(0).setStateName("BluetoothA2dpOff");
                break;  
            }
            case 1:
            {
                Log.d(getTAG(), "isBluetoothA2dpOn()");
                btheasetdmodel= new HeadSetModel().setState(1).setStateName("BluetoothA2dpOn");
                break;
            }
            case 2:
            {
                Log.d(getTAG(), "isBluetoothA2dpOn()");
                btheasetdmodel= new HeadSetModel().setState(1).setStateName("BluetoothA2dpOn");
                break;
            }
            default:
                break;
        }
    }

    private void initiBTHeadSetConfiguration()
    {
        if (mBTHeadSetManager == null)
            mBTHeadSetManager = new BluetoothHeadsetManager(mContext);
        
        mBTHeadSetManager.addListener(mHeadsetCallback);
        
        // if BT is turn on then we move next step
        if(mBTHeadSetManager.hasEnableBluetooth())
        {
            mBTHeadSetManager.connectionToProxy();
        }
    }
    
    private void resetBTHeadSetConfiguration()
    {
        mBTHeadSetManager.disconnectProxy();
    }

    public onBluetoothHeadSetListener mHeadsetCallback = new onBluetoothHeadSetListener() {        
        @Override
        public void disconnectedToProxy() 
        {
            verifyHeadSetState(false,null);
        }
        
        @Override
        public void connectedToProxy(BluetoothHeadset aBluetoothHeadset) 
        {
            mBluetoothHeadset = aBluetoothHeadset;
            if(mBluetoothHeadset != null)
            {
                verifyHeadSetState(false,null); 
            }
        }
    };
}

Register the broadcast receiver inside your activity :

@Override
protected void onResume() 
{
    super.onResume();
    // register for normal head set plugged in/out
    registerReceiver(AudioInOutChangeReceiver.getInstance(AbsBaseActivity.this).addAudioController(mAudioHeadsetController), new IntentFilter(Intent.ACTION_HEADSET_PLUG));
    registerReceiver(AudioInOutChangeReceiver.getInstance(AbsBaseActivity.this).addAudioController(mAudioHeadsetController), new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED));
    registerReceiver(AudioInOutChangeReceiver.getInstance(AbsBaseActivity.this).addAudioController(mAudioHeadsetController), new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED));
    registerReceiver(AudioInOutChangeReceiver.getInstance(AbsBaseActivity.this).addAudioController(mAudioHeadsetController), new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
}

@Override
protected void onPause() 
{
    super.onPause();
    unregisterReceiver(AudioInOutChangeReceiver.getInstance(AbsBaseActivity.this).removeAudioController());
}

You will need these 2 files (find them in zip) for this code to work, import them in your project, change package name to match your project’s and use above code.

DetectHeadphoneBTHs.zip

1) AudioInOutChangeReceiver.java

2) BluetoothHeadsetManager.java

Thanks,
Vipul

facebooktwittergoogle_plusredditpinterestlinkedinmailfacebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Using proximity sensor in Android App

Proximity Sensor in Android device is really helpful while building interactive applications, it can help you to add very good usability features in application.

For more technical details of proximity sensor and how it works check Wikipedia.

The main function of proximity sensor is to detect presence of nearby objects without any physical contact.

Now in many interactive apps it can be used like :

– Receive a call when user picks up the device and takes it near their ear
– Automate audio recording when user takes device near their ear
– Reject call when phone is placed upside down
– Turnoff screen when phone is in pocket
– Turnoff screen when phone is near ear to avoid accidental touches

We used this feature for our app to start playing a sound through earpiece when user takes device near their ear. It took some time to get it working so we thought to share the code so it can be helpful for others, you can use below code to get it working easily.

Usage : 
/**
 * Initial set Up of proximity sensor
 *  
 * It will call onPlay when device near to any object,
 * and will call onPause when device os moved far from the object
 */
private void setUpProximitySensor()
{
    if(mProximityController == null)
    {
        mProximityController = new ProximitySensorController(getApplicationContext()
        ,new onProximitySensorCallback() {
            
            @Override
            public void onSensorUnregister() 
            {
                Log.i(TAG,String.format("onSensorUnregister"));
            }
            
            @Override
            public void onSensorRegister() 
            {
                Log.i(TAG,String.format("onSensorRegister"));
            }
            
            @Override
            public void onPlay() 
            {
                onPlayPauseCall(false);
            }
            
            @Override
            public void onPause() 
            {
                onPlayPauseCall(true);
            }
            
            @Override
            public void onError(int errorCode, String message) 
            {
                Log.e(TAG,String.format("onError() : %2s", message));
            }
        });
        
        //start register here
        registerProximitySensor();
    }
}


/**
 * register the proximity sensor using proximity controller
 */
private void registerProximitySensor()
{
    if(mProximityController != null)
    {
        mProximityController.registerListener();
    }
}

/**
 * Unregister the proximity sensor using proximity controller
 */ 
private void unregisterProximitySensor()
{
    if(mProximityController != null)
    {
        mProximityController.unregisterListener();
    }
}

You will need these 2 files (find them in zip) for this code to work, import them in your project, change package name to match your project’s and use above code.

ProximitySensorAPI.zip

1) ProximitySensorController.java

2) ProximitySensorManager.java

Follow android developers guide for Proximity Sensor here : Position Sensors | Android Developers

Thanks,
Vipul

facebooktwittergoogle_plusredditpinterestlinkedinmailfacebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Color Sense – Live on Google Play

Smart Screen Filter

Description :

Color Sense allows you to color part of your photo while leaving the rest black and white. This is the add supported free version. Please support us by upgrading to the ad free version.

Screenshots :

Splash Screen

Splash Screen

Options

Options

Main UI

Main UI

It has 2 versions, one free with ads and another paid without ads.

Paid version is here : https://play.google.com/store/apps/details?id=com.numersoft.colorsensepro

facebooktwittergoogle_plusredditpinterestlinkedinmailfacebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Smart Screen Filter

Smart Screen Filter

Easy to use Screen Filter :

Ever felt the brightness of your device is still harsh while reading a book or watching a movie, and wanted to control screen appearance based on your need, you can do that now with easy to use “Smart Screen Filter”

Our screen filter is applied to notification area as well as the soft key buttons area (on android 4.4 and supported apps only), it will help you to disable soft key backlight on some phones (its experimental feature)

– Just open the app, enable it and select overlay color
– You can change the trigger area on screen to be Top-Left or Top-Right, when you change setting you will see the trigger area highlighted
– When swiping in on that section, you will get the filter level slider, you can change filter level from anywhere on any application
– It works on landscape and portrait modes even with fullscreen apps.
– You can open settings of app by clicking app notification on notification drawer
– You can easily disable filter by setting level to 0, if you want to close the app, just click the close icon on notification drawer.

Screenshots :

facebooktwittergoogle_plusredditpinterestlinkedinmailfacebooktwittergoogle_plusredditpinterestlinkedinmailby feather

MiniMap – jQuery Plugin

MiniMap – jQuery Plugin

It will help you to visualize content you want to highlight in your long page or a panel on a MiniMap

MiniMap jQuery Plugin

MiniMap jQuery Plugin

Requires :

jquery-1.7.2.min.js (older versions should also work)
simpleMinimap.jquery.js (5KB)
jquery.scrollTo-1.4.2-min.jquery.js (2KB)
vtip.js (1KB) – Optional, to show content of marker line in tooltip
simpleMinimap.css (few bytes)

Javascript :

<script type="text/javascript">// <![CDATA[
$(document).ready(function(){
        var minimap = $("#logPanel").simpleMiniMap({
            afterBuildMap : function(elem, map)
            {
                vtip(map); //Only if vtip is added and you want to show tooltip on markers
            }
        });
        minimap.buildMap(); //This builds markers and shows, every time when you update content of the element and want to reload markers, call this method.
    });
// ]]></script>

Options :

$.simpleMiniMap.defaultOptions = {
    filterElem : ".highlight", //Can be filtered by any possible jquery selector
    showScrollButtons : true, //To show/hide scroll to top/bottom buttons
    noTitleOnMarker : false, //No title/tooltip for markers
    titleBuilder : false, //If you want to customize title of marker, this is function, function(marker)
    beforeBuildMap : false, //method to call before building maf, function(mainElement, miniMapWrapper)
    afterBuildMap : false, //method to call after building maf, function(mainElement, miniMapWrapper)
    markerCSSClass : "marker", //CSS class for marker on minimap
    highlightBGColor : "#574E4E", //After scrolling to marker reference it highlights the parent item of it, this color will be used to highlight(as background color)
    highlightItemDuration : 1000 //0 will disable highlighting, duration of animation
};

Live Demo :

http://www.labs.urvatechlabs.com/miniMap/

Download :

http://www.labs.urvatechlabs.com/miniMap/demo.zip

Disclaimer :  This is the first, untested version, it requires specific ordered/styled HTML to generate map properly and has very minimal options right now. I may improvise this code as I get time, but it is usable if followed same HTML/CSS as this page. You can send me your queries or issues at vipul[dot]limbachiya[at] gmail (format to valid email address).

Licence : You can use it as you own it! (Licence for other libraries stays as they have defined.)

facebooktwittergoogle_plusredditpinterestlinkedinmailfacebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Smart Floating Clock – Android App from Urva TechLabs

Smart Floating Clock Logo Full

Smart Floating Clock

Smart Floating Clock is now available on Google Play Store :

https://play.google.com/store/apps/details?id=com.UrvaTechLabs.SmartFloatingClock

It’s Smart because the Clock stays on top, still you can click through it!

Features :

– A text only clock stays always on top, floating
– When its set to not moveable, you can click through it.
– Text size, color and position can be customized
– You can select to show AM/PM
– You can select 24 Hrs or 12Hrs format
– Date can be visible or hidden
– Date color and format can be changed, we have many date format options available
– Automagically manages its position in landscape and portrait modes.
– You can open settings, toggle clock mode to make it moveable or not or close the clock directly from notification
– Ongoing notification is must to keep the clock alive, if you disable it, clock will be closed anytime.
– If you messed up the position of the clock or want to reset your changes, just click on reset all settings!

Screenshots :

 

facebooktwittergoogle_plusredditpinterestlinkedinmailfacebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Smart Expense Tracker – First Android app from Urva TechLabs

Smart Expense Tracker - Free

Hi All,

Here we are launching our first android application, its live on Google Play Store :

https://play.google.com/store/apps/details?id=com.UTL.smartExpenseTracker

What it does :

– Almost every Indian bank and credit card services send transaction details to customers phone as an SMS, so we tried to help you to track expense through parsing those messages.

– However its not limited to track expenses only through SMS, you can add expenses as much as you can.

– So dont get confused at the end of the month calculating which thing covered most of your budget, just use “Smart Expense Tracker” without paying anything.

Dashboard

– Dashboard helps you to manage everything on single page, you can add expense, manage categories, manage SMS parsing and see history of your expenses.

– On Dashboard, Expense quick view panel displays expenses per categories, you can select period of days to see expenses only for that period.

Add Expense

Adding expense to “Smart Expense Tracker” is really easy :

– Add your amount
– Add optional notes for your expense (we recommend you add, as it will help you to recollect why the expense was made)
– You can change date and time for the expense, default time will be current time of device
– Select a category for your expense
– And save!

Expense History

– The History page will help you to scrutinize your expenses
– By default you see expenses made “Today”, you can change the period of expenses, using custom mode you can see maximum 60 days expenses on this page
– You can group expenses by category or date
– We have beautiful graphs to visualize your expenses, each category will have their own color code
– By tapping on any expense entry, you can see more details of that expense, you can edit and remove expense from the same details panel.
– If the expense entry was made with SMS parsing, you can see the SMS content from details panel too.

SMS Parsing

– SMS Parsing simplified : You can restrict the app from parsing every SMS you receive, you can use either SMS Templates or more smarter Hot Words. So it will ask you to add expense only the SMS content matches the template and/or hotwords.

– You can enable or disable all or particular hotwords or templates parsing at any point of time.

Hot Words :

– When SMS is received and it contains any of the Hot Words added to the application, it will try parsing the content, and if any amount is found in text, it will ask you to save this to “Smart Expense Tracker”

Templates :

– Templates are very helpful to parse messages perfectly, we will not guess the amount from SMS, but it will have exact amount, so you just have to press “Save” when “Smart Expense Tracker” asks you to save expense.

If your XYZ bank sends you transaction message in this format :

Your a/c 00000000 is debited Rs 10000 on 2014-02-04 A/c balance is Rs 100000.00 Info: Payment Through Online Gateway

Just replace the amount with “@@” and its ready to go :

Your a/c 00000000 is debited Rs
@@ on 2014-02-04 A/c balance is Rs 100000.00 Info: Payment Through Online Gateway

So when you receive next message from bank :

Your a/c 00000000 is debited Rs 1234.56 on 2014-02-04 A/c balance is Rs 98765.44 Info: Payment Through Online Gateway

“Smart Expense Tracker” will ask you to save expense like :

SMS Popup

SMS Popup

Categories

– Its not much smart if you can not categorize your expenses, just storing expenses might be not much helpful, so we have easy to manage categories.
– You can add as many categories as you want, color code them to easily identify
– You can change category name and color at any time and it will be reflected everywhere
– We have smart category removal
– Inactive categories will no longer be shown while adding or editing an expense

Backup & Restore

– We change devices, just to upgrade or its necessary sometimes, so we have smart Backup & Restore facility to help you never lose your old entries in “Smart Expense Tracker”
– You can Export everything from your “Smart Expense Tracker” and Import it to another device
– While importing you can select to “Merge with Current Data” or “Delete Current Data”, Merging is smart feature, you will not end up with duplicate entries
– You can keep backing up your data and transfer it to safe location so you never lose any records. In future we will provide server sync

Other Features

– You can select currency from our limited list for now : INR, USD, EUR, GBP, RM, AUD, CAD We will add more currency support in next release
– You can use beautiful widget on your homescreen, so you can quickly review your expenses and easily add expense directly from your homescreen!
– No ads, no annoying advertising popups and no suspicious permissions!! We require only these permissions :

 

Permissions

Permissions

Privacy and Terms Of Use

– “Smart Expense Tracker” is free to use, you don’t need to pay anyone anything to use this application.
– We never send your usage, SMS or any other information to anywhere, everything you store using this application stays on your device, unless you intentionally send backup file to someone or any service, but
“Smart Expense Tracker” never does that with or without your knowledge.
– “Smart Expense Tracker” is available with as-is basis, we are not responsible for any data, information loss, or anything which can harm you or your device by using this application in any way

 

Credits

Beautiful Graphs

https://bitbucket.org/danielnadeau/holographlibrary/

Color Picker

https://github.com/attenzione/android-ColorPickerPreference/

Typography

https://github.com/Bearded-Hen/Android-Bootstrap/wiki/Font-Awesome-Text/

facebooktwittergoogle_plusredditpinterestlinkedinmailfacebooktwittergoogle_plusredditpinterestlinkedinmailby feather