Create categories so that Hybrid Apps and messages appear in lists under a category heading.
The comment tag associated with creating categorized views is ANDROID_CUSTOMIZATION_POINT_CATEGORIZEDVIEWS.
First, determine names for the categories. SAP recommends that you name the final category “Miscellaneous;” this adds all applications and messages that do not match a category to the Miscellaneous category. Also in this example, all applications that belong to a category must include the category name contained in their display name. For example, an application named “Financial Claim” belongs in the “Financial” category.
There are other ways to determine categories; if you know the names of the applications in advance, you can simply list all the application names that belong in each category.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="?android:attr/listPreferredItemHeight" android:padding="6dip"> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="0dip" android:layout_weight="1" android:layout_height="fill_parent"> <TextView android:id="@+id/category" android:layout_width="fill_parent" android:layout_height="0dip" android:layout_weight="1" android:singleLine="true" android:ellipsize="marquee" android:gravity="center_vertical" /> </LinearLayout> </LinearLayout>
public static final String[] m_asHybridAppCategories = { "Financial", "Utilities", "Miscellaneous" };
private class HybridAppAdapter extends ArrayAdapter<Object>
{
private String[] m_asCategories;
public HybridAppAdapter( Context context, int textviewResourceId, List<Object> items, String[] categories ){
super( context, textviewResourceId, items );
m_asCategories = categories;
for( int index = 0; index < m_asCategories.length; index++ )
{
this.add( m_asCategories[index] );
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
Object oObject = this.getItem(position);
View v = null;
if( oObject instanceof HybridApp )
{
HybridApp oHybridApp = ( HybridApp ) oObject;
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.workflows, null);
if ( oHybridApp != null )
{
ImageView ic = (ImageView) v.findViewById( R.id.workflow_icon );
ic.setImageResource( UiIconIndexLookup.getNormalIconIdForIndex( oHybridApp.getIconIndex() ));
TextView tt = (TextView) v.findViewById(R.id.workflow_title);
if (tt != null) {
tt.setText( oHybridApp.getDisplayName());
}
}
}
else
{ //This position is not a HybridApp, but a category heading
String sString = ( String ) oObject;
LayoutInflater vi = ( LayoutInflater ) getSystemService( Context.LAYOUT_INFLATER_SERVICE );
v = vi.inflate( R.layout.category, null );
if( sString != null )
{
TextView tt = (TextView) v.findViewById( R.id.category );
if ( tt != null )
{
tt.setText( sString );
}
}
}
return v;
}
public void remove( HybridApp oApp )
{
// The object to remove has a different pointer
// so match it up with the one in the list
for ( int i = 0; i < this.getCount(); i++ )
{
Object oObject = getItem( i );
if( oObject instanceof HybridApp )
{
HybridApp oTemp = ( HybridApp ) oObject;
if ( oApp.getModuleId() == oTemp.getModuleId()
&& oApp.getVersion() == oTemp.getVersion() )
{
super.remove( oTemp );
return;
}
}
}
}
public void sort()
{
// Sorts applications by name
this.sort( new Comparator<Object>()
{
@Override
public int compare( Object oObject1, Object oObject2 )
{
if( oObject1 instanceof String && oObject2 instanceof String)
{
String sString1 = ( String ) oObject1;
String sString2 = ( String ) oObject2;
for( int index = 0; index < m_asCategories.length; index++ )
{
if( sString1.equals( m_asCategories[index] ) )
{
return -1;
}
if( sString2.equals( m_asCategories[index]) )
{
return 1;
}
}
}
else if( oObject1 instanceof HybridApp && oObject2 instanceof HybridApp )
{
HybridApp oHybridApp1 = ( HybridApp ) oObject1;
HybridApp oHybridApp2 = ( HybridApp ) oObject2;
int iCategoryIndex1 = getCategoryIndex( oHybridApp1 );
int iCategoryIndex2 = getCategoryIndex( oHybridApp2 );
if( iCategoryIndex1 == iCategoryIndex2 )
{
return oHybridApp1.getDisplayName().toLowerCase().compareTo( oHybridApp2.getDisplayName().toLowerCase() );
}
else
{
return iCategoryIndex1 - iCategoryIndex2;
}
}
else
{ //we have one String (category heading) and one HybridApp
HybridApp oHybridApp = null;
String sString = null;
int iSwitch = 1;
if( oObject1 instanceof HybridApp)
{
oHybridApp = ( HybridApp ) oObject1;
sString = ( String ) oObject2;
}
else
{
oHybridApp = ( HybridApp ) oObject2;
sString = ( String ) oObject1;
iSwitch = -1;
}
int iHybridAppCategoryIndex = getCategoryIndex( oHybridApp );
int iCategoryIndex = getCategoryIndex( sString );
if( iCategoryIndex <= iHybridAppCategoryIndex )
{
return 1*iSwitch;
}
else
{
return -1*iSwitch;
}
}
return 0;
}
private int getCategoryIndex( String sString )
{
for( int index = 0; index < m_asCategories.length; index++ )
{
if( m_asCategories[index].equalsIgnoreCase( sString ) )
{
return index;
}
}
return m_asCategories.length - 1;
}
private int getCategoryIndex( HybridApp oHybridApp )
{
for( int index = 0; index < m_asCategories.length; index++ )
{
if( oHybridApp.getDisplayName().toLowerCase().indexOf( m_asCategories[index].toLowerCase() ) >= 0 )
{
return index;
}
}
return m_asCategories.length - 1;
}
});
}
}
this.m_adapter = new HybridAppAdapter( this, R.layout.workflows, new ArrayList<Object>(Arrays.asList( HybridAppDb.getInvocableHybridApps() ) ), m_asHybridAppCategories );
public void onListItemClick(ListView oParent, View v, int iPos, long id )
{
Object oObject = m_adapter.getItem( iPos );
if( oObject instanceof HybridApp )
{
HybridApp oHybridApp = ( HybridApp ) oObject;
Intent oIntentHybridAppContainer = new Intent( this, UiHybridAppContainer.class );
oIntentHybridAppContainer.putExtra( Consts.INTENT_PARAM_HYBRIDAPP_START_MODE, Consts.START_MODE_HYBRIDAPP );
oIntentHybridAppContainer.putExtra( Consts.INTENT_PARAM_HYBRIDAPP_ID, ((HybridAppDb) oHybridApp).getHybridAppId() );
oIntentHybridAppContainer.putExtra( Consts.INTENT_PARAM_HYBRIDAPP_PROGRESS_TEXT, oHybridApp.getDisplayName() );
startActivityForResult( oIntentHybridAppContainer, Consts.INTENT_ID_HYBRIDAPP_CONTAINER );
}
}
public void onCreateContextMenu( ContextMenu oMenu, View v, ContextMenu.ContextMenuInfo menuInfo)
{
super.onCreateContextMenu( oMenu, v, menuInfo );
AdapterContextMenuInfo oInfo = (AdapterContextMenuInfo) menuInfo;
Object oObject = m_adapter.getItem( oInfo.position );
if( oObject instanceof Message )
{
Message oMsg = ( Message ) oObject;
oMenu.setHeaderTitle( oMsg.getSubject() );
oMenu.add( 0, CONTEXT_MENU_DELETE, 0, R.string.Context_Menu_Delete );
// Save the id for operations used in the context menu
m_iContextMessageId = oMsg.getMessageId();
}
}
public boolean onContextItemSelected( MenuItem oItem )
{
if ( oItem.getItemId() == CONTEXT_MENU_DELETE )
{
AdapterContextMenuInfo oInfo = (AdapterContextMenuInfo) oItem.getMenuInfo();
// The message might have been deleted while the context menu was open.
// Make sure the position is still present and matches the id we expect
if ( oInfo.position < m_adapter.getCount() )
{
Object oObject = m_adapter.getItem( oInfo.position );
if( oObject instanceof Message )
{
Message oMsg = ( Message ) oObject;
if ( oMsg.getMessageId() == m_iContextMessageId )
{
// Remove message from database
MessageDb.delete( oMsg.getMessageId() );
}
}
}
return true;
}
return false;
}
private class MessageAdapter extends ArrayAdapter<Object>
{
String[] m_asCategories;
public MessageAdapter( Context context, int textviewResourceId, ArrayList<Object> items, String[] categories ){
super( context, textviewResourceId, items );
m_asCategories = categories;
for( int index = 0; index < m_asCategories.length; index++ )
{
this.add( m_asCategories[index] );
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Object oObject = getItem( position );
View v = null;
if( oObject instanceof Message )
{
Message oMsg = (Message) oObject;
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.workflowmessages, null);
if ( oMsg != null )
{
//set the Hybrid App message priority icon
ImageView imageForPriority = (ImageView) v.findViewById( R.id.priority_icon );
if ( oMsg.getMailPriority() == AmpConsts.EMAIL_STATUS_IMPORTANCE_HIGH )
{
imageForPriority.setImageResource( R.drawable.readhi );
imageForPriority.setVisibility( View.VISIBLE );
}
else if ( oMsg.getMailPriority() == AmpConsts.EMAIL_STATUS_IMPORTANCE_LOW )
{
imageForPriority.setImageResource( R.drawable.readlow );
imageForPriority.setVisibility( View.VISIBLE );
}
else
imageForPriority.setVisibility( View.GONE );
ImageView ic = (ImageView) v.findViewById( R.id.msg_icon );
if ( oMsg.isMsgProcessed() )
ic.setImageResource( UiIconIndexLookup.getProcessedIconIdForIndex( oMsg.getIconIndex()));
else
ic.setImageResource( UiIconIndexLookup.getNormalIconIdForIndex( oMsg.getIconIndex()));
TextView tf = (TextView) v.findViewById(R.id.msg_from);
TextView tt = (TextView) v.findViewById(R.id.msg_title);
TextView bt = (TextView) v.findViewById(R.id.msg_datetime);
if ( tf != null ) {
tf.setText( oMsg.getMsgFrom() );
}
if (tt != null) {
tt.setText( oMsg.getSubject());
}
if(bt != null){
Calendar dtReceived = Calendar.getInstance();
dtReceived.setTime( oMsg.getReceivedDate() );
Calendar dtNow = Calendar.getInstance();
if ( dtNow.get( Calendar.YEAR ) == dtReceived.get( Calendar.YEAR ) &&
dtNow.get( Calendar.MONTH ) == dtReceived.get( Calendar.MONTH ) &&
dtNow.get( Calendar.DAY_OF_MONTH ) == dtReceived.get( Calendar.DAY_OF_MONTH ) )
{
bt.setText( ( new SimpleDateFormat( "hh:mm a" ) ).format( oMsg.getReceivedDate() ) );
}
else {
bt.setText( ( new SimpleDateFormat( "MM/dd/yy" ) ).format( oMsg.getReceivedDate() ) );
}
}
// Update appearance unread messages
if ( tf != null && tt != null && bt != null )
{
if ( !oMsg.isMsgRead() )
{
// Setup view for unread message
v.setBackgroundResource( R.drawable.unread_selector );
tf.setTextColor( Color.WHITE );
tf.setTypeface( null, Typeface.BOLD );
}
else
{
// Setup view for read message
v.setBackgroundResource( 0 );
TypedValue tv = new TypedValue();
getTheme().resolveAttribute( android.R.attr.textColorSecondary, tv, true );
tf.setTextColor( getResources().getColor( tv.resourceId ) );
tf.setTypeface( null, Typeface.NORMAL );
}
}
}
}
else
{
String sString = ( String ) oObject;
LayoutInflater vi = ( LayoutInflater ) getSystemService( Context.LAYOUT_INFLATER_SERVICE );
v = vi.inflate( R.layout.category, null );
if( sString != null )
{
TextView tt = (TextView) v.findViewById( R.id.category );
if ( tt != null )
{
tt.setText( sString );
}
}
}
return v;
}
public void sort()
{
// Sorts applications by name
this.sort( new Comparator<Object>()
{
@Override
public int compare( Object oObject1, Object oObject2 )
{
if( oObject1 instanceof String && oObject2 instanceof String)
{
String sString1 = ( String ) oObject1;
String sString2 = ( String ) oObject2;
for( int index = 0; index < m_asCategories.length; index++ )
{
if( sString1.equals( m_asCategories[index] ) )
{
return -1;
}
if( sString2.equals( m_asCategories[index]) )
{
return 1;
}
}
}
else if( oObject1 instanceof Message && oObject2 instanceof Message )
{
Message oMessage1 = ( Message ) oObject1;
Message oMessage2 = ( Message ) oObject2;
int iCategoryIndex1 = getCategoryIndex( oMessage1 );
int iCategoryIndex2 = getCategoryIndex( oMessage2 );
if( iCategoryIndex1 == iCategoryIndex2 )
{
return oMessage1.getReceivedDate().compareTo( oMessage2.getReceivedDate() );
}
else
{
return iCategoryIndex1 - iCategoryIndex2;
}
}
else
{ //we have one String (category heading) and one HybridApp
Message oMessage = null;
String sString = null;
int iSwitch = 1;
if( oObject1 instanceof Message)
{
oMessage = ( Message ) oObject1;
sString = ( String ) oObject2;
}
else
{
oMessage = ( Message ) oObject2;
sString = ( String ) oObject1;
iSwitch = -1;
}
int iMessageCategoryIndex = getCategoryIndex( oMessage );
int iCategoryIndex = getCategoryIndex( sString );
if( iCategoryIndex <= iMessageCategoryIndex )
{
return 1*iSwitch;
}
else
{
return -1*iSwitch;
}
}
return 0;
}
private int getCategoryIndex( String sString )
{
for( int index = 0; index < m_asCategories.length; index++ )
{
if( m_asCategories[index].equalsIgnoreCase( sString ) )
{
return index;
}
}
return m_asCategories.length - 1;
}
private int getCategoryIndex( Message oMessage )
{
MessageDb oMessageDb = (MessageDb) oMessage;
if( oMessageDb != null )
{
HybridApp oHybridApp = HybridAppDb.getHybridApp(oMessage.getModuleId(), oMessage.getModuleVersion());
String sModuleName = oHybridApp.getDisplayName();
if( sModuleName != null )
{
for( int index = 0; index < m_asCategories.length; index++ )
{
if( sModuleName.toLowerCase().indexOf( m_asCategories[index].toLowerCase() ) >= 0 )
{
return index;
}
}
}
}
return m_asCategories.length - 1;
}
});
}
}
try
{
// ANDROID_CUSTOMIZATION_POINT_FILTERING
ArrayList<Message> alMessages = MessageDb.getMessages();
ArrayList<Object> alMessagesObjects = new ArrayList( alMessages );
this.m_adapter = new MessageAdapter( this, R.layout.workflowmessages, alMessagesObjects, UiHybridAppScreen.m_asHybridAppCategories );
this.m_adapter.sort();
}
public void onListItemClick(ListView oParent, View v, int iPos, long id )
{
try
{
Object oObject = m_adapter.getItem( iPos );
if( oObject instanceof Message )
{
Message oMsg = ( Message ) oObject;
// Check if Hybrid App is available
HybridApp oHybridApp = HybridAppDb.getHybridApp( oMsg.getModuleId(), oMsg.getModuleVersion());
// CR668069 -Check if we can handle transform data - 1mb limit by sqllite database
try
{
oMsg.getTransformData();
}
catch ( Exception ex )
{
MocaLog.getAmpHostLog().logMessage( "Failed to read transform data", MocaLog.eMocaLogLevel.Normal );
new AlertDialog.Builder( this )
.setTitle( android.R.string.dialog_alert_title )
.setMessage( R.string.IDS_MSG_ERR_MESSAGE_TOO_LARGE )
.setIcon( android.R.drawable.ic_dialog_alert )
.setPositiveButton( android.R.string.ok,
new DialogInterface.OnClickListener()
{
public void onClick( DialogInterface dialog, int whichButton)
{
dialog.dismiss();
}
} )
.show();
return;
}
// Update read flag
if ( !oMsg.isMsgRead() )
{
m_adapter.notifyDataSetChanged();
}
// Open Hybrid App
Intent oIntentHybridAppContainer = new Intent( this, UiHybridAppContainer.class );
oIntentHybridAppContainer.putExtra( Consts.INTENT_PARAM_HYBRIDAPP_START_MODE, Consts.START_MODE_MESSAGE );
oIntentHybridAppContainer.putExtra( Consts.INTENT_PARAM_HYBRIDAPP_MSG_ID, oMsg.getMessageId() );
oIntentHybridAppContainer.putExtra( Consts.INTENT_PARAM_HYBRIDAPP_MODULE_ID, oMsg.getModuleId() );
oIntentHybridAppContainer.putExtra( Consts.INTENT_PARAM_HYBRIDAPP_MODULE_VERSION, oMsg.getModuleVersion() );
oIntentHybridAppContainer.putExtra( Consts.INTENT_PARAM_HYBRIDAPP_PROGRESS_TEXT, oMsg.getSubject() );
startActivityForResult( oIntentHybridAppContainer, Consts.INTENT_ID_HYBRIDAPP_CONTAINER );
}
}
catch( Exception ex )
{
MocaLog.getAmpHostLog().logMessage( "Failed to open message. Caught exception - " + ex.getMessage(), MocaLog.eMocaLogLevel.Normal );
}
}