GUI Components are one of three basic components that can be added to the Fermat Framework. The two others are Add-ons and Plug-ins. Each GUI component has a well defined responsibility within the system, and usually collaborates from within one or more workflows in which it participates.
To accomplish its mission, a GUI component must have a wireframe.
A Wallet is a GUI Component that allows a user to carry out financial transactions, like sending and receiving crypto currencies, using different Plug-ins that Fermat offers through Modules. Each Module Wallet has an associated Module, thus, there is a one-on-one relationship between a Wallet and its Module.
A SubApp is a GUI Component that allows a user to carry out non-financial operations, such as creating identities within the platform, administrative tasks, among others. All of this, using various Plug-ins that Fermat offers through Modules. SubApps serve generally to complement the functionality of a wallet. Just like Wallets, each SubApp has an associated Module (there is also a one-on-one relationship between a SubApp and a Module).
A GUI component in Fermat is divided into 2 Plug-ins, the graphic interfaces and the module of such interface. This last one has the following functionalities:
- Works as a connection between the Plug-ins of the platform, consuming the services that they provide.
- It covers the logic of the presentation, gathering, organizing and grouping Plug-in data.
For more information about how to create a Module refer to this documentation
One of the problems when using fragments to construct wallets or subApps is the sharing of information between fragments on a fermat app life cycle, since a fragment is eliminated when not visible, and has to be recreated when it regains focus. This data must be saved in some place just in case a user wants to change something in a Wallet, and leave the session open.
To resolve this, there exists something called Sessions: Objects that works like shared memory between the different screens that your Wallet or SubApp may have. These apps must have their own session object to share any information they need to share. There is also data that every session always shares, such as the Module of the Wallet or SubApp, its Public Key, a reference to the Error Manager (object that handles exceptions generated in the platform) and a Map (<Key,Value> pair object) that lets an app hold the data it needs to share.
Managing fermat sessions is done by using a Wallet Manager or a SubApp Manager. These objects hold the state of a Wallet or a SubApp ready for when the user switches back to the Wallet ot SubApp screen.
Every class made to represent a Session has to extend its functionality from AbstractFermatSession
. Here's an example:
public class ReferenceWalletSession extends AbstractFermatSession<InstalledWallet,CryptoWalletManager,ProviderManager> implements WalletSession {
...
Where:
InstalledWallet
holds a reference to the installed wallet.CryptoWalletManager
is the module corresponding to the wallet mentioned.ProviderManager
(not used at this time) is a Fermat equivalent to android's R class.
Each GUI component has a folder designated to the fragment factory, that is in charge of connecting what is already developed in the Navigation Structure with the controlling fragments of such screens.
A Fragment Factory consists of two elements: an enum Enum Type Fragment and a Fragment Factory class. These elements are to be placed in the project folder fragmentFactory
representing your app.
- The Enum Type fragments represent identifiers for fragments that make up your Wallet or SubApp. These enums are to inherit from
FermatFragmentsEnumType
as shown in the following example:
public enum IntraUserIdentityFragmentsEnumType implements FermatFragmentsEnumType<IntraUserIdentityFragmentsEnumType> {
CCP_SUB_APP_CRYPTO_CUSTOMER_IDENTITY_MAIN_FRAGMENT("CCPSACCIMF"),
CCP_SUB_APP_CRYPTO_CUSTOMER_IDENTITY_CREATE_IDENTITY_FRAGMENT("CCPSACCICIF")
;
private String key;
IntraUserIdentityFragmentsEnumType(String key) { this.key = key; }
@Override
public String getKey() { return this.key; }
@Override
public String toString() { return key; }
public static IntraUserIdentityFragmentsEnumType getValue(String name) {
for (IntraUserIdentityFragmentsEnumType fragments : IntraUserIdentityFragmentsEnumType.values()) {
if (fragments.key.equals(name)) {
return fragments;
}
}
return null;
}
}
- The Fragment Factory are classes that return forms of the fragments identified by its corresponding Fragments Enum Type. Every app must have its own Fragment Factory and it has to inherit from
FermatWalletFragmentFactory
if the fragments form part of a wallet or fromFermatSubAppFragmentFactory
if the fragments are part of a SubApp, as shown in this example:
public class IntraUserIdentityFragmentFactory extends FermatSubAppFragmentFactory<IntraUserIdentitySubAppSession, IntraUserIdentityPreferenceSettings, IntraUserIdentityFragmentsEnumType> {
@Override
public AbstractFermatFragment getFermatFragment(IntraUserIdentityFragmentsEnumType fragments) throws FragmentNotFoundException {
if (fragments.equals(IntraUserIdentityFragmentsEnumType.CCP_SUB_APP_CRYPTO_CUSTOMER_IDENTITY_MAIN_FRAGMENT))
return IntraUserIdentityListFragment.newInstance();
if (fragments.equals(IntraUserIdentityFragmentsEnumType.CCP_SUB_APP_CRYPTO_CUSTOMER_IDENTITY_CREATE_IDENTITY_FRAGMENT))
return CreateIntraUserIdentityFragment.newInstance();
throw createFragmentNotFoundException(fragments);
}
@Override
public IntraUserIdentityFragmentsEnumType getFermatFragmentEnumType(String key) {
return IntraUserIdentityFragmentsEnumType.getValue(key);
}
private FragmentNotFoundException createFragmentNotFoundException(FermatFragmentsEnumType fragments) {
String possibleReason, context;
if (fragments == null) {
possibleReason = "The parameter 'fragments' is NULL";
context = "Null Value";
} else {
possibleReason = "Not found in switch block";
context = fragments.toString();
}
return new FragmentNotFoundException("Fragment not found", new Exception(), context, possibleReason);
}
}
The AppConnections
abstract class lets you include instances of the things that your Wallet or Sub-App needs to run; these things are: the Module, the Session and the Fragment Factory. You can also include other instances such as: a Navigation View Painter (in case you'd like to include a custom a side menu), a Footer Painter (in case you'd want to include a footer) and a Header Painter (the same, only a header). These three elements can be defined in the Navigation Structure of your Wallet or Sub-App.
To include an AppConnections class inside your project, you first need to extend it and modify it, adding the instances of your project's classes. Then, you need to add an instance of your new AppConnections
class in the FermatAppConnectionManager
, which manages all the the different AppConnections
classes inside Fermat.
This is a example of an AppConnections
class:
public class CryptoCustomerWalletFermatAppConnection extends AppConnections {
ActorIdentity identity;
public CryptoCustomerWalletFermatAppConnection(Activity activity, ActorIdentity identity) {
super(activity);
this.identity = identity;
}
@Override
public FermatFragmentFactory getFragmentFactory() {
return new CryptoCustomerWalletFragmentFactory();
}
@Override
public PluginVersionReference getPluginVersionReference() {
return new PluginVersionReference(Platforms.CRYPTO_BROKER_PLATFORM, Layers.WALLET_MODULE,
Plugins.CRYPTO_CUSTOMER, Developers.BITDUBAI, new Version());
}
@Override
protected AbstractFermatSession getSession() {
return new CryptoCustomerWalletSession();
}
@Override
public NavigationViewPainter getNavigationViewPainter() {
return new CustomerNavigationViewPainter(getActivity(), identity);
}
@Override
public HeaderViewPainter getHeaderViewPainter() {
return new CryptoCustomerWalletHeaderPainter();
}
@Override
public FooterViewPainter getFooterViewPainter() {
return null;
}
}
This is a example of the FermatAppConnectionManager
public class FermatAppConnectionManager {
public static AppConnections switchStatement(Activity activity,String publicKey){
AppConnections fermatAppConnection = null;
switch (publicKey){
//CCP WALLET
case "reference_wallet":
fermatAppConnection = new BitcoinWalletFermatAppConnection(activity);
break;
//CCP Sub Apps
case "public_key_ccp_intra_user_identity":
fermatAppConnection = new CryptoWalletUserFermatAppConnection(activity);
break;
case "public_key_intra_user_community":
fermatAppConnection = new CryptoWalletUserCommunityFermatAppConnection(activity);
break;
//DAP WALLETS
case "asset_issuer" :
fermatAppConnection = new WalletAssetIssuerFermatAppConnection(activity);
break;
case "asset_user" :
fermatAppConnection = new WalletAssetUserFermatAppConnection(activity);
break;
case "redeem_point" :
fermatAppConnection = new WalletRedeemPointFermatAppConnection(activity);
break;
//DAP Sub Apps
case "public_key_dap_asset_issuer_identity":
fermatAppConnection = new AssetIssuerFermatAppConnection(activity);
break;
case "public_key_dap_asset_user_identity":
fermatAppConnection = new AssetUserFermatAppConnection(activity);
break;
case "public_key_dap_redeem_point_identity":
fermatAppConnection = new RedeemPointFermatAppConnection(activity);
break;
case "public_key_dap_factory":
fermatAppConnection = new AssetFactoryFermatAppConnection(activity);
break;
case "public_key_dap_issuer_community":
fermatAppConnection = new CommunityAssetIssuerFermatAppConnection(activity);
break;
case "public_key_dap_user_community":
fermatAppConnection = new CommunityAssetUserFermatAppConnection(activity);
break;
case "public_key_dap_redeem_point_community":
fermatAppConnection = new CommunityRedeemPointFermatAppConnection(activity);
break;
//PIP Sub Apps
case "public_key_pip_developer_sub_app":
fermatAppConnection = new DeveloperFermatAppConnection(activity);
break;
//CBP WALLETS
case "crypto_broker_wallet":
fermatAppConnection = new CryptoBrokerWalletFermatAppConnection(activity, null);
break;
case "crypto_customer_wallet":
fermatAppConnection = new CryptoCustomerWalletFermatAppConnection(activity, null);
break;
//CBP Sub Apps
case "public_key_crypto_broker_community":
fermatAppConnection = new CryptoBrokerCommunityFermatAppConnection(activity);
break;
case "sub_app_crypto_broker_identity":
fermatAppConnection = new CryptoBrokerIdentityFermatAppConnection(activity);
break;
case "sub_app_crypto_customer_identity":
fermatAppConnection = new CryptoCustomerIdentityFermatAppConnection(activity);
break;
//CASH WALLET
case "cash_wallet":
fermatAppConnection = new CashMoneyWalletFermatAppConnection(activity, null);
break;
//BANKING WALLET
case "banking_wallet":
fermatAppConnection = new BankMoneyWalletFermatAppConnection(activity);
break;
// WPD Sub Apps
case "public_key_store":
fermatAppConnection = new WalletStoreFermatAppConnection(activity);
}
return fermatAppConnection;
}
public static AppConnections getFermatAppConnection(String publicKey, Activity activity, FermatSession referenceAppFermatSession) {
AppConnections fermatAppConnection = switchStatement(activity,publicKey);
fermatAppConnection.setFullyLoadedSession(referenceAppFermatSession);
return fermatAppConnection;
}
public static AppConnections getFermatAppConnection(String appPublicKey, Activity activity) {
AppConnections fermatAppConnection = switchStatement(activity,appPublicKey);
return fermatAppConnection;
}
}
Fermat is an application different from other Android applications; it has its own navigation structure, that is based on screens and sub-screens that begin to “draw” from uploaded objects when executed based on files that deliver information about what it is needed to draw in each screen/sub-screen and in what order.
It allows to set the flow of interaction between the different application screens just as certain visual aspects of these screens like backgrounds, colors , and sizes.
It also allows to set for screens the existence of Headers, Footers, Navigation Drawers, Tabs and TabStrips, Menus, among other elements following a similar style to WordPress.
Depending on whether you want to create a SubApp or Wallet, you have to add your navigation structure in the void factoryReset()
method to any of these two classes:
SubAppRuntimeEnginePluginRoot
Located inDMP/plugin/engine/fermat-dmp-plugin-engine-sub-app-runtime-bitdubai/
in the case of a SubAppWalletRuntimeEnginePluginRoot
Located inDMP/plugin/engine/fermat-dmp-plugin-engine-wallet-runtime-bitdubai/
in the case of a Wallet
This is a simple example of how to create the navigation structure for a SubApp:
private void factoryReset(){
...
// Creating the Navigation Structure for the Intra User Identity SubApp
RuntimeSubApp runtimeSubApp = new RuntimeSubApp();
runtimeSubApp.setType(SubApps.CCP_INTRA_USER_IDENTITY);
String intraUserIdentityPublicKey = "public_key_ccp_intra_user_identity";
runtimeSubApp.setPublicKey(intraUserIdentityPublicKey);
// Creating a Activity. Screen: Create New Identity
runtimeActivity = new Activity();
runtimeActivity.setType(Activities.CCP_SUB_APP_INTRA_IDENTITY_CREATE_IDENTITY);
runtimeActivity.setActivityType(Activities.CCP_SUB_APP_INTRA_IDENTITY_CREATE_IDENTITY.getCode());
runtimeActivity.setColor("#03A9F4");
// Adding the Activity in the Navigation Structure
runtimeSubApp.addActivity(runtimeActivity);
runtimeSubApp.setStartActivity(Activities.CCP_SUB_APP_INTRA_IDENTITY_CREATE_IDENTITY);
// Title Bar (a.k.a Action Bar) of the Activity
runtimeTitleBar = new TitleBar();
runtimeTitleBar.setLabel("Identity Manager");
runtimeTitleBar.setColor("#1189a4");
runtimeTitleBar.setTitleColor("#ffffff");
runtimeTitleBar.setLabelSize(18);
runtimeTitleBar.setIsTitleTextStatic(true);
// Adding the Title Bar in the Activity
runtimeActivity.setTitleBar(runtimeTitleBar);
// Status Bar of the Activity
statusBar = new StatusBar();
statusBar.setColor("#1189a4");
// Adding the Status Bar in the Activity
runtimeActivity.setStatusBar(statusBar);
// Fragment for this activity
runtimeFragment = new Fragment();
runtimeFragment.setType(Fragments.CCP_SUB_APP_CRYPTO_CUSTOMER_IDENTITY_CREATE_IDENTITY_FRAGMENT.getKey());
// Adding the Fragment in the Activity
// and seting it has a Start Fragment (is going to show first for this activiy)
runtimeActivity.addFragment(Fragments.CCP_SUB_APP_CRYPTO_CUSTOMER_IDENTITY_CREATE_IDENTITY_FRAGMENT.getKey(), runtimeFragment);
runtimeActivity.setStartFragment(Fragments.CCP_SUB_APP_CRYPTO_CUSTOMER_IDENTITY_CREATE_IDENTITY_FRAGMENT.getKey());
// Adding the Navigation Structure in the platform
listSubApp.put(runtimeSubApp.getPublicKey(), runtimeSubApp);
...
}
NOTE: For a more complete example of navigation structures you can review the private WalletNavigationStructure createCryptoBrokerWalletNavigationStructure()
method in the case of a Wallet and private void createWalletStoreNavigationStructure()
in case of a SubApp.
The location of the navigation structure in these files is temporary; in the future, as a first step it should be read from an XML in the Fermat repository in github and as a second step it should be able to be obtained from the other nodes of the Fermat network.
As indicated in the previous point, Fermat offers a number of objects to build the navigation structure of a Wallet or SubApp, following a similar style to WordPress. In these following sections we’ll talk a little more in detail about the different objects provided and an example of how to use it.
...
// Creating a Activity. Screen: Create New Identity
runtimeActivity = new Activity();
runtimeActivity.setType(Activities.CCP_SUB_APP_INTRA_IDENTITY_CREATE_IDENTITY);
runtimeActivity.setActivityType(Activities.CCP_SUB_APP_INTRA_IDENTITY_CREATE_IDENTITY.getCode());
runtimeActivity.setColor("#03A9F4");
// Adding the Activity in the Navigation Structure
runtimeSubApp.addActivity(runtimeActivity);
// Seting the Activity has a Start Activity (is going to show first for this app)
runtimeSubApp.setStartActivity(Activities.CCP_SUB_APP_INTRA_IDENTITY_CREATE_IDENTITY);
...
An activity in the context of Fermat is a base container which tells the android core how the screen will be designed, what will its flow be and what elements make part of it (This is done this way so that in the future developers could join Fermat). Unlike android a developer should not develop Android Activity class in order to run their fragments, but declare them in the runtime under Activity object (FermatActivity) is enough for them to draw on screen.
Activity IDs must be created in the Activities
enum package
com.bitdubai.fermat_api.layer.all_definition.navigation_structure.enums
public enum Activities {
CWP_SHELL_LOGIN("CSL"),
CWP_SHOP_MANAGER_MAIN("CSMM"),
CWP_WALLET_MANAGER_MAIN("CWMM"),
CWP_WALLET_RUNTIME_WALLET_AGE_KIDS_ALL_BITDUBAI_VERSION_1_MAIN("CWRWAKAB1M"),
// Reference wallet
CWP_WALLET_RUNTIME_WALLET_BASIC_WALLET_BITDUBAI_VERSION_1_MAIN("CWRWBWBV1M"),
CWP_WALLET_RUNTIME_WALLET_BASIC_WALLET_BITDUBAI_VERSION_1_TRANSACTIONS("CWRWBWBV1T"),
CWP_WALLET_RUNTIME_WALLET_BASIC_WALLET_BITDUBAI_VERSION_1_PAYMENT_REQUEST("CWRWBWBV1PR"),
CWP_WALLET_RUNTIME_WALLET_BASIC_WALLET_BITDUBAI_VERSION_1_CONTACTS("CWRWBWBV1C"),
CWP_WALLET_RUNTIME_WALLET_BASIC_WALLET_BITDUBAI_VERSION_1_SETTINGS("CWRWBWBV1S"),
CCP_BITCOIN_WALLET_SEND_FORM_ACTIVITY("CCPBWSFA"),
CCP_BITCOIN_WALLET_REQUEST_FORM_ACTIVITY("CCPBWRFA"),
CCP_BITCOIN_WALLET_CONTACT_DETAIL_ACTIVITY("CCPBWCDA"),
CCP_BITCOIN_WALLET_SETTINGS_ACTIVITY("CCPBWSA"),
CCP_BITCOIN_WALLET_ADD_CONNECTION_ACTIVITY("CCPBWACA"),
CCP_BITCOIN_WALLET_NO_IDENTITY_ACTIVITY("CCPBWNIA"),
...
}
...
// Fragment for this activity
runtimeFragment = new Fragment();
runtimeFragment.setType(Fragments.CCP_SUB_APP_CRYPTO_CUSTOMER_IDENTITY_CREATE_IDENTITY_FRAGMENT.getKey());
// Adding the Fragment in the Activity
// and setting it has a Start Fragment (is going to show first for this activity)
runtimeActivity.addFragment(Fragments.CCP_SUB_APP_CRYPTO_CUSTOMER_IDENTITY_CREATE_IDENTITY_FRAGMENT.getKey(), runtimeFragment);
runtimeActivity.setStartFragment(Fragments.CCP_SUB_APP_CRYPTO_CUSTOMER_IDENTITY_CREATE_IDENTITY_FRAGMENT.getKey());
...
A fragment on Fermat has the same meaning as in Android, and has a representation in the navigation structure to be assigned to an activity or a Tab.
Fragment IDs must be created in the Fragments
enum package
com.bitdubai.fermat_api.layer.all_definition.navigation_structure.enums.
public enum Fragments implements FermatFragments {
CWP_SHELL_LOGIN("CSL"),
CWP_WALLET_MANAGER_MAIN("CWMM"),
CWP_SUB_APP_DEVELOPER("CSAD"),
CWP_WALLET_MANAGER_SHOP("CWMS"),
CWP_SHOP_MANAGER_MAIN("CSMM"),
CWP_SHOP_MANAGER_FREE("CSMF"),
CWP_SHOP_MANAGER_PAID("CSMP"),
CWP_SHOP_MANAGER_ACCEPTED_NEARBY("CSMAN"),
CWP_WALLET_PUBLISHER_MAIN_FRAGMENT("CWPMF"),
// Wallet Store
CWP_WALLET_STORE_MAIN_ACTIVITY("CWPWSMA"),
CWP_WALLET_STORE_DETAIL_ACTIVITY("CWPWSDA"),
CWP_WALLET_STORE_MORE_DETAIL_ACTIVITY("CWPWSMDA"),
...
}
...
// Creating a Header
runtimeHeader = new Header();
runtimeHeader.setLabel("Market rate");
// Seting the Header in the Activity
runtimeActivity.setHeader(runtimeHeader);
...
It’s possible to add an expandable and collapsible header in an activity of your app. This is done in several steps:
-
Set in the navigation structure that the activity has a header:
-
Create a class
<ScreenName>HeaderViewPainter
that implementsHeaderViewPainter
in thecommons/headers/
folder of your GUI Project. For example, in the bitcoin wallet it would becommons/headers/HomeHeaderViewPainter.java
. This class contains the view wanted to be shown as a header. -
Inside the
onActivityCreated
method of the fragment that the header will contain,getPaintActivityFeatures().addHeaderView()
must be passed as a standard, a form of<ScreenName>HeaderViewPainter
...
// Creating a Footer
Footer runtimeFooter = new Footer();
runtimeFooter.setBackgroundColor("#AAAAAA");
// Creating the Fragment for the Footer
runtimeFragment = new Fragment();
runtimeFragment.setType(Fragments.CBP_CRYPTO_BROKER_WALLET_STOCK_STATISTICS.getKey());
runtimeActivity.addFragment(Fragments.CBP_CRYPTO_BROKER_WALLET_STOCK_STATISTICS.getKey(), runtimeFragment);
// Associating the Fragment with the Footer
runtimeFooter.setFragmentCode(Fragments.CBP_CRYPTO_BROKER_WALLET_STOCK_STATISTICS.getKey());
// Associating the Footer with the Activity
runtimeActivity.setFooter(runtimeFooter);
...
It’s possible to add a sliding Footer in an activity of your app. This is done in several steps:
-
Set in the navigation structure for the activity to have a Footer and assign a fragment to it
-
Create a
<ScreenName>FooterViewPainter
class that implementsFooterViewPainter
in thecommons/footers/
folder of your GUI project; for example in the Crypto Broker wallet it would becommons/footers/HomeFooterViewPainter.java
. This class contains the views that make up the Footer:slide_container
is the Footer view that is always visible to be able to display the content.footer_container
is the Footer view that represents its content, and it shows up when the Footer is displayed.
-
Within the
onActivityCreated
method of the fragment that will contain the Footer, the standard must be passedgetPaintActivtyFeactures().addFooterView()
a form of<nombreScreen>FooterViewPainter
...
// Side Menu
runtimeSideMenu = new SideMenu();
runtimeMenuItem = new MenuItem();
runtimeMenuItem.setLabel("Home");
runtimeMenuItem.setLinkToActivity(Activities.CBP_CRYPTO_BROKER_WALLET_HOME);
runtimeMenuItem.setAppLinkPublicKey(publicKey);
runtimeSideMenu.addMenuItem(runtimeMenuItem);
runtimeMenuItem = new MenuItem();
runtimeMenuItem.setLabel("Contracts History");
runtimeMenuItem.setLinkToActivity(Activities.CBP_CRYPTO_BROKER_WALLET_CONTRACTS_HISTORY);
runtimeMenuItem.setAppLinkPublicKey(publicKey);
runtimeSideMenu.addMenuItem(runtimeMenuItem);
runtimeMenuItem = new MenuItem();
runtimeMenuItem.setLabel("Earnings");
runtimeMenuItem.setLinkToActivity(Activities.CBP_CRYPTO_BROKER_WALLET_EARNINGS);
runtimeMenuItem.setAppLinkPublicKey(publicKey);
runtimeSideMenu.addMenuItem(runtimeMenuItem);
runtimeMenuItem = new MenuItem();
runtimeMenuItem.setLabel("Settings");
runtimeMenuItem.setLinkToActivity(Activities.CBP_CRYPTO_BROKER_WALLET_SETTINGS);
runtimeMenuItem.setAppLinkPublicKey(publicKey);
runtimeSideMenu.addMenuItem(runtimeMenuItem);
...
It’s possible to add a Navigation Drawer (or Side Menu) that allows you to go to different screens of your app. This is set in several steps
-
Set in the navigation structure that the activity has a Side Menu and that the latter has a number of Menu Items
-
Create a
<AppName>NavigationViewAdapter
class (with its View Holder) that implementsFermatAdapter
in thecommons/navigationView/
folder. For example in the bitcoin wallet it would becommons/navigationDrawer/BitcoinWalletNavigationViewAdapter.java
. This adapter represents the items that are to be displayed in the navigation drawer and are related to those already set in the navigation structure -
Create a
<AppName>NavigationViewPainter
class that implementsNavigationViewPainter
in thecommons/navigationView/
folder. For example in the bitcoin wallet it would becommons/navigationDrawer/BitcoinWalletNavigationViewPainter.java
. This class contains the elements that make up the Navigation Drawer:- Header: A View that represents the header of the Navigation Drawer. Usually the photo of the person logged in is placed here.
- Adapter: a form
<AppName>NavigationViewAdapter
that represents the menu items - Content: A View that is drawn after the menu items, anything can be placed here, for example a footer to show more information
-
Within the
onActivityCreated
method of the fragment that will contain the Navigation Drawer, as a standard we must passgetPaintActivityFeactures().addNavigationView()
a form of<AppName>NavigationViewPainter
In your GUI project, you must create the fragments that you set in the navigation structure, creating classes that inherit from AbstractFermatFragment
and placing them within the fragments
folder of your project. AbstractFermatFragment
has a reference to your Wallet or SubApp Session
, as well as, to Settings
and ProviderManager
. There are several subclasses in fermat-api
that extend AbstractFermatFragment
and facilitate certain jobs, such as handling lists and some more specialized things like drop-down lists, wirzards, etc:
FermatExpandableListFragment
FermatListFragment
FermatWalletExpandableListFragment
FermatWalletListFragment
FermatWizardPageFragment
For more information about these and other fragments please see the fermat-api
project.
Here is an example of a basic fragment extending from AbstractFermatFragment
where we obtain reference to the app Session
to which it belongs, its Module
and its Error Manager
:
public class SettingsActivityFragment extends AbstractFermatFragment {
// Constants
private static final String TAG = "SettingsActivityFragment";
// Fermat Managers
private CryptoBrokerWalletModuleManager moduleManager;
private ErrorManager errorManager;
public static SettingsActivityFragment newInstance() {
return new SettingsActivityFragment();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
moduleManager = ((CryptoBrokerWalletSession) walletSession).getModuleManager();
errorManager = walletSession.getErrorManager();
} catch (Exception ex) {
CommonLogger.exception(TAG, ex.getMessage(), ex);
if (errorManager != null)
errorManager.reportUnexpectedWalletException(Wallets.CBP_CRYPTO_BROKER_WALLET,
UnexpectedWalletExceptionSeverity.DISABLES_THIS_FRAGMENT, ex);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
try {
BrokerNavigationViewPainter navigationViewPainter = new BrokerNavigationViewPainter(getActivity(), null);
getPaintActivityFeatures().addNavigationView(navigationViewPainter);
} catch (Exception e) {
makeText(getActivity(), "Oops! recovering from system error", Toast.LENGTH_SHORT).show();
errorManager.reportUnexpectedUIException(UISource.VIEW, UnexpectedUIExceptionSeverity.CRASH, e);
}
}
}
This section will help you understand the workflow needed to be followed in order to implement a GUI component in Fermat.
### Getting Organized ---------------------
It is mandatory that you create an initial set of GitHub issues before you proceed further on the workflow. This will show the rest of the teams that someone is working in this functionality and avoid conflicting work early on. It will also hook the team leader into your workflow and allow him to guide and advise you when needed.
A basic hierarchy of issues is created as a first step. The issues are linked one to the other just by placing a link on the first comment.
Where we refer to 'Plugin Name' what we expect is the following information:
- Platform or Super Layer name - 3 characters.
- Layer name
- Plug-in name
All of them separated by " - ".
Issues that needs to be linked to its parent must have their first line starting with "Parent: " + http link to parent issue.
Team leaders are tagged in the second line in order to ask them to assign the issue to you and at the same time subscribe to any issue update. This helps team leaders to follow the issue events and provide assistance or guidance is they see something wrong. The suggested format is:
"@team-leader-user-name please assign this issue to me."
#### Plug-in Issue Structure
The mandatory initial structure is the following: (note: the word ISSUE is not part of the name)
##### ISSUE: '_Plugin Name_' - Plug-In
This is the root of your issue structure and must be labeled as SUPER ISSUE. It is closed only when all of its children and grand children are closed.
This is the Analysis root. It is closed whenever all analysis is done. This issue must be linked to the root of the issue structure.
1 - ISSUE: **'_Plugin Name_' - Module - prototype**
This is the hardcoded module. Used for making the GUI prototype without using the fermat platform. This issue must be linked to the root of the issue structure.
2 - ISSUE: **'_Plugin Name_' - Module - connection**
This is the module connected with fermat platform. Used for making the GUI using the fermat platform. This issue must be linked to the root of the issue structure.
3 - ISSUE: **'_Plugin Name_' - GUI - screen - **
This issue is for a specific wireframe of a screen.
##### ISSUE: '_Plugin Name_' - Testing
This is the Testing root. It is closed whenever all testing is done. This issue must be linked to the root of the issue structure.
-
ISSUE: 'Plugin Name' - Testing - Unit Testing
-
ISSUE: 'Plugin Name' - Testing - Integration Testing
##### ISSUE: '_Plugin Name_' - QA
This is the QA root. It is closed whenever QA tests are passed. This issue must be linked to the root of the issue structure.
It is expected to have here child issues in the form 'Plugin Name' QA - Bug Fix n, where n is both the number and the bug name.
##### ISSUE: '_Plugin Name_' - Production
This is the Production root. It is closed whenever the Plug-in reaches production. It can be re-opened if bug issues are found on production and closed again once they are fixed. This issue must be linked to the root of the issue structure.
It is expected to have here child issues in the form 'Plugin Name' Production - Bug Fix n, where n is both the number and the bug name.
The GUI components are grouped in projects that could represent a Wallet, SubApp or a Desktop for a platform; For example CBP has 2 Wallets and 4 SubApps.
Whenever you wish you create a new Wallet, SubApp or Desktop, you must create the project that will hold the GUI components in any of the three directories that are shown below following this structure:
+ Platform_Name
+ Client_Type (Android, nowadays)
+ desktop
- desktop_project_name_1
- desktop_project_name_2
+ reference_wallet
- wallet_project_name_1
- wallet_project_name_2
- wallet_project_name_n
+ sub_app
- sub_app_project_name_1
- sub_app_project_name_2
- sub_app_project_name_3
- sub_app_project_name_n
Where:
- Platform_Name: Refers to the platform where you’re going to create your components.
- Client_Type: Refers to the device where the client is going to create, either Android, IPhone, a web or desktop application, etc. At the moment the client we are using is Android, therefore the name of this folder is “android”
- desktop: You place desktop, SubApps and Wallets projects here.
- reference_wallet: Here you will create the projects that have their GUI components that represent Wallets.
- sub_app: Here you will create the projects that have their GUI components that represent SubApps.
Here’s an example:
+ CBP
+ android
+ desktop
- fermat-cbp-android-desktop-sub-app-manager-bitdubai
- fermat-cbp-android-desktop-wallet-manager-bitdubai
+ reference_wallet
- fermat-cbp-android-reference-wallet-crypto-broker-bitdubai
- fermat-cbp-android-reference-wallet-crypto-customer-bitdubai
+ sub_app
- fermat-cbp-android-sub-app-crypto-broker-community-bitdubai
- fermat-cbp-android-sub-app-crypto-broker-identity-bitdubai
- fermat-cbp-android-sub-app-crypto-customer-community-bitdubai
- fermat-cbp-android-sub-app-crypto-customer-identity-bitdubai
This means that i have a total of 8 projects that hold GUI components, from which 2 are Desktops, 2 are Wallets and 4 are SubApps.
The name of the projects follow this pattern:
fermat-[platform_name]-[client_type]-[project_type]-[name_of_the_project]-[org_name]
Where:
- platform_Name: Refers to the platform where you will create your components.
- client_type: Refers to the device where the client is going to create, either Android, IPhone, a web or desktop application, etc. At the moment the client we are using is Android, therefore the name of this folder is “android”.
- project_type: Refers to the type of project you’re goint to create GUI components for. They could be desktop, reference wallet or SubApp.
- name_of_the_project: This is the name of the project. For example: if your project is named Crypto Broker Community then you have to name it crypto broker community.
- org_name: This is the name of the developer organization o company that is creating the project, for example: bitdubai.
Here’s an example:
fermat-cbp-android-sub-app-crypto-broker-community-bitdubai
Where: cbp is the platform, android is the device, sub-app is the type of project, crypto-broker-community es is the name of the project and bitdubai is the organization responsible for the components of this project. This means that the project is a SubApp called Crypto Broker Community developed for Android devices and created by BitDubai for the CBP platform.
A GUI component project for Android in Fermat has the following basic structure (Label: + folder, > package, - file):
+ fermat-[platform_name]-[client_type]-[project_type]-[name_of_the_project]-[org_name]
- .gitignore
- build.gradle
- proguard-rules.pro
+ src
+ main
+ java
> com.bitdubai.[project_type].[name_of_the_project]
> fragmentFactory
> fragments
> preference_settings
> session
+ res
+ drawable
+ layout
+ menu
+ values
+ test
+ java
> unit.com.bitdubai.[project_type].[name_of_the_project]
Where:
- Everything that goes in the
src
folder are files and resources you will need to develop your Wallet/SubApp/Desktop in Android. - Inside
src/main/java
you will find the package where you will place java files (classes, interfaces, enums..) with your Android code. It has the following basic packages: fragmentFactory, fragments, preference_settings and session. Each one of them explained in detail later on in this README. - Inside
src/main/res
there arexml
files found that represent layouts, menus, colors, strings and sizes as well as image files and others that represent visual resources with which you’re going to interact the java classes that have an Android logic. - Everything that goes in the
test
folder is code that is used to make Unit Testing on the functionalities you’re developing insrc
. - The Unit Test are created inside the package
unit.com.bitdubai.[project_type].[name_of_the_project]
intest/java
- The file
build.gradle
is where you define the dependencies of the project with others of the platforms or with third party libraries and those that Android offers but not as default (the Support Libraries for example). Also the minimal version of the OS is defined where the app is going to run like the SDK Android version that is going to be used among other things (for more information see this link) - The file
proguard-rules.pro
configures the Proguard tool. (for more information see this link). NOTE: we do not configure this file at the moment, therefore it is empty
At the beginning when you create your Android project to develop your Wallet/SubApp/Desktop, it won’t be recognized as such in the dependencies structure of the root project (Fermat) and it will show like one more directory. So your project is included in dependencies structure it is necessary to add the following lines in the file settings.gradle
that is found in the folder of the platform where you’re going to work:
include ':fermat-[platform_name]-[client_type]-[project_type]-[name_of_the_project]-[org_name]'
project(':fermat-[platform_name]-[client_type]-[project_type]-[name_of_the_project]-[org_name]').projectDir = new File('platform_name/client_type/project_type/fermat-[platform_name]-[client_type]-[project_type]-[name_of_the_project]-[org_name]')
Here's an example of part of the file settings.gradle
of the CBP platform (fermat/CBP/settings.gradle
):
...
//Desktop
include ':fermat-cbp-android-desktop-sub-app-manager-bitdubai'
project(':fermat-cbp-android-desktop-sub-app-manager-bitdubai').projectDir = new File('CBP/android/desktop/fermat-cbp-android-desktop-sub-app-manager-bitdubai')
include ':fermat-cbp-android-desktop-wallet-manager-bitdubai'
project(':fermat-cbp-android-desktop-wallet-manager-bitdubai').projectDir = new File('CBP/android/desktop/fermat-cbp-android-desktop-wallet-manager-bitdubai')
//Reference Wallet
include ':fermat-cbp-android-reference-wallet-crypto-broker-bitdubai'
project(':fermat-cbp-android-reference-wallet-crypto-broker-bitdubai').projectDir = new File('CBP/android/reference_wallet/fermat-cbp-android-reference-wallet-crypto-broker-bitdubai')
include ':fermat-cbp-android-reference-wallet-crypto-customer-bitdubai'
project(':fermat-cbp-android-reference-wallet-crypto-customer-bitdubai').projectDir = new File('CBP/android/reference_wallet/fermat-cbp-android-reference-wallet-crypto-customer-bitdubai')
//Sub App
include ':fermat-cbp-android-sub-app-crypto-broker-community-bitdubai'
project(':fermat-cbp-android-sub-app-crypto-broker-community-bitdubai').projectDir = new File('CBP/android/sub_app/fermat-cbp-android-sub-app-crypto-broker-community-bitdubai')
include ':fermat-cbp-android-sub-app-crypto-broker-identity-bitdubai'
project(':fermat-cbp-android-sub-app-crypto-broker-identity-bitdubai').projectDir = new File('CBP/android/sub_app/fermat-cbp-android-sub-app-crypto-broker-identity-bitdubai')
include ':fermat-cbp-android-sub-app-crypto-customer-community-bitdubai'
project(':fermat-cbp-android-sub-app-crypto-customer-community-bitdubai').projectDir = new File('CBP/android/sub_app/fermat-cbp-android-sub-app-crypto-customer-community-bitdubai')
include ':fermat-cbp-android-sub-app-crypto-customer-identity-bitdubai'
project(':fermat-cbp-android-sub-app-crypto-customer-identity-bitdubai').projectDir = new File('CBP/android/sub_app/fermat-cbp-android-sub-app-crypto-customer-identity-bitdubai')
include ':fermat-cbp-android-sub-app-customers-bitdubai'
project(':fermat-cbp-android-sub-app-customers-bitdubai').projectDir = new File('CBP/android/sub_app/fermat-cbp-android-sub-app-customers-bitdubai')
//PLUG-INS
...
When connecting the corresponding FragmentFactory to the developed Plug-in we must add to the android core so it can have reference to itself, we must follow these steps:
Include dependency to the build.gradle module Find in the folder the /android-core/common/version_1/fragment_factory/ route Here you will find the SubAppFragmentFactory and WalletFragmentFactory classes, that are in charge of creating the fragmentFactory form of the previously created module and so just as in the adroid core be able to do a petition.
When connecting the corresponding session to the developed plug-in we must add it to the android core so that it can have referente to itself, we must follow these steps: Include dependency to the build.gradle module Find in the folder the /android-core/common/version_1/sessions/ route Here you will find the SubAppSessionManager and WalletSessionManager classes, that are in charge of creating the form to the Session of the previously created module and so just as in the adroid core be able to do a petition.
Under construction… it is temporarily located in the /android-core/common/version_1/ProvisoryData class
- Create the Android Reference Wallet code base:
- Create the proyect structure has said in Where to put your projects section of this document
- Add the following to the project:
- In src/main/java:
- A class that extends from
WalletFragmentFactory
, - A Enum that extends from
WalletFragmentsEnumType
, - A class that extends from
PreferenceSettings
- A class that extends from
AbstractFermatSession
- A class that extends from
- In src/main/res:
- at least one
layout.xml
colors.xml
,dimension.xml
andstrings.xml
- at least one
- In src/main/java:
- Create the
AppConnections
class and add it in theFermatAppConnectionsManager
- In
src/main/java/app_connection
create a class that extend fromAppConnections
and fill the required methods, as described in the App Connections Class section of this document
- Register the Activities and Fragments in the fermat-api project:
- Go to:
fermat_api/layer/all_definition/navigation_structure/enums
and:- In
Activities
enum: Enter the wallet or Sub-App activities (the home, for starters) and add it to thegetValueFromString(...)
method of this enum. Example:CSH_CASH_MONEY_WALLET_HOME("CSHCMWH")
- In
Fragments
enum: Enter at least a Fragment that belongs to the home. Example:CSH_CASH_MONEY_WALLET_BALANCE_SUMMARY("CSHCMWBS")
- In
- The enums made in
Fragments
must also be created in yourFermatFragmentsEnumType
and used in your Wallet or Sub-AppFermatFragmentFactory
.
- Create the Navigation Structure:
- If you are creating a Wallet go to:
WPD/plugin/engine/fermat-wpd-plugin-engine-wallet-runtime-bitdubai/.../WalletRuntimeEnginePluginRoot.java
- If you are creating a Sub-App go to:
DMP/plugin/engine/fermat-pip-plugin-engine-sub-app-runtime-bitdubai/.../SubAppRuntimeEnginePluginRoot.java
- Add the Navigation Structure as described in the Navigation Structure section of this document using the Activities and Fragments created above.
- Create an icon in the Desktop:
- If you are creating a Wallet go to:
DMP/android/sub_app/fermat-wpd-android-sub-app-wallet-manager-bitdubai/.../DesktopFragment.java
- If you are creating a Sub-App go to:
PIP/android/sub_app/fermat-pip-android-sub-app-sub-app-manager-bitdubai/.../DesktopSubAppFragment.java
- Add in the
getMoreData()
method the Wallet or Sub-App, in a way so the Desktop shows the wallet icon in order to be able to open it.
- How to Create a wallet/subapp from scratch: https://www.youtube.com/watch?v=-gIZqKwvhac
- The AppConection class, What it is and How to use it: https://www.youtube.com/watch?v=S0hqL3Smcko
- Where to put the Icons in the Fermat Desktop: https://www.youtube.com/watch?v=vhI-bq0Nz0Y
- Android api - Dialog Presentation Template: https://www.youtube.com/watch?v=oTDJN7RKajw