How To Have Multiple Launcher Icons In One Android APK Install For Different Activities

If you’ve ever installed Facebook from the Google Play store and noticed it adds 2 launcher icons (Facebook and Fb Chat) and wondered how they do this (have multiple launcher icons in one install bound to different activities) here is how to achieve this.

Step 1) For each activity you wish to expose an icon for in your Android app, add a corresponding “android:icon” attribute to your in AndroidManifest.xml:

android:icon="@drawable/power_saver_settings_app_icon"

Step 2) The key to getting this working is also adding an “android:taskAffinity” attribute with a unique value for each activity. Note that in the example below I just used the fully qualified package name + activity name. You can use any value you want here though:

android:taskAffinity="com.logicvoid.androidadvancedsettings.PowerSaverSettingsActivity"

Something to note is that the icon you define in the application section of AndroidManifest.xml (<application android:icon="@drawable/app_icon"..) will NOT be visible in the launcher, however it is still important to include as the Google Play store consumes this asset and will display it representing your application.

Complete AndroidManifest.xml:

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

    <uses-sdk android:minSdkVersion="15" />
    

    <application
        android:icon="@drawable/app_icon"
        android:label="@string/app_name" >
        
        <activity            
            android:icon="@drawable/power_saver_settings_app_icon"
            android:name=".PowerSaverSettingsActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"
            android:label="@string/power_saver_settings_launcher_name" 
            android:taskAffinity="com.logicvoid.androidadvancedsettings.PowerSaverSettingsActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <activity            
            android:icon="@drawable/roaming_guard_settings_app_icon"
            android:name=".RoamingGuardsSettingsActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"
            android:label="@string/roaming_guards_settings_launcher_name"
            android:taskAffinity="com.logicvoid.androidadvancedsettings.RoamingGuardsSettingsActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Advertisements

Launch Activity/Service On Android Boot

OnBootReceiver.java

package com.logicvoid.voguetools;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

public  class OnBootReceiver extends  BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
         if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
              Log.d("VogueTools", "Got the Boot Event>>>");
              // do your stuff for example, start a background service directly
              // here
              Toast.makeText(context, "Testing From VogueTools", Toast.LENGTH_LONG).show();

         }
    }
}

manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.logicvoid.voguetools"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".MainActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

		<!--   Handling for On Boot Receiver -->
		 <receiver android:name=".OnBootReceiver"  android:enabled="true"  android:exported="false"  android:label="OnBootReceiver">
		    <intent-filter>
		        <action android:name="android.intent.action.BOOT_COMPLETED" />
		    </intent-filter>
		</receiver>
		 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
		<!-- End Handling for On Boot Receiver -->

    </application>
    <uses-sdk android:minSdkVersion="4" />

</manifest>

For reference. the Context passed in the onReceive is that of the Application, not a specific Activity.

If you’re doing anything that is context sensitive like dealing with preferences in your application, perhaps using appContext.getSharedPreferences. Use getApplicationContext() within your application to ensure the preferences will be read from both the BroadcastReceiver onReceive and the application itself. As the onReceive Context is that of the application, they will be equal.

Easily Remove /r and /n Chars From MultiLine Literal XML String

protected string CreateInfoRequestPackage()
    {

        string RequestPackage = "<inforequest ID=\"90210\">";
        RequestPackage += @"       
       <UserData>
      <salutation>Mr.</salutation> 
      <fname>John</fname> 
      <lname>Doe</lname> 
      <title>Sr Manager</title> 
      <institution>Acme Inc</institution> 
      <addr1>100 Main St</addr1> 
      <addr2>Suite 12</addr2> 
      <city>Anytown</city> 
      <state>MA</state> 
      <zip>02110</zip> 
      <country>USA</country> 
      <telephone>617-603-7000</telephone> 
      <fax>617-603-7001</fax> 
      <email>test@test.com</email> 
      <investor_type>2</investor_type> 
      <carrier>FEX*PO</carrier> 
      <shipment_account>12345531</shipment_account> 
      <comment>Send ASAP</comment> 
      </UserData>
     <Materials>
     <Material>
      <material_id>3434222</material_id> 
      <qty>1</qty> 
      </Material>
     <Material>
      <material_id>2342344</material_id> 
      <qty>1</qty> 
      </Material>
      </Materials>
      </inforequest>";



        // Using the data above create well formed XML (removing the /r /n)
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.LoadXml(RequestPackage);
        return xmlDoc.InnerXml;


        

    }

How To Bind Custom Object To Build Dynamic CheckBoxList

ASPX Page

<%@ Page Language="C#" AutoEventWireup="true" %>

<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Text" %>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="InvestorDataFeedTest" %>

<script runat="server">
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        
        if (!IsPostBack)
        {
            
            CBMaterialItems.DataSource = PrintedMaterialLogic.GetPrintedMaterialCBDataTable();
            CBMaterialItems.DataValueField = "MaterialID";
            CBMaterialItems.DataTextField = "MaterialName";
            CBMaterialItems.DataBind();

        }
        

    }

  
</script>

<html>
<head id="Head1" runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:CheckBoxList ID="CBMaterialItems" runat="server" AutoPostBack="True" />
    </div>
    </form>
</body>
</html>

PrintedMaterialLogic.cs

using System;
using System.Collections.Generic;
using System.Web;

using System.Web.UI;
using System.Xml;
using System.Data;
using System.Reflection;
using System.Net;
using System.IO;
using System.Collections.Specialized;

namespace InvestorDataFeedTest
{
    public class PrintedMaterialLogic
    {

        public PrintedMaterialLogic() { }


        // Public Methods (Business Logic Layer)
        #region public static DataTable GetPrintedMaterialCBDataTable()
        //[DataObjectMethod(DataObjectMethodType.Select)]
        public static DataTable GetPrintedMaterialCBDataTable()
        {

            // Create an object to return
            DataTable datatable = new DataTable();

            try
            {
                List<PrintedMaterialData> entireList = new List<PrintedMaterialData>();

                entireList = GetPrintedMaterialCBData();

                datatable = ListToDataTable(entireList);
            }
            catch (Exception ex)
            {
                // Send error email
                BLL.SendErrorEmail("Get Printed Material CheckBox DataTable Error", "", ex);
            }


            return datatable;

        }
        #endregion    







        // Private Methods (Data Access Layer)
        #region public static List<PrintedMaterialData> GetPrintedMaterialCBData()
        public static List<PrintedMaterialData> GetPrintedMaterialCBData()
        {
            // Create object to return
            List<PrintedMaterialData> list = new List<PrintedMaterialData>();

            // Check cache for value first           
            Page page = (Page)HttpContext.Current.CurrentHandler;
            string cacheKey = "GetPrintedMaterialCBData";

            if (page.Cache[cacheKey] != null)
            {
                // Return cached value if it exists
                return (List<PrintedMaterialData>)page.Cache[cacheKey];
            }
            else
            {
                
                // Fill cache



                // Get XML
                string url = "http://xml.site.net/irxmlclient.asp?compid=343432&reqtype=informationrequest";
                string data = GetScreenScrape(url);

                XmlDocument xmlDoc = new XmlDocument();              
                xmlDoc.LoadXml(data);              


                // Get nodes
                XmlNodeList xmlNodes = xmlDoc.DocumentElement.SelectNodes("/IRXML/InformationRequest/InfoRequestMaterials/InfoRequestMaterial");
                // For each xml node, create the corresponding objects
                foreach (XmlNode xmlNode in xmlNodes)
                {

                    XmlElement elt = (XmlElement)xmlNode;

                    PrintedMaterialData node = PrintedMaterialCBDataCreate(xmlNode);

                    // If node was created, then add to our list
                    if (node != null) { list.Add(node); }
                }
            }


            return list;


        }
        #endregion
        #region public static PrintedMaterialData PrintedMaterialCBDataCreate(XmlNode xmlNode)
        public static PrintedMaterialData PrintedMaterialCBDataCreate(XmlNode xmlNode)
        {
            // Create an object to return
            PrintedMaterialData item = new PrintedMaterialData();

            if (xmlNode != null)
            {
                
                XmlNode materialNameNode = xmlNode.SelectSingleNode("MaterialName");                   
                XmlAttribute materialIDAttribute = xmlNode.Attributes["MaterialID"];

                item.MaterialName = (materialNameNode == null) ? "" : materialNameNode.InnerText.Trim();
                item.MaterialID = (materialIDAttribute == null) ? "" : materialIDAttribute.InnerText.Trim();     

                
                return item;
            }

            return null;
        }
        #endregion



        




        // Methods / Functions already in .COM Solution
        #region public static string GetScreenScrape(string url)
        public static string GetScreenScrape(string url)
        {
            // Create the WebRequest for the URL we are using
            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);
            req.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)";
            // Get the stream from the returned web response
            StreamReader stream = new StreamReader(req.GetResponse().GetResponseStream());

            //experiment try reading entire thing at once
            string html = stream.ReadToEnd();


            // Finished with the stream so close it now
            stream.Close();

            return html;

        }
        #endregion
        #region private static DataTable ListToDataTable<T>(List<T> list)
        private static DataTable ListToDataTable<T>(List<T> list)
        {
            DataTable dt = new DataTable();

            foreach (PropertyInfo info in typeof(T).GetProperties())
            {
                dt.Columns.Add(new DataColumn(info.Name, info.PropertyType));
            }
            foreach (T t in list)
            {
                DataRow row = dt.NewRow();
                foreach (PropertyInfo info in typeof(T).GetProperties())
                {
                    row[info.Name] = info.GetValue(t, null);
                }
                dt.Rows.Add(row);
            }
            return dt;
        }
        #endregion




    }
}

Rendering XML formated as HTML using XSLT

Source XML with HTML formatted text inside

<Wizard.com_filing version="2.1">
−
<FILING_INFO>
<NAME>DEREK REYNOLDS CO</NAME>
<FILER>DEREK REYNOLDS CO</FILER>
<DATE_FILED>20070731</DATE_FILED>
<FORM>15-12G</FORM>
<SIZE>17.1 KB</SIZE>
<PAGES>1</PAGES>
</FILING_INFO>
−
<FILING view="Entire">
−
<DOCUMENT type="HTML" number="1">
<html>
  
  <head>
    <title>tncform15.htm</title>
</head>
  <body bgcolor="#ffffff"><br>
    <div style="DISPLAY: block; MARGIN-LEFT: 0pt; TEXT-INDENT: 0pt; MARGIN-RIGHT: 0pt" align="center"><font style="DISPLAY: inline; FONT-SIZE: 12pt; FONT-FAMILY: Times New Roman;"><strong>UNITED
      STATES</strong></font></div>
    <div style="DISPLAY: block; MARGIN-LEFT: 0pt; TEXT-INDENT: 0pt; MARGIN-RIGHT: 0pt" align="center"><font style="DISPLAY: inline; FONT-SIZE: 12pt; FONT-FAMILY: Times New Roman;"><strong>SECURITIES
      AND EXCHANGE COMMISSION</strong></font></div>
    <div style="DISPLAY: block; MARGIN-LEFT: 0pt; TEXT-INDENT: 0pt; MARGIN-RIGHT: 0pt" align="center"><font style="DISPLAY: inline; FONT-SIZE: 12pt; FONT-FAMILY: Times New Roman;"><strong>WASHINGTON,
      D.C. 20549</strong></font></div>
    <div><br></div>
    <div style="DISPLAY: block; MARGIN-LEFT: 0pt; TEXT-INDENT: 0pt; MARGIN-RIGHT: 0pt" align="justify"> </div>
    <div style="DISPLAY: block; MARGIN-LEFT: 0pt; TEXT-INDENT: 0pt; MARGIN-RIGHT: 0pt" align="center"><font style="DISPLAY: inline; FONT-SIZE: 12pt; FONT-FAMILY: Times New Roman;"><strong>FORM
      15</strong></font></div>
    <div><br></div>
    <div style="DISPLAY: block; MARGIN-LEFT: 0pt; TEXT-INDENT: 0pt; MARGIN-RIGHT: 0pt" align="justify"><font style="DISPLAY: inline; FONT-SIZE: 12pt; FONT-FAMILY: Times New Roman;">CERTIFICATION
      AND NOTICE OF TERMINATION OF REGISTRATION UNDER SECTION 12(g) OF THE SECURITIES
      EXCHANGE ACT OF 1934 OR SUSPENSION OF DUTY TO FILE REPORTS UNDER SECTIONS 13
      AND 
      15(d) OF THE SECURITIES EXCHANGE ACT OF 1934.</font></div>
...
..
.

XSLT filtering out only the DOCUMENT portion containing the HTML (HTMLView.xslt)
Note: disable-output-escaping=”yes” is required, otherwise the HTML markup will not be rendered in browser. If you exclude this the output will just be the HTML source.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <xsl:value-of select="/Wizard.com_filing/FILING/DOCUMENT"  disable-output-escaping="yes"/>
  </xsl:template>
</xsl:stylesheet>

ASP.NET code to transform XML using XSLT



<script runat="server">
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        string xmlUrl = "http://ccbn.10kwizard.com/xml/filing.xml?repo=tenk&ipage=5076639&attach=ON&sXBRL=1";
       

        xmlOutput.DocumentContent = RetrieveXML(xmlUrl);

        xmlOutput.TransformSource = Server.MapPath("HTMLView.xslt");


       

    }

   

    private static string RetrieveXML(string url)
    {
        // Create the WebRequest for the URL we are using
        HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);
        req.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)";

        // Get the stream from the returned web response
        StreamReader stream = new StreamReader(req.GetResponse().GetResponseStream());

        //experiment try reading entire thing at once
        string html = stream.ReadToEnd();

        // Finished with the stream so close it now
        stream.Close();

        return html;

    }

    
    


</script>

<html>
<head id="Head1" runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Xml ID="xmlOutput" runat="server" Visible="true"></asp:Xml>      
    </div>
    </form>
</body>
</html>

XPath Pattern Using XmlNode and XmlAttribute

XML Source (/lib/data/Quotes/Quotes.xml)

<?xml version="1.0" standalone="no"?>
<IRXML CorpMasterID="105011">
  <StockQuotes PubDate="20100125" PubTime="08:58:06">
    <Stock_Quote PrimaryTicker="Yes" DisplayInDropdown="Yes" SecurityID="27714" Company="Derek Reynolds INC" Ticker="DRR" DisplayTicker="DRR" Exchange="NYSE" Currency="US Dollar" CurrencyLabel="$" CurrencyLabelSuffix="" Type="COMPANY" Class="Common Stock" FirstTradeDate="" FinancialStatusIndicator="">
      <Date Date="20100122" Time="16:00:00">Jan 22 2010  4:00PM</Date>
      <Trade>35.42</Trade>
      <Change>-0.69</Change>
      <Bid>35.42</Bid>
      <Ask>35.43</Ask>
      <DataProviderInfo>
        <DataProvider>
          <Name>MarketWatch</Name>
          <Key>DRR</Key>
        </DataProvider>
        <DataProvider>
          <Name>ThomsonChart</Name>
          <Key>DRR;DRR;DRR</Key>
        </DataProvider>
      </DataProviderInfo>
    </Stock_Quote>
  </StockQuotes>
</IRXML>

C# Code:

using System.Xml;

        // Get XML
        string xmlPath = HttpContext.Current.Server.MapPath("/lib/data/Quotes/Quotes.xml");

        // XML Reader
        XmlTextReader xtr = new XmlTextReader(xmlPath);
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load(xtr);

        // Close reader
        xtr.Close();

        // Get nodes / attributes
        XmlNode stockRow = xmlDoc.SelectSingleNode("/IRXML/StockQuotes/Stock_Quote");
        XmlNode askNode = stockRow.SelectSingleNode("Ask");
        XmlNode bidNode = stockRow.SelectSingleNode("Bid");
        XmlAttribute tickerAttribute = stockRow.Attributes["Ticker"];
        XmlAttribute exchangeAttribute = stockRow.Attributes["Exchange"];

        // Format values from node/attributes
        string ask = (askNode == null) ? "" : askNode.InnerText;
        string bid = (bidNode == null) ? "" : bidNode.InnerText;
        string ticker = (tickerAttribute == null) ? "" : tickerAttribute.InnerText;
        string exchange = (exchangeAttribute == null) ? "" : exchangeAttribute.InnerText;

Another example using sub-selects within the first select node

<?xml version="1.0"  encoding="ISO-8859-1"?>
<Wizard.com_results version="2.1">
  <Hitlist total="332">
    <HIT>
      <COMPANY_PROFILE>
        <SYMBOL>DRR</SYMBOL>
        <CIK>1234</CIK>
        <NAME>DEREK REYNOLDS CO</NAME>
      </COMPANY_PROFILE>
      <FILING_INFO size="11.96 MB" pages="79">
        <FILING_ID>6575040</FILING_ID>
        <ISSUER></ISSUER>
        <FORM>10-Q</FORM>
        <FORM_DESC>Quarterly report which provides a continuing view of a company&apos;s financial position</FORM_DESC>
        <FORM_GROUP>10K,10Q,8K,6K,DEF14</FORM_GROUP>
        <DATE_FILED>20091030</DATE_FILED>
        <HTML_LINK>http://ccbn.10kwizard.com/xml/contents.xml?ipage=6575040&amp;repo=tenk&amp;sXBRL=1</HTML_LINK>
        <DOC_LINK>http://ccbn.10kwizard.com/xml/download.php?format=RTF&amp;ipage=6575040&amp;sXBRL=1</DOC_LINK>
        <PDF_LINK>http://ccbn.10kwizard.com/xml/download.php?format=PDF&amp;ipage=6575040&amp;sXBRL=1</PDF_LINK>
        <XLS_LINK>http://ccbn.10kwizard.com/xml/download.php?format=XLS&amp;ipage=6575040</XLS_LINK>
        <XBRL_LINK></XBRL_LINK>
        <MDA_LINK></MDA_LINK>
      </FILING_INFO>
    </HIT>

Code that enumerates through base XPATH


            // Get XML
            string xmlPath = HttpContext.Current.Server.MapPath(feedPath);

            XmlTextReader xtr = new XmlTextReader(xmlPath);
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(xtr);
            // Close reader
            xtr.Close();

            // Get nodes
            XmlNodeList xmlNodes = xmlDoc.DocumentElement.SelectNodes("//Wizard.com_results/Hitlist/HIT");
            // For each xml node, create the corresponding objects
            foreach (XmlNode xmlNode in xmlNodes)
            {

                XmlElement elt = (XmlElement)xmlNode;

                InvestorFilingData node = InvestorFilingDataCreate(xmlNode);

                // If node was created, then add to our list
                if (node != null) { list.Add(node); }
            }

InvestorFilingData method that digs deeper from base node to extract different values from it’s limbs.

 public static InvestorFilingData InvestorFilingDataCreate(XmlNode xmlNode)
    {
        // Create an object to return
        InvestorFilingData item = new InvestorFilingData();

        if (xmlNode != null)
        {

            XmlNode dateFiledNode = xmlNode.SelectSingleNode("FILING_INFO/DATE_FILED");
            XmlNode filingNode = xmlNode.SelectSingleNode("FILING_INFO/FORM");
            XmlNode companyNode = xmlNode.SelectSingleNode("COMPANY_PROFILE/NAME");  
            XmlNode htmlURLNode = xmlNode.SelectSingleNode("FILING_INFO/HTML_LINK");
            XmlNode docURLNode = xmlNode.SelectSingleNode("FILING_INFO/DOC_LINK");
            XmlNode pdfURLNode = xmlNode.SelectSingleNode("FILING_INFO/PDF_LINK");
            XmlNode xlsURLNode = xmlNode.SelectSingleNode("FILING_INFO/XLS_LINK");

            // Size is located in the attributes of FILING_INFO so select this node before 
            // extracting the size attribute
            XmlNode sizeNode = xmlNode.SelectSingleNode("FILING_INFO");
            XmlAttribute sizeAttribute = sizeNode.Attributes["size"];
            
            

            
            // convert the yyyyMMdd format in the XML into a DateTime object     
            item.DateFiled = (dateFiledNode == null) ? DateTime.MinValue :
                System.DateTime.ParseExact(dateFiledNode.InnerText.Trim(), "yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture);            
          
            item.Filing = (filingNode == null) ? "" : filingNode.InnerText.Trim();
            item.CompanyName = (companyNode == null) ? "" : companyNode.InnerText.Trim();
            item.HTMLURL = (htmlURLNode == null) ? "" : htmlURLNode.InnerText.Trim();
            item.DocURL = (docURLNode == null) ? "" : docURLNode.InnerText.Trim();
            item.PDFURL = (pdfURLNode == null) ? "" : pdfURLNode.InnerText.Trim();
            item.XLSURL = (xlsURLNode == null) ? "" : xlsURLNode.InnerText.Trim();
            item.Size = (sizeAttribute == null) ? "" : sizeAttribute.InnerText.Trim();


            return item;
        }

        return null;
    }