diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5edb4ee --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.iml +.gradle +/local.properties +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser new file mode 100644 index 0000000..ad97ff4 Binary files /dev/null and b/.idea/caches/build_file_checksums.ser differ diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..30aa626 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..7ac24c7 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..dc34569 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..d4ea1c9 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,51 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 27 + defaultConfig { + applicationId "com.example.ian.sambazaquick" + minSdkVersion 19 + targetSdkVersion 27 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'com.google.firebase:firebase-auth:11.6.0' + implementation 'com.google.firebase:firebase-database:11.6.0' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + implementation 'com.google.android.gms:play-services:12.0.1' + implementation 'com.google.firebase:firebase-core:11.6.0' + implementation files('json-20090211.jar') +} + +allprojects{ + repositories { + //... + } + + subprojects { + project.configurations.all { + resolutionStrategy.eachDependency{details -> + if (details.requested.group == 'com.google.android.gms' && !details.requested.name.contains('multidex')){ + details.useVersion "12.0.1" + } + } + } + } +} + +apply plugin: 'com.google.gms.google-services' diff --git a/app/google-services.json b/app/google-services.json new file mode 100644 index 0000000..9a8366e --- /dev/null +++ b/app/google-services.json @@ -0,0 +1,55 @@ +{ + "project_info": { + "project_number": "830949487098", + "firebase_url": "https://sambazaquick.firebaseio.com", + "project_id": "sambazaquick", + "storage_bucket": "sambazaquick.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:830949487098:android:73bdf9f61bc2d933", + "android_client_info": { + "package_name": "com.example.ian.sambazaquick" + } + }, + "oauth_client": [ + { + "client_id": "830949487098-ph7npqgq33rj7vh10nt7choddmcbvqs5.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.example.ian.sambazaquick", + "certificate_hash": "5cdbfb6243abcaa938a4affb1fb42464d47a4764" + } + }, + { + "client_id": "830949487098-udensv1lig1q0eki0ru9pk46pito5166.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyBYIG0z2Yl_t0W3f9dsmHlq9vQ0OHUwGfU" + } + ], + "services": { + "analytics_service": { + "status": 1 + }, + "appinvite_service": { + "status": 2, + "other_platform_oauth_client": [ + { + "client_id": "830949487098-udensv1lig1q0eki0ru9pk46pito5166.apps.googleusercontent.com", + "client_type": 3 + } + ] + }, + "ads_service": { + "status": 2 + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/app/json-20090211.jar b/app/json-20090211.jar new file mode 100644 index 0000000..ef29094 Binary files /dev/null and b/app/json-20090211.jar differ diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/com/example/ian/sambazaquick/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/example/ian/sambazaquick/ExampleInstrumentedTest.java new file mode 100644 index 0000000..9e9c633 --- /dev/null +++ b/app/src/androidTest/java/com/example/ian/sambazaquick/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.example.ian.sambazaquick; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.example.ian.sambazaquick", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..193fadc --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/example/ian/sambazaquick/AddNewContactsFragment.java b/app/src/main/java/com/example/ian/sambazaquick/AddNewContactsFragment.java new file mode 100644 index 0000000..60661c4 --- /dev/null +++ b/app/src/main/java/com/example/ian/sambazaquick/AddNewContactsFragment.java @@ -0,0 +1,158 @@ +package com.example.ian.sambazaquick; + +import android.app.ProgressDialog; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; + +//for firebase database access +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.DatabaseReference; + +//for firebase authentication to get +import com.google.firebase.auth.FirebaseAuth; + +//for our UI widgets +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageButton; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Button; +import android.widget.Toast; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; + +public class AddNewContactsFragment extends Fragment { + + //for our db references + private DatabaseReference mDbRef; + + //for getting our current user + private FirebaseAuth mAuth; + + //for our UI widgets + private ImageButton mBtnBck; + private EditText mEditName, mEditPhone; + private Button mBtnAdd; + private TextView mTxtShwName, mTxtShwNo; + private ProgressDialog progressDialog; + + //Override onCreate and initialize our DatabaseReference here + @Override + public void onCreate (Bundle savedInstanceState){ + super.onCreate(savedInstanceState); + + mDbRef = FirebaseDatabase.getInstance().getReference(); + mAuth = FirebaseAuth.getInstance(); + } + + //Now, to load our UI and wire it up + @Override + public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){ + + //remove previous views + container.removeAllViews(); + + //load our UI + View view = inflater.inflate(R.layout.add_contacts_fragment,container,false); + + //get widget references + mBtnBck = view.findViewById(R.id.btnBack); + mEditName = view.findViewById(R.id.editName); + mEditPhone = view.findViewById(R.id.editPhone); + mBtnAdd = view.findViewById(R.id.btnAdd); + mTxtShwName = view.findViewById(R.id.shwName); + mTxtShwNo = view.findViewById(R.id.shwPhoneNo); + + progressDialog = new ProgressDialog(getContext()); + + //Wire up click event listeners + mBtnBck.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + + //load the main screen fragment + getFragmentManager().beginTransaction().replace(R.id.fragmentHolder,new HomeScreenFragment()).commit(); + } + }); + + mBtnAdd.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + + //attempt to save the data + saveContact(); + } + }); + + return view; + } + + //method to save our contacts on the online db + public void saveContact(){ + + //make sure the form has no blanks + if (TextUtils.isEmpty(mEditName.getText().toString()) || TextUtils.isEmpty(mEditPhone.getText().toString())){ + + //Show error message based on exact error + if (TextUtils.isEmpty(mEditName.getText().toString())){ + Toast.makeText(getContext(),"Please key in a name",Toast.LENGTH_LONG).show(); + } + if (TextUtils.isEmpty(mEditPhone.getText().toString())){ + Toast.makeText(getContext(),"Please key in the phone number",Toast.LENGTH_LONG).show(); + } + }else{ //data set is okay + + //show saving progress dialog + progressDialog.setMessage("Saving contact..."); + progressDialog.setCanceledOnTouchOutside(false); + + //create a hash to save this data + HashMap contactData = new HashMap<>(); + contactData.put("Name",mEditName.getText().toString()); + contactData.put("Phone Number", mEditPhone.getText().toString()); + + //Now send it to FirebaseDB + //Interesting thing learnt. Putting / jumps us to a new child. + //To use authentication, make sure you've enabled identity toolkit in Google APIs console + mDbRef.child(mAuth.getCurrentUser().getUid() + "_contacts").child("save_" + new SimpleDateFormat("dd-MM-yy HH:mm:ss").format(new Date())) + .setValue(contactData).addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + + if (task.isSuccessful()){ + + //dismiss dialog + progressDialog.dismiss(); + + //show success toast + Toast.makeText(getContext(),"Contact added successfully",Toast.LENGTH_LONG).show(); + + //update the text view widgets + mTxtShwName.setText(mEditName.getText().toString()); + mTxtShwNo.setText(mEditPhone.getText().toString()); + + //clear the edit text widgets + mEditName.setText(""); + mEditPhone.setText(""); + + } else{ + + //dismiss dialog + progressDialog.dismiss(); + + //show error message + Toast.makeText(getContext(),"Failed to add contact. Please check your internet connection",Toast.LENGTH_LONG).show(); + } + } + }); + } + } +} diff --git a/app/src/main/java/com/example/ian/sambazaquick/AfricasTalkingGateway.java b/app/src/main/java/com/example/ian/sambazaquick/AfricasTalkingGateway.java new file mode 100644 index 0000000..08e5a62 --- /dev/null +++ b/app/src/main/java/com/example/ian/sambazaquick/AfricasTalkingGateway.java @@ -0,0 +1,516 @@ +package com.example.ian.sambazaquick; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +public class AfricasTalkingGateway +{ + private String _username; + private String _apiKey; + private String _environment; + private int responseCode; + + private static final int HTTP_CODE_OK = 200; + private static final int HTTP_CODE_CREATED = 201; + + //Change debug flag to true to view raw server response + private static final boolean DEBUG = false; + + public AfricasTalkingGateway(String username_, String apiKey_) + { + _username = username_; + _apiKey = apiKey_; + _environment = "production"; + } + + public AfricasTalkingGateway(String username_, String apiKey_, String environment_) + { + _username = username_; + _apiKey = apiKey_; + _environment = environment_; + } + + + //Bulk messages methods + public JSONArray sendMessage(String to_, String message_) throws Exception + { + + HashMap data = new HashMap(); + data.put("username", _username); + data.put("to", to_); + data.put("message", message_); + + return sendMessageImpl(to_, message_, data); + } + + + public JSONArray sendMessage(String to_, String message_, String from_) throws Exception + { + HashMap data = new HashMap(); + data.put("username", _username); + data.put("to", to_); + data.put("message", message_); + + if ( from_.length() > 0 ) data.put("from", from_); + + return sendMessageImpl(to_, message_, data); + } + + + public JSONArray sendMessage(String to_, String message_, String from_, int bulkSMSMode_) throws Exception + { + HashMap data = new HashMap(); + data.put("username", _username); + data.put("to", to_); + data.put("message", message_); + + if ( from_.length() > 0 ) data.put("from", from_); + + data.put("bulkSMSMode", Integer.toString(bulkSMSMode_)); + + return sendMessageImpl(to_, message_, data); + } + + + public JSONArray sendMessage(String to_, String message_, String from_, int bulkSMSMode_, HashMap options_) throws Exception + { + HashMap data = new HashMap(); + data.put("username", _username); + data.put("to", to_); + data.put("message", message_); + + if ( from_.length() > 0 ) data.put("from", from_); + + data.put("bulkSMSMode", Integer.toString(bulkSMSMode_)); + + + if (options_.containsKey("enqueue")) data.put("enqueue", options_.get("enqueue")); + if (options_.containsKey("keyword")) data.put("keyword", options_.get("keyword")); + if (options_.containsKey("linkId")) data.put("linkId", options_.get("linkId")); + if (options_.containsKey("retryDurationInHours")) data.put("retryDurationInHours", options_.get("retryDurationInHours")); + + return sendMessageImpl(to_, message_, data); + } + + + public JSONArray fetchMessages(int lastReceivedId_) throws Exception + { + String requestUrl = getSmsUrl() + "?" + + URLEncoder.encode("username", "UTF-8") + "=" + URLEncoder.encode(_username, "UTF-8") + + "&" + URLEncoder.encode("lastReceivedId", "UTF-8") + "=" + URLEncoder.encode(Integer.toString(lastReceivedId_), "UTF-8"); + + String response = sendGETRequest(requestUrl); + if(responseCode == HTTP_CODE_OK) { + JSONObject jsObject = new JSONObject(response); + return jsObject.getJSONObject("SMSMessageData").getJSONArray("Messages"); + } + + throw new Exception(response.toString()); + } + + + //Subcscription methods + public JSONObject createSubscription(String phoneNumber_, String shortCode_, String keyword_) throws Exception + { + if(phoneNumber_.length() == 0 || shortCode_.length() == 0 || keyword_.length() == 0) + throw new Exception("Please supply phoneNumber, shortCode and keyword"); + + HashMap data_ = new HashMap(); + data_.put("username", _username); + data_.put("phoneNumber", phoneNumber_); + data_.put("shortCode", shortCode_); + data_.put("keyword", keyword_); + String requestUrl = getSubscriptionUrl() + "/create"; + + String response = sendPOSTRequest(data_, requestUrl); + + if(responseCode != HTTP_CODE_CREATED) + throw new Exception(response.toString()); + + JSONObject jsObject = new JSONObject(response); + return jsObject; + } + + + public JSONObject deleteSubscription(String phoneNumber_,String shortCode_, String keyword_) throws Exception + { + if(phoneNumber_.length() == 0 || shortCode_.length() == 0 || keyword_.length() == 0) + throw new Exception("Please supply phone number, short code and keyword"); + + HashMap data_ = new HashMap(); + data_.put("username", _username); + data_.put("phoneNumber", phoneNumber_); + data_.put("shortCode", shortCode_); + data_.put("keyword", keyword_); + String requestUrl = getSubscriptionUrl() + "/delete"; + + String response = sendPOSTRequest(data_, requestUrl); + + if(responseCode != HTTP_CODE_CREATED) + throw new Exception(response.toString()); + + JSONObject jsObject = new JSONObject(response); + return jsObject; + } + + + public JSONArray fetchPremiumSubscriptions (String shortCode_, String keyword_, int lastReceivedId_) throws Exception + { + if(shortCode_.length() == 0 || keyword_.length() == 0) + throw new Exception("Please supply short code and keyword"); + + lastReceivedId_ = lastReceivedId_ > 0? lastReceivedId_ : 0; + String requestUrl = getSubscriptionUrl() + "?username="+_username+"&shortCode="+shortCode_+"&keyword="+keyword_+"&lastReceivedId="+lastReceivedId_; + + String response = sendGETRequest(requestUrl); + if(responseCode == HTTP_CODE_OK) { + JSONObject jsObject = new JSONObject(response); + return jsObject.getJSONArray("responses"); + } + + throw new Exception(response.toString()); + } + + + public JSONArray call(String from_, String to_) throws Exception + { + HashMap data = new HashMap(); + data.put("username", _username); + data.put("from", from_); + data.put("to", to_); + String urlString = getVoiceUrl() + "/call"; + String response = sendPOSTRequest(data, urlString); + + JSONObject jsObject = new JSONObject(response); + + if(jsObject.getString("errorMessage").equals("None")) + return jsObject.getJSONArray("entries"); + throw new Exception(jsObject.getString("errorMessage")); + } + + //Call methods + public JSONArray getNumQueuedCalls(String phoneNumber, String queueName) throws Exception + { + HashMap data = new HashMap(); + data.put("username", _username); + data.put("phoneNumber", phoneNumber); + data.put("queueName", queueName); + + return queuedCalls(data); + } + + + public JSONArray getNumQueuedCalls(String phoneNumber) throws Exception + { + HashMap data = new HashMap(); + data.put("username", _username); + data.put("phoneNumbers", phoneNumber); + + return queuedCalls(data); + } + + + public void uploadMediaFile(String url_, String phoneNumber_) throws Exception + { + HashMap data = new HashMap(); + data.put("username", _username); + data.put("url", url_); + data.put("phoneNumber", phoneNumber_); + String requestUrl = getVoiceUrl() + "/mediaUpload"; + + sendPOSTRequest(data, requestUrl); + } + + + //Airtime methods + public JSONArray sendAirtime(String recipients_) throws Exception + { + HashMap data_ = new HashMap(); + data_.put("username", _username); + data_.put("recipients", recipients_); + String urlString = getAirtimeUrl() + "/send"; + + String response = sendPOSTRequest(data_, urlString); + + if(responseCode == HTTP_CODE_CREATED) { + JSONObject jsObject = new JSONObject(response); + JSONArray results = jsObject.getJSONArray("responses"); + if(results.length() > 0) + return results; + throw new Exception(jsObject.getString("errorMessage")); + } + + throw new Exception(response); + } + + + //User data method + public JSONObject getUserData() throws Exception + { + String requestUrl = getUserDataUrl() + "?username="+_username; + + String response = sendGETRequest(requestUrl); + if(responseCode == HTTP_CODE_OK) { + JSONObject jsObject = new JSONObject(response); + return jsObject.getJSONObject("UserData"); + } + + throw new Exception(response); + } + + public JSONObject initiateMobilePaymentCheckout(String productName_, + String phoneNumber_, + String currencyCode_, + Double amount_, + Map metadata_) throws Exception + { + JSONObject requestBody = new JSONObject() + .put("username", _username) + .put("productName", productName_) + .put("phoneNumber", phoneNumber_) + .put("currencyCode", currencyCode_) + .put("amount", amount_) + .put("metadata", metadata_); + String response = sendJsonPOSTRequest(requestBody.toString(), getMobilePaymentCheckoutUrl()); + return new JSONObject(response); + } + + public JSONArray mobilePaymentB2CRequest(String productName_, + List recipients_) throws Exception + { + List jsonRecipients = new ArrayList(); + for (MobilePaymentB2CRecipient recipient: recipients_) { + jsonRecipients.add(recipient.toJSON()); + } + JSONObject requestBody = new JSONObject() + .put("username", _username) + .put("productName", productName_) + .put("recipients", jsonRecipients); + + if(DEBUG) System.out.println("Raw Request: " + requestBody.toString()); + + String response = sendJsonPOSTRequest(requestBody.toString(), getMobilePaymentB2CUrl()); + JSONObject jsonResponse = new JSONObject(response); + JSONArray entries = jsonResponse.getJSONArray("entries"); + if ( entries.length() > 0 ) return entries; + throw new Exception(jsonResponse.getString("errorMessage")); + } + + public JSONObject mobilePaymentB2BRequest(String productName_, HashMap providerData_, + String currencyCode_, float amount_, HashMap metadata_) throws Exception + { + if(!providerData_.containsKey("provider")) + throw new Exception("Missing field provider"); + + if(!providerData_.containsKey("destinationChannel")) + throw new Exception("Missing field destinationChannel"); + + if(!providerData_.containsKey("destinationAccount")) + throw new Exception("Missing field destinationAccount"); + + if(!providerData_.containsKey("transferType")) + throw new Exception("Missing field transferType"); + + JSONObject requestBody = new JSONObject(); + requestBody.put("username", _username); + requestBody.put("productName", productName_); + requestBody.put("currencyCode", currencyCode_); + requestBody.put("amount", amount_); + requestBody.put("provider", providerData_.get("provider")); + requestBody.put("destinationChannel", providerData_.get("destinationChannel")); + requestBody.put("destinationAccount", providerData_.get("destinationAccount")); + requestBody.put("transferType", providerData_.get("transferType")); + requestBody.put("metadata", new JSONObject(metadata_)); + + if(DEBUG) System.out.println("Raw Request: " + requestBody.toString()); + + String response = sendJsonPOSTRequest(requestBody.toString(), getMobilePaymentB2BUrl()); + JSONObject jsonResponse = new JSONObject(response); + return jsonResponse; + } + + private JSONArray sendMessageImpl(String to_, String message_, HashMap data_) throws Exception { + String response = sendPOSTRequest(data_, getSmsUrl()); + if (responseCode == HTTP_CODE_CREATED) { + JSONObject jsObject = new JSONObject(response); + JSONArray recipients = jsObject.getJSONObject("SMSMessageData").getJSONArray("Recipients"); + if(recipients.length() > 0) return recipients; + + throw new Exception(jsObject.getJSONObject("SMSMessageData").getString("Message")); + } + + throw new Exception(response); + } + + //Private accessor methods + private JSONArray queuedCalls(HashMap data_) throws Exception { + String requestUrl = getVoiceUrl() + "/queueStatus"; + String response = sendPOSTRequest(data_, requestUrl); + JSONObject jsObject = new JSONObject(response); + if(jsObject.getString("errorMessage").equals("None")) + return jsObject.getJSONArray("entries"); + throw new Exception(jsObject.getString("errorMessage")); + } + + private String sendPOSTRequest(HashMap dataMap_, String urlString_) throws Exception { + String data = new String(); + Iterator> it = dataMap_.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry pairs = (Map.Entry)it.next(); + data += URLEncoder.encode(pairs.getKey().toString(), "UTF-8"); + data += "=" + URLEncoder.encode(pairs.getValue().toString(), "UTF-8"); + if ( it.hasNext() ) data += "&"; + } + URL url = new URL(urlString_); + URLConnection conn = url.openConnection(); + conn.setRequestProperty("Accept", "application/json"); + conn.setRequestProperty("apikey", _apiKey); + conn.setDoOutput(true); + return sendPOSTRequestImpl(data, conn); + } + + private String sendJsonPOSTRequest(String data_, String urlString_) throws Exception + { + URL url = new URL(urlString_); + URLConnection conn = url.openConnection(); + conn.setRequestProperty("Content-Type", "application/json"); + conn.setRequestProperty("Accept", "application/json"); + conn.setRequestProperty("apikey", _apiKey); + conn.setDoOutput(true); + return sendPOSTRequestImpl(data_, conn); + } + + private String sendPOSTRequestImpl(String data_, URLConnection conn_) throws Exception { + try { + OutputStreamWriter writer = new OutputStreamWriter(conn_.getOutputStream()); + writer.write(data_); + writer.flush(); + + HttpURLConnection http_conn = (HttpURLConnection)conn_; + responseCode = http_conn.getResponseCode(); + + BufferedReader reader; + boolean passed = true; + + if(responseCode == HTTP_CODE_OK || responseCode == HTTP_CODE_CREATED) { + reader = new BufferedReader(new InputStreamReader(http_conn.getInputStream())); + } + else { + reader = new BufferedReader(new InputStreamReader(http_conn.getErrorStream())); + passed = false; + } + String response = readResponse(reader); + + if(DEBUG) System.out.println("ResponseCode: " + responseCode + " RAW Response: " + response); + + reader.close(); + + if(passed) return response; + + throw new Exception(response); + + } catch (Exception e){ + throw e; + } + } + + private String readResponse(BufferedReader reader) throws Exception + { + StringBuilder response = new StringBuilder(); + String line; + while((line = reader.readLine()) != null) { + response.append(line); + } + return response.toString(); + } + + private String sendGETRequest(String urlString) throws Exception + { + try { + URL url= new URL(urlString); + URLConnection connection = (URLConnection)url.openConnection(); + connection.setRequestProperty("Accept","application/json"); + connection.setRequestProperty("apikey", _apiKey); + + HttpURLConnection http_conn = (HttpURLConnection)connection; + responseCode = http_conn.getResponseCode(); + + BufferedReader reader; + boolean passed = true; + if(responseCode == HTTP_CODE_OK || responseCode == HTTP_CODE_CREATED) { + reader = new BufferedReader(new InputStreamReader(http_conn.getInputStream())); + } + else { + reader = new BufferedReader(new InputStreamReader(http_conn.getErrorStream())); + passed = false; + } + String response = reader.readLine(); + + if(DEBUG) System.out.println(response); + + reader.close(); + + if(passed) return response; + + throw new Exception(response); + } + catch (Exception e) {throw e;} + } + + private String getApiHost() { + return (_environment == "sandbox") ? "https://api.sandbox.africastalking.com" : "https://api.africastalking.com"; + } + + private String getPaymentHost() { + return (_environment == "sandbox") ? "https://payments.sandbox.africastalking.com" : "https://payments.africastalking.com"; + } + + private String getVoiceHost() { + return (_environment == "sandbox") ? "https://voice.sandbox.africastalking.com" : "https://voice.africastalking.com"; + } + + private String getSmsUrl() { + return getApiHost() + "/version1/messaging"; + } + + private String getVoiceUrl() { + return getVoiceHost(); + } + + private String getSubscriptionUrl() { + return getApiHost() + "/version1/subscription"; + } + + private String getUserDataUrl() { + return getApiHost() + "/version1/user"; + } + + private String getAirtimeUrl() { + return getApiHost() + "/version1/airtime"; + } + + private String getMobilePaymentCheckoutUrl() { + return getPaymentHost() + "/mobile/checkout/request"; + } + + private String getMobilePaymentB2BUrl() { + return getPaymentHost() + "/mobile/b2b/request"; + } + + private String getMobilePaymentB2CUrl() { + return getPaymentHost() + "/mobile/b2c/request"; + } +} diff --git a/app/src/main/java/com/example/ian/sambazaquick/HomeScreenFragment.java b/app/src/main/java/com/example/ian/sambazaquick/HomeScreenFragment.java new file mode 100644 index 0000000..74ed0f3 --- /dev/null +++ b/app/src/main/java/com/example/ian/sambazaquick/HomeScreenFragment.java @@ -0,0 +1,85 @@ +package com.example.ian.sambazaquick; + +import android.os.Bundle; +import android.support.v4.app.Fragment; + +//For firebase authentication, to log the user out +import com.google.firebase.auth.FirebaseAuth; + +//For our UI +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; + +public class HomeScreenFragment extends Fragment { + + //For our UI + private Button mBtnAddNewContacts, mBtnSendAirtime, mBtnLogOut; + + //For firebase authentication + private FirebaseAuth mAuth; + + //initialize mAuth in onCreate + @Override + public void onCreate(Bundle savedInstanceState){ + super.onCreate(savedInstanceState); + + mAuth = FirebaseAuth.getInstance(); + } + + //Override onCreateView and load UI, wire it up + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){ + + //remove previous views + container.removeAllViews(); + + //inflate UI + View view = inflater.inflate(R.layout.mainpage_fragment,container,false); + + //get references to our widgets + mBtnAddNewContacts = view.findViewById(R.id.btnAddNewContacts); + mBtnSendAirtime = view.findViewById(R.id.btnSendAirtime); + mBtnLogOut = view.findViewById(R.id.btnLogOut); + + //wire up click event listeners + mBtnAddNewContacts.setOnClickListener(new View.OnClickListener(){ + @Override + public void onClick (View v){ + + //load the add new contacts fragment + getFragmentManager().beginTransaction().setCustomAnimations(R.anim.fade_in,R.anim.fade_out).replace(R.id.fragmentHolder,new AddNewContactsFragment()).commit(); + } + }); + + mBtnSendAirtime.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + + //load the send airtime fragment + getFragmentManager().beginTransaction().setCustomAnimations(R.anim.fade_in,R.anim.fade_out).replace(R.id.fragmentHolder,new SendAirtimeFragment()).commit(); + } + }); + + mBtnLogOut.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + + //invoke method to logout user + logoutUser(); + } + }); + + return view; + } + + //method to log out user + private void logoutUser(){ + + mAuth.signOut(); + + //load log in fragment + getFragmentManager().beginTransaction().replace(R.id.fragmentHolder,new LogInFragment()).commit(); + } +} diff --git a/app/src/main/java/com/example/ian/sambazaquick/LogInFragment.java b/app/src/main/java/com/example/ian/sambazaquick/LogInFragment.java new file mode 100644 index 0000000..6ad79e6 --- /dev/null +++ b/app/src/main/java/com/example/ian/sambazaquick/LogInFragment.java @@ -0,0 +1,139 @@ +package com.example.ian.sambazaquick; + +import android.os.Bundle; +import android.support.v4.app.Fragment; + +import android.app.ProgressDialog; +import android.support.annotation.NonNull; + +//For our UI widgets +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.Button; +import android.widget.Toast; + +//For our firebase authentication +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.auth.AuthResult; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; + +public class LogInFragment extends Fragment { + + //For our firebase authentication + private FirebaseAuth mAuth; + + //For our UI widgets + private EditText mEditEmail, mEditPass; + private Button mBtnLogIn, mBtnSignUp; + private ProgressDialog progressDialog; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + //instantiate FirebaseAuth + mAuth = FirebaseAuth.getInstance(); + + //go direct to homepage if we have a current user logged in + if (mAuth.getCurrentUser() != null) { + + //load the home screen fragment + getFragmentManager().beginTransaction().setCustomAnimations(R.anim.bottom_top, R.anim.top_bottom).replace(R.id.fragmentHolder, new HomeScreenFragment()).commit(); + + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + + //remove previous views + container.removeAllViews(); + + //inflate our UI + View view = inflater.inflate(R.layout.log_in_fragment, container,false); + //instantiate our UI widgets + mEditEmail = view.findViewById(R.id.editEmail); + mEditPass = view.findViewById(R.id.editPass); + mBtnLogIn = view.findViewById(R.id.loginBtn); + mBtnSignUp = view.findViewById(R.id.signupBtn); + progressDialog = new ProgressDialog(getContext()); + + //Set up click event listeners for log in button and sign up button + mBtnLogIn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + + //attempt logging in the user + logInUser(); + } + }); + + mBtnSignUp.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + + //load the sign up fragment + getFragmentManager().beginTransaction().setCustomAnimations(R.anim.right_left, R.anim.expand_left_right).replace(R.id.fragmentHolder, new SignUpFragment()).commit(); + } + }); + + return view; + } + + //Function to log in user + private void logInUser() { + + //get the email and password put in + String email = mEditEmail.getText().toString(); + String pass = mEditPass.getText().toString(); + + //Ensure no string is empty + if (TextUtils.isEmpty(email) || TextUtils.isEmpty(pass)) { + + if (TextUtils.isEmpty(email)) { + + //Show a toast warning that email cannot be empty + Toast.makeText(getContext(), "Email cannot be empty", Toast.LENGTH_LONG).show(); + } + + if (TextUtils.isEmpty(pass)) { + + //Show a toast that password cannot be empty + Toast.makeText(getContext(), "Password cannot be empty", Toast.LENGTH_LONG).show(); + } + + } else { + + //attempt to log in the user + progressDialog.setMessage("Please wait as we log you in"); + progressDialog.setCanceledOnTouchOutside(false); + progressDialog.show(); + mAuth.signInWithEmailAndPassword(email, pass).addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()) { + + //dismiss progress dialog + progressDialog.dismiss(); + + //load the homescreen fragment + getFragmentManager().beginTransaction().setCustomAnimations(R.anim.bottom_top, R.anim.top_bottom).replace(R.id.fragmentHolder, new HomeScreenFragment()).commit(); + + } else { + + //dismiss progress dialog + progressDialog.dismiss(); + + //Show a toast indicating failure + Toast.makeText(getActivity(), "Failed to log you in. Ensure you have a good network connection and your details are okay", Toast.LENGTH_LONG).show(); + } + } + }); + } + } +} diff --git a/app/src/main/java/com/example/ian/sambazaquick/MainActivity.java b/app/src/main/java/com/example/ian/sambazaquick/MainActivity.java new file mode 100644 index 0000000..d860154 --- /dev/null +++ b/app/src/main/java/com/example/ian/sambazaquick/MainActivity.java @@ -0,0 +1,22 @@ +package com.example.ian.sambazaquick; + + +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; + + + +public class MainActivity extends AppCompatActivity { + + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + //load the log in fragment + getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.top_bottom,R.anim.bottom_top).replace(R.id.fragmentHolder,new LogInFragment()).commit(); + + } +} diff --git a/app/src/main/java/com/example/ian/sambazaquick/MobilePaymentB2CRecipient.java b/app/src/main/java/com/example/ian/sambazaquick/MobilePaymentB2CRecipient.java new file mode 100644 index 0000000..837529f --- /dev/null +++ b/app/src/main/java/com/example/ian/sambazaquick/MobilePaymentB2CRecipient.java @@ -0,0 +1,33 @@ +package com.example.ian.sambazaquick; + +import org.json.JSONObject; + +import java.util.HashMap; + +public class MobilePaymentB2CRecipient { + private String _phoneNumber; + private String _currencyCode; + private Double _amount; + private HashMap _metadata; + + public MobilePaymentB2CRecipient(String phoneNumber_, + String currencyCode_, + Double amount_) { + _phoneNumber = phoneNumber_; + _currencyCode = currencyCode_; + _amount = amount_; + _metadata = new HashMap(); + } + + public void addMetadata(String key_, String value_) { + _metadata.put(key_, value_); + } + + public JSONObject toJSON() throws Exception { + return new JSONObject() + .put("phoneNumber", _phoneNumber) + .put("currencyCode", _currencyCode) + .put("amount", _amount) + .put("metadata", _metadata); + } +} diff --git a/app/src/main/java/com/example/ian/sambazaquick/SendAirtimeFragment.java b/app/src/main/java/com/example/ian/sambazaquick/SendAirtimeFragment.java new file mode 100644 index 0000000..d8c4c3f --- /dev/null +++ b/app/src/main/java/com/example/ian/sambazaquick/SendAirtimeFragment.java @@ -0,0 +1,309 @@ +package com.example.ian.sambazaquick; + +import android.app.ProgressDialog; +import android.os.Bundle; +import android.support.v4.app.Fragment; + +//for our UI widgets +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.accessibility.AccessibilityManager; +import android.widget.ImageButton; +import android.widget.EditText; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +//For our firebase database +import com.google.firebase.database.DataSnapshot; +import com.google.firebase.database.DatabaseError; +import com.google.firebase.database.FirebaseDatabase; +import com.google.firebase.database.DatabaseReference; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.database.ValueEventListener; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +//For Africa's talking API integration +import org.json.*; + +public class SendAirtimeFragment extends Fragment { + + //For our UI widgets + private ImageButton mBtnBack; + private EditText mEditPhoneNo; + private EditText mEditAmnt; + private TextView mShwName, mShwTotalAmnt; + private ProgressDialog progressDialog; + private ImageView mImgError; + private Button mBtnAdd, mBtnSend; + + //For our UI works/magic + private boolean clickOnce = true; + + //For storing details of who the airtime is being sent to + private String phoneNo; + private String amnt; + + //To store the total amnt of credit to be bought + private int mTotalAmnt = 0; + + //Storing our contacts List + private List contactsList = new ArrayList<>(); + + //My JSONArray for recepients + JSONArray recepients = new JSONArray(); + + //for firebase + private DatabaseReference mDbRef; + private ValueEventListener dbListener; + + + @Override + public void onCreate (Bundle savedInstanceState){ + super.onCreate(savedInstanceState); + + //instantiate our mDbRef + mDbRef = FirebaseDatabase.getInstance().getReference(); + + //instantiate our listener + dbListener = new ValueEventListener() { + @Override + public void onDataChange(DataSnapshot dataSnapshot) { + + //call method to load our contacts list + loadContactsList((Map) dataSnapshot.getValue()); + } + + @Override + public void onCancelled(DatabaseError databaseError) { + + Toast.makeText(getActivity(),"Error loading your contacts. Please check your internet connection",Toast.LENGTH_LONG).show(); + } + }; + + //set up our listener + mDbRef.child(FirebaseAuth.getInstance().getCurrentUser().getUid() + "_contacts").addValueEventListener(dbListener); + + } + + @Override + public View onCreateView (LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState){ + + container.removeAllViews(); + + //Inflate our UI and wire it up + View view = inflater.inflate(R.layout.send_airtime_fragment,container,false); + mBtnBack = view.findViewById(R.id.btnBack); + mEditPhoneNo = view.findViewById(R.id.keyNumber); + mEditAmnt = view.findViewById(R.id.keyAmount); + mShwName = view.findViewById(R.id.shwName); + mShwTotalAmnt = view.findViewById(R.id.shwTotalAirtime); + mImgError = view.findViewById(R.id.imgError); + mBtnAdd = view.findViewById(R.id.btnAddAnother); + mBtnSend = view.findViewById(R.id.btnSendAirtime); + + //set the visibility of amount and imgError to gone + mEditAmnt.setVisibility(View.GONE); + mImgError.setVisibility(View.GONE); + + //set the button add text to Next + mBtnAdd.setText("Next"); + mBtnAdd.setBackgroundColor(Integer.valueOf(R.color.orangeShade)); + + //Listener for clicks on btnAdd + mBtnAdd.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + + MyContacts c = null; + + if (clickOnce){ + + boolean found = false; + for (int i = 0; i < contactsList.size();i++){ + c = contactsList.get(i); + + if (c.getPhoneNo() == mEditPhoneNo.getText().toString()){ + //This contact exists in the user's contact list + //Load the number in our string + phoneNo = mEditPhoneNo.getText().toString(); + + //show the amounts widget and change the next button to add new contact + mEditAmnt.setVisibility(View.VISIBLE); + mBtnAdd.setBackgroundResource(R.drawable.add_another_contact_btn_bg); + mBtnAdd.setBackgroundColor(Integer.valueOf(R.color.white)); + + clickOnce = !clickOnce; + found = !found; + + break; + } + } + + if (found){ + //Show toast with error + Toast.makeText(getActivity(),"This number doesn't exist in your contacts",Toast.LENGTH_LONG).show(); + } + } else{ //dealing with amount here, + + if (TextUtils.isEmpty(mEditAmnt.getText().toString())){ + Toast.makeText(getActivity(),"Please key in the amount", Toast.LENGTH_LONG).show(); + } else if (mEditAmnt.getText().toString().contains(" ")) { + + //Do not allow for spaces + Toast.makeText(getContext(),"Leave no space in your text",Toast.LENGTH_LONG).show(); + } else { + + //amount has been keyed in + amnt = mEditAmnt.getText().toString(); + + //update the amount variable + mTotalAmnt += Integer.valueOf(amnt); + + //feed this data to our JSONObjectArray + try { + recepients.put(new JSONObject().put("phoneNumber", phoneNo).put("amount", "KES " + amnt)); + } catch (JSONException e) { + e.printStackTrace(); + } + //change the clickOnce + clickOnce = !clickOnce; + + //Update the textviews + mShwName.setText(mShwName.getText().toString() + c.getName() + ","); + mShwTotalAmnt.setText(String.valueOf(mTotalAmnt)); + + //set the button add text to Next + mBtnAdd.setText("Next"); + mBtnAdd.setBackgroundColor(Integer.valueOf(R.color.orangeShade)); + //set the visibility of amount and imgError to gone + mEditAmnt.setVisibility(View.GONE); + + //Handle click on send + } + } + } + }); + + mBtnBack.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + getFragmentManager().beginTransaction().replace(R.id.fragmentHolder, new HomeScreenFragment()).commit(); + } + }); + + mBtnSend.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + + //ensure our JSONarray is not empty + if (recepients == null){ + Toast.makeText(getContext(),"Please provide recepients and an amount",Toast.LENGTH_LONG).show(); + }else{ + + //invoke sendAirtimeMethod + sendAirtime(); + } + + } + }); + + return view; + } + + private void loadContactsList(Map dbData){ + + //Start our progress dialog + progressDialog = new ProgressDialog(getContext()); + progressDialog.setMessage("Retrieving your contacts list"); + progressDialog.setCanceledOnTouchOutside(false); + progressDialog.show(); + + //create an instance of our node + MyContacts myContacts = null; + + if (dbData == null){ + Toast.makeText(getContext(),"No contacts to load",Toast.LENGTH_LONG).show(); + } else { + + Map contact = null; + //gather all contacts data + for (Map.Entry entry: dbData.entrySet()){ + + myContacts = new MyContacts(); + + contact = (Map) entry.getValue(); + + //Get the necessary data + myContacts.setName((String) contact.get("Name")); + myContacts.setPhoneNo((String) contact.get("Phone Number")); + + //push to the array list + contactsList.add(myContacts); + + } + } + + //Remove listener. Thus this will only fire once + mDbRef.removeEventListener(dbListener); + progressDialog.dismiss(); + + } + + private void sendAirtime(){ + + String username = "sandbox"; + String apiKey = "8d98d8c1b6efbcb51daa68a3dc93756b3ad3b7eddc68fd28668beb474a502ffd"; + + String recipientStringFormat = recepients.toString(); + + //Create an instance of GateWayClass + AfricasTalkingGateway gateway = new AfricasTalkingGateway(username,apiKey,"sandbox"); + + try { + JSONArray results = gateway.sendAirtime(recipientStringFormat); + int length = results.length(); + for(int i = 0; i < length; i++) { + JSONObject result = results.getJSONObject(i); + Log.e("Error",result.getString("status")); + Log.e("Error",result.getString("amount")); + Log.e("Error",result.getString("phoneNumber")); + System.out.println(result.getString("discount")); + System.out.println(result.getString("requestId")); + //Error message is important when the status is not Success + System.out.println(result.getString("errorMessage")); + } + } catch(Exception e){ + System.out.println(e.getMessage()); + } + } + + //an inner class to act as our node for contact list + private class MyContacts{ + + private String name; + private String phoneNo; + + protected void setName(String name){ + this.name = name; + } + protected String getName(){ + return name; + } + + protected void setPhoneNo(String phoneNo){ + this.phoneNo = phoneNo; + } + + protected String getPhoneNo(){ + return phoneNo; + } + } +} diff --git a/app/src/main/java/com/example/ian/sambazaquick/SignUpFragment.java b/app/src/main/java/com/example/ian/sambazaquick/SignUpFragment.java new file mode 100644 index 0000000..2ee4f29 --- /dev/null +++ b/app/src/main/java/com/example/ian/sambazaquick/SignUpFragment.java @@ -0,0 +1,138 @@ +package com.example.ian.sambazaquick; + +import android.app.ProgressDialog; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; + +//For our UI widgets +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.Button; +import android.widget.ImageButton; +import android.widget.Toast; + +//For our firebase authentication +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.firebase.auth.AuthResult; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.auth.FirebaseUser; + +public class SignUpFragment extends Fragment { + + //For our firebase authentication + private FirebaseAuth mAuth; + + //For our UI widgets + private EditText mEditEmail, mEditPass, mConfirmPass; + private Button mBtnSignUp; + private ImageButton mBtnBack; + private ProgressDialog progressDialog; + + //Overriding onCreate to instantiate mAuth + @Override + public void onCreate(Bundle savedInstanceState){ + super.onCreate(savedInstanceState); + + //mAuth = FirebaseAuth.getInstance(); + } + + //now, override onCreateView to load the UI and wire it up + @Override + public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){ + + //remove the previous views. Sometimes necessary + container.removeAllViews(); + + //load our view + View view = inflater.inflate(R.layout.sign_up_fragment,container,false); + + //get our UI references + mEditEmail = view.findViewById(R.id.editEmail); + mEditPass = view.findViewById(R.id.editPass); + mConfirmPass = view.findViewById(R.id.confirmPass); + mBtnSignUp = view.findViewById(R.id.btnSignUp); + mBtnBack = view.findViewById(R.id.back); + progressDialog = new ProgressDialog(getContext()); + + //Wire our click event listener for the sign up button + mBtnSignUp.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + + //attempt to sign up the user + signUpNewUser(); + } + }); + + mBtnBack.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + + //load the log in fragment + getFragmentManager().beginTransaction().replace(R.id.fragmentHolder,new LogInFragment()).commit(); + } + }); + + return view; + } + + //Method to sign up our new user + private void signUpNewUser(){ + + //confirm that none of the fields are empty + if (TextUtils.isEmpty(mEditEmail.getText().toString()) || TextUtils.isEmpty(mEditPass.getText()) || TextUtils.isEmpty(mConfirmPass.getText().toString())){ + + //Show a message based on which one exactly is empty + if (TextUtils.isEmpty(mEditEmail.getText().toString())){ + Toast.makeText(getContext(),"Email field cannot be empty",Toast.LENGTH_LONG).show(); + } + if (TextUtils.isEmpty(mEditPass.getText().toString())){ + Toast.makeText(getContext(),"Password field cannot be empty",Toast.LENGTH_LONG).show(); + } + if (TextUtils.isEmpty(mConfirmPass.getText().toString())){ + Toast.makeText(getContext(),"Please confirm your password",Toast.LENGTH_LONG).show(); + } + } else if (!(mEditPass.getText().toString()).equals(mConfirmPass.getText().toString())){ //A test to ensure the password fields match + + Toast.makeText(getContext(),"Your passwords don't match",Toast.LENGTH_LONG).show(); + } else{ //No empty field, passwords match + + String email = mEditEmail.getText().toString(); + String pass = mEditPass.getText().toString(); + progressDialog.setMessage("Signing you up"); + progressDialog.setCanceledOnTouchOutside(false); + progressDialog.show(); + + mAuth = FirebaseAuth.getInstance(); + mAuth.createUserWithEmailAndPassword(email,pass).addOnCompleteListener( new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + + + if (task.isSuccessful()){ + + //get the current user + mAuth.getCurrentUser(); + progressDialog.dismiss(); + + //load the home screen fragment + getFragmentManager().beginTransaction().setCustomAnimations(R.anim.bottom_top,R.anim.top_bottom).replace(R.id.fragmentHolder,new HomeScreenFragment()).commit(); + }else{ + + //use toast to show error in signing up user + + Toast.makeText(getContext(),"Failed to sign up. Make sure you have a good internet connection and your " + + "password is at least 8 characters long" + task.getException().getMessage().toString(),Toast.LENGTH_LONG).show(); + + progressDialog.dismiss(); + } + } + }); + } + } +} diff --git a/app/src/main/res/anim/bottom_top.xml b/app/src/main/res/anim/bottom_top.xml new file mode 100644 index 0000000..8a64f36 --- /dev/null +++ b/app/src/main/res/anim/bottom_top.xml @@ -0,0 +1,13 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/bounce.xml b/app/src/main/res/anim/bounce.xml new file mode 100644 index 0000000..da9ad4d --- /dev/null +++ b/app/src/main/res/anim/bounce.xml @@ -0,0 +1,14 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/close_along_x.xml b/app/src/main/res/anim/close_along_x.xml new file mode 100644 index 0000000..38c080f --- /dev/null +++ b/app/src/main/res/anim/close_along_x.xml @@ -0,0 +1,16 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/expand_left_right.xml b/app/src/main/res/anim/expand_left_right.xml new file mode 100644 index 0000000..c2ac784 --- /dev/null +++ b/app/src/main/res/anim/expand_left_right.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/fade_in.xml b/app/src/main/res/anim/fade_in.xml new file mode 100644 index 0000000..884a84c --- /dev/null +++ b/app/src/main/res/anim/fade_in.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/fade_in_signin.xml b/app/src/main/res/anim/fade_in_signin.xml new file mode 100644 index 0000000..50ca53e --- /dev/null +++ b/app/src/main/res/anim/fade_in_signin.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/fade_out.xml b/app/src/main/res/anim/fade_out.xml new file mode 100644 index 0000000..538591a --- /dev/null +++ b/app/src/main/res/anim/fade_out.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/flashing_alpha.xml b/app/src/main/res/anim/flashing_alpha.xml new file mode 100644 index 0000000..fcb83a0 --- /dev/null +++ b/app/src/main/res/anim/flashing_alpha.xml @@ -0,0 +1,21 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/right_left.xml b/app/src/main/res/anim/right_left.xml new file mode 100644 index 0000000..a1e7822 --- /dev/null +++ b/app/src/main/res/anim/right_left.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/top_bottom.xml b/app/src/main/res/anim/top_bottom.xml new file mode 100644 index 0000000..0a6b701 --- /dev/null +++ b/app/src/main/res/anim/top_bottom.xml @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/add_another_contact_btn_bg.png b/app/src/main/res/drawable-hdpi/add_another_contact_btn_bg.png new file mode 100644 index 0000000..4356089 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/add_another_contact_btn_bg.png differ diff --git a/app/src/main/res/drawable-hdpi/add_btn_bg.png b/app/src/main/res/drawable-hdpi/add_btn_bg.png new file mode 100644 index 0000000..8b3ce77 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/add_btn_bg.png differ diff --git a/app/src/main/res/drawable-hdpi/add_contacts_txt.png b/app/src/main/res/drawable-hdpi/add_contacts_txt.png new file mode 100644 index 0000000..65a1f41 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/add_contacts_txt.png differ diff --git a/app/src/main/res/drawable-hdpi/add_new_contacts_btn_bg.png b/app/src/main/res/drawable-hdpi/add_new_contacts_btn_bg.png new file mode 100644 index 0000000..a564d6c Binary files /dev/null and b/app/src/main/res/drawable-hdpi/add_new_contacts_btn_bg.png differ diff --git a/app/src/main/res/drawable-hdpi/enter_amount_txt.png b/app/src/main/res/drawable-hdpi/enter_amount_txt.png new file mode 100644 index 0000000..872cc7e Binary files /dev/null and b/app/src/main/res/drawable-hdpi/enter_amount_txt.png differ diff --git a/app/src/main/res/drawable-hdpi/home_txt.png b/app/src/main/res/drawable-hdpi/home_txt.png new file mode 100644 index 0000000..0163d0e Binary files /dev/null and b/app/src/main/res/drawable-hdpi/home_txt.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_arrow_back.png b/app/src/main/res/drawable-hdpi/ic_arrow_back.png new file mode 100644 index 0000000..9370875 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_arrow_back.png differ diff --git a/app/src/main/res/drawable-hdpi/key_in_phone_number_txt.png b/app/src/main/res/drawable-hdpi/key_in_phone_number_txt.png new file mode 100644 index 0000000..a42a3d0 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/key_in_phone_number_txt.png differ diff --git a/app/src/main/res/drawable-hdpi/list_of_contacts_youve_just_added_txt.png b/app/src/main/res/drawable-hdpi/list_of_contacts_youve_just_added_txt.png new file mode 100644 index 0000000..61bfcd2 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/list_of_contacts_youve_just_added_txt.png differ diff --git a/app/src/main/res/drawable-hdpi/log_in_txt.png b/app/src/main/res/drawable-hdpi/log_in_txt.png new file mode 100644 index 0000000..94d263b Binary files /dev/null and b/app/src/main/res/drawable-hdpi/log_in_txt.png differ diff --git a/app/src/main/res/drawable-hdpi/log_out_btn_bg.png b/app/src/main/res/drawable-hdpi/log_out_btn_bg.png new file mode 100644 index 0000000..9e2937b Binary files /dev/null and b/app/src/main/res/drawable-hdpi/log_out_btn_bg.png differ diff --git a/app/src/main/res/drawable-hdpi/login_btn_bg.png b/app/src/main/res/drawable-hdpi/login_btn_bg.png new file mode 100644 index 0000000..e8c0dce Binary files /dev/null and b/app/src/main/res/drawable-hdpi/login_btn_bg.png differ diff --git a/app/src/main/res/drawable-hdpi/name_txt.png b/app/src/main/res/drawable-hdpi/name_txt.png new file mode 100644 index 0000000..395029f Binary files /dev/null and b/app/src/main/res/drawable-hdpi/name_txt.png differ diff --git a/app/src/main/res/drawable-hdpi/open_an_acc_txt.png b/app/src/main/res/drawable-hdpi/open_an_acc_txt.png new file mode 100644 index 0000000..66fd3f4 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/open_an_acc_txt.png differ diff --git a/app/src/main/res/drawable-hdpi/phone_number_txt.png b/app/src/main/res/drawable-hdpi/phone_number_txt.png new file mode 100644 index 0000000..938ae1b Binary files /dev/null and b/app/src/main/res/drawable-hdpi/phone_number_txt.png differ diff --git a/app/src/main/res/drawable-hdpi/red_warning_icon.png b/app/src/main/res/drawable-hdpi/red_warning_icon.png new file mode 100644 index 0000000..bce00a2 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/red_warning_icon.png differ diff --git a/app/src/main/res/drawable-hdpi/sambaza_header.png b/app/src/main/res/drawable-hdpi/sambaza_header.png new file mode 100644 index 0000000..a8ab4eb Binary files /dev/null and b/app/src/main/res/drawable-hdpi/sambaza_header.png differ diff --git a/app/src/main/res/drawable-hdpi/selected_contacts_txt.png b/app/src/main/res/drawable-hdpi/selected_contacts_txt.png new file mode 100644 index 0000000..105ff73 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/selected_contacts_txt.png differ diff --git a/app/src/main/res/drawable-hdpi/send_airtime_btn_bg.png b/app/src/main/res/drawable-hdpi/send_airtime_btn_bg.png new file mode 100644 index 0000000..fb441d8 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/send_airtime_btn_bg.png differ diff --git a/app/src/main/res/drawable-hdpi/send_airtime_txt.png b/app/src/main/res/drawable-hdpi/send_airtime_txt.png new file mode 100644 index 0000000..52963c2 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/send_airtime_txt.png differ diff --git a/app/src/main/res/drawable-hdpi/send_btn_bg.png b/app/src/main/res/drawable-hdpi/send_btn_bg.png new file mode 100644 index 0000000..51c53e0 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/send_btn_bg.png differ diff --git a/app/src/main/res/drawable-hdpi/sign_up_btn_bg.png b/app/src/main/res/drawable-hdpi/sign_up_btn_bg.png new file mode 100644 index 0000000..9f7da57 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/sign_up_btn_bg.png differ diff --git a/app/src/main/res/drawable-hdpi/sign_up_txt.png b/app/src/main/res/drawable-hdpi/sign_up_txt.png new file mode 100644 index 0000000..2c9a57d Binary files /dev/null and b/app/src/main/res/drawable-hdpi/sign_up_txt.png differ diff --git a/app/src/main/res/drawable-ldpi/add_another_contact_btn_bg.png b/app/src/main/res/drawable-ldpi/add_another_contact_btn_bg.png new file mode 100644 index 0000000..3505414 Binary files /dev/null and b/app/src/main/res/drawable-ldpi/add_another_contact_btn_bg.png differ diff --git a/app/src/main/res/drawable-ldpi/add_btn_bg.png b/app/src/main/res/drawable-ldpi/add_btn_bg.png new file mode 100644 index 0000000..137d0c2 Binary files /dev/null and b/app/src/main/res/drawable-ldpi/add_btn_bg.png differ diff --git a/app/src/main/res/drawable-ldpi/add_contacts_txt.png b/app/src/main/res/drawable-ldpi/add_contacts_txt.png new file mode 100644 index 0000000..160f333 Binary files /dev/null and b/app/src/main/res/drawable-ldpi/add_contacts_txt.png differ diff --git a/app/src/main/res/drawable-ldpi/add_new_contacts_btn_bg.png b/app/src/main/res/drawable-ldpi/add_new_contacts_btn_bg.png new file mode 100644 index 0000000..73b33cb Binary files /dev/null and b/app/src/main/res/drawable-ldpi/add_new_contacts_btn_bg.png differ diff --git a/app/src/main/res/drawable-ldpi/enter_amount_txt.png b/app/src/main/res/drawable-ldpi/enter_amount_txt.png new file mode 100644 index 0000000..dc1736b Binary files /dev/null and b/app/src/main/res/drawable-ldpi/enter_amount_txt.png differ diff --git a/app/src/main/res/drawable-ldpi/home_txt.png b/app/src/main/res/drawable-ldpi/home_txt.png new file mode 100644 index 0000000..02e4701 Binary files /dev/null and b/app/src/main/res/drawable-ldpi/home_txt.png differ diff --git a/app/src/main/res/drawable-ldpi/ic_arrow_back.png b/app/src/main/res/drawable-ldpi/ic_arrow_back.png new file mode 100644 index 0000000..e21ceab Binary files /dev/null and b/app/src/main/res/drawable-ldpi/ic_arrow_back.png differ diff --git a/app/src/main/res/drawable-ldpi/key_in_phone_number_txt.png b/app/src/main/res/drawable-ldpi/key_in_phone_number_txt.png new file mode 100644 index 0000000..c79b31b Binary files /dev/null and b/app/src/main/res/drawable-ldpi/key_in_phone_number_txt.png differ diff --git a/app/src/main/res/drawable-ldpi/list_of_contacts_youve_just_added_txt.png b/app/src/main/res/drawable-ldpi/list_of_contacts_youve_just_added_txt.png new file mode 100644 index 0000000..30f58f8 Binary files /dev/null and b/app/src/main/res/drawable-ldpi/list_of_contacts_youve_just_added_txt.png differ diff --git a/app/src/main/res/drawable-ldpi/log_in_txt.png b/app/src/main/res/drawable-ldpi/log_in_txt.png new file mode 100644 index 0000000..41e06dd Binary files /dev/null and b/app/src/main/res/drawable-ldpi/log_in_txt.png differ diff --git a/app/src/main/res/drawable-ldpi/log_out_btn_bg.png b/app/src/main/res/drawable-ldpi/log_out_btn_bg.png new file mode 100644 index 0000000..e78aa3f Binary files /dev/null and b/app/src/main/res/drawable-ldpi/log_out_btn_bg.png differ diff --git a/app/src/main/res/drawable-ldpi/login_btn_bg.png b/app/src/main/res/drawable-ldpi/login_btn_bg.png new file mode 100644 index 0000000..95cbd7a Binary files /dev/null and b/app/src/main/res/drawable-ldpi/login_btn_bg.png differ diff --git a/app/src/main/res/drawable-ldpi/name_txt.png b/app/src/main/res/drawable-ldpi/name_txt.png new file mode 100644 index 0000000..18e2dea Binary files /dev/null and b/app/src/main/res/drawable-ldpi/name_txt.png differ diff --git a/app/src/main/res/drawable-ldpi/open_an_acc_txt.png b/app/src/main/res/drawable-ldpi/open_an_acc_txt.png new file mode 100644 index 0000000..1f27011 Binary files /dev/null and b/app/src/main/res/drawable-ldpi/open_an_acc_txt.png differ diff --git a/app/src/main/res/drawable-ldpi/phone_number_txt.png b/app/src/main/res/drawable-ldpi/phone_number_txt.png new file mode 100644 index 0000000..e950c08 Binary files /dev/null and b/app/src/main/res/drawable-ldpi/phone_number_txt.png differ diff --git a/app/src/main/res/drawable-ldpi/red_warning_icon.png b/app/src/main/res/drawable-ldpi/red_warning_icon.png new file mode 100644 index 0000000..104a4ef Binary files /dev/null and b/app/src/main/res/drawable-ldpi/red_warning_icon.png differ diff --git a/app/src/main/res/drawable-ldpi/sambaza_header.png b/app/src/main/res/drawable-ldpi/sambaza_header.png new file mode 100644 index 0000000..5fd196b Binary files /dev/null and b/app/src/main/res/drawable-ldpi/sambaza_header.png differ diff --git a/app/src/main/res/drawable-ldpi/selected_contacts_txt.png b/app/src/main/res/drawable-ldpi/selected_contacts_txt.png new file mode 100644 index 0000000..bf4c586 Binary files /dev/null and b/app/src/main/res/drawable-ldpi/selected_contacts_txt.png differ diff --git a/app/src/main/res/drawable-ldpi/send_airtime_btn_bg.png b/app/src/main/res/drawable-ldpi/send_airtime_btn_bg.png new file mode 100644 index 0000000..2e94b0d Binary files /dev/null and b/app/src/main/res/drawable-ldpi/send_airtime_btn_bg.png differ diff --git a/app/src/main/res/drawable-ldpi/send_airtime_txt.png b/app/src/main/res/drawable-ldpi/send_airtime_txt.png new file mode 100644 index 0000000..ddaed9c Binary files /dev/null and b/app/src/main/res/drawable-ldpi/send_airtime_txt.png differ diff --git a/app/src/main/res/drawable-ldpi/send_btn_bg.png b/app/src/main/res/drawable-ldpi/send_btn_bg.png new file mode 100644 index 0000000..0798eab Binary files /dev/null and b/app/src/main/res/drawable-ldpi/send_btn_bg.png differ diff --git a/app/src/main/res/drawable-ldpi/sign_up_btn_bg.png b/app/src/main/res/drawable-ldpi/sign_up_btn_bg.png new file mode 100644 index 0000000..e28896c Binary files /dev/null and b/app/src/main/res/drawable-ldpi/sign_up_btn_bg.png differ diff --git a/app/src/main/res/drawable-ldpi/sign_up_txt.png b/app/src/main/res/drawable-ldpi/sign_up_txt.png new file mode 100644 index 0000000..271ccc4 Binary files /dev/null and b/app/src/main/res/drawable-ldpi/sign_up_txt.png differ diff --git a/app/src/main/res/drawable-mdpi/add_another_contact_btn_bg.png b/app/src/main/res/drawable-mdpi/add_another_contact_btn_bg.png new file mode 100644 index 0000000..128c1ce Binary files /dev/null and b/app/src/main/res/drawable-mdpi/add_another_contact_btn_bg.png differ diff --git a/app/src/main/res/drawable-mdpi/add_btn_bg.png b/app/src/main/res/drawable-mdpi/add_btn_bg.png new file mode 100644 index 0000000..b3f9764 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/add_btn_bg.png differ diff --git a/app/src/main/res/drawable-mdpi/add_contacts_txt.png b/app/src/main/res/drawable-mdpi/add_contacts_txt.png new file mode 100644 index 0000000..1feb128 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/add_contacts_txt.png differ diff --git a/app/src/main/res/drawable-mdpi/add_new_contacts_btn_bg.png b/app/src/main/res/drawable-mdpi/add_new_contacts_btn_bg.png new file mode 100644 index 0000000..5128c54 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/add_new_contacts_btn_bg.png differ diff --git a/app/src/main/res/drawable-mdpi/enter_amount_txt.png b/app/src/main/res/drawable-mdpi/enter_amount_txt.png new file mode 100644 index 0000000..407032a Binary files /dev/null and b/app/src/main/res/drawable-mdpi/enter_amount_txt.png differ diff --git a/app/src/main/res/drawable-mdpi/home_txt.png b/app/src/main/res/drawable-mdpi/home_txt.png new file mode 100644 index 0000000..f7b8f23 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/home_txt.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_arrow_back.png b/app/src/main/res/drawable-mdpi/ic_arrow_back.png new file mode 100644 index 0000000..4c2e4f3 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_arrow_back.png differ diff --git a/app/src/main/res/drawable-mdpi/key_in_phone_number_txt.png b/app/src/main/res/drawable-mdpi/key_in_phone_number_txt.png new file mode 100644 index 0000000..2ad644a Binary files /dev/null and b/app/src/main/res/drawable-mdpi/key_in_phone_number_txt.png differ diff --git a/app/src/main/res/drawable-mdpi/list_of_contacts_youve_just_added_txt.png b/app/src/main/res/drawable-mdpi/list_of_contacts_youve_just_added_txt.png new file mode 100644 index 0000000..6635187 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/list_of_contacts_youve_just_added_txt.png differ diff --git a/app/src/main/res/drawable-mdpi/log_in_txt.png b/app/src/main/res/drawable-mdpi/log_in_txt.png new file mode 100644 index 0000000..0397931 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/log_in_txt.png differ diff --git a/app/src/main/res/drawable-mdpi/log_out_btn_bg.png b/app/src/main/res/drawable-mdpi/log_out_btn_bg.png new file mode 100644 index 0000000..808019f Binary files /dev/null and b/app/src/main/res/drawable-mdpi/log_out_btn_bg.png differ diff --git a/app/src/main/res/drawable-mdpi/login_btn_bg.png b/app/src/main/res/drawable-mdpi/login_btn_bg.png new file mode 100644 index 0000000..3bd314e Binary files /dev/null and b/app/src/main/res/drawable-mdpi/login_btn_bg.png differ diff --git a/app/src/main/res/drawable-mdpi/name_txt.png b/app/src/main/res/drawable-mdpi/name_txt.png new file mode 100644 index 0000000..0d88053 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/name_txt.png differ diff --git a/app/src/main/res/drawable-mdpi/open_an_acc_txt.png b/app/src/main/res/drawable-mdpi/open_an_acc_txt.png new file mode 100644 index 0000000..1efb8c9 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/open_an_acc_txt.png differ diff --git a/app/src/main/res/drawable-mdpi/phone_number_txt.png b/app/src/main/res/drawable-mdpi/phone_number_txt.png new file mode 100644 index 0000000..3e8ab44 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/phone_number_txt.png differ diff --git a/app/src/main/res/drawable-mdpi/red_warning_icon.png b/app/src/main/res/drawable-mdpi/red_warning_icon.png new file mode 100644 index 0000000..6370c1a Binary files /dev/null and b/app/src/main/res/drawable-mdpi/red_warning_icon.png differ diff --git a/app/src/main/res/drawable-mdpi/sambaza_header.png b/app/src/main/res/drawable-mdpi/sambaza_header.png new file mode 100644 index 0000000..e159304 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/sambaza_header.png differ diff --git a/app/src/main/res/drawable-mdpi/selected_contacts_txt.png b/app/src/main/res/drawable-mdpi/selected_contacts_txt.png new file mode 100644 index 0000000..5f6097c Binary files /dev/null and b/app/src/main/res/drawable-mdpi/selected_contacts_txt.png differ diff --git a/app/src/main/res/drawable-mdpi/send_airtime_btn_bg.png b/app/src/main/res/drawable-mdpi/send_airtime_btn_bg.png new file mode 100644 index 0000000..a961f9f Binary files /dev/null and b/app/src/main/res/drawable-mdpi/send_airtime_btn_bg.png differ diff --git a/app/src/main/res/drawable-mdpi/send_airtime_txt.png b/app/src/main/res/drawable-mdpi/send_airtime_txt.png new file mode 100644 index 0000000..e838134 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/send_airtime_txt.png differ diff --git a/app/src/main/res/drawable-mdpi/send_btn_bg.png b/app/src/main/res/drawable-mdpi/send_btn_bg.png new file mode 100644 index 0000000..64d133c Binary files /dev/null and b/app/src/main/res/drawable-mdpi/send_btn_bg.png differ diff --git a/app/src/main/res/drawable-mdpi/sign_up_btn_bg.png b/app/src/main/res/drawable-mdpi/sign_up_btn_bg.png new file mode 100644 index 0000000..185c95e Binary files /dev/null and b/app/src/main/res/drawable-mdpi/sign_up_btn_bg.png differ diff --git a/app/src/main/res/drawable-mdpi/sign_up_txt.png b/app/src/main/res/drawable-mdpi/sign_up_txt.png new file mode 100644 index 0000000..e729c78 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/sign_up_txt.png differ diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..c7bd21d --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable-xhdpi/add_another_contact_btn_bg.png b/app/src/main/res/drawable-xhdpi/add_another_contact_btn_bg.png new file mode 100644 index 0000000..008ffe4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/add_another_contact_btn_bg.png differ diff --git a/app/src/main/res/drawable-xhdpi/add_btn_bg.png b/app/src/main/res/drawable-xhdpi/add_btn_bg.png new file mode 100644 index 0000000..04598d1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/add_btn_bg.png differ diff --git a/app/src/main/res/drawable-xhdpi/add_contacts_txt.png b/app/src/main/res/drawable-xhdpi/add_contacts_txt.png new file mode 100644 index 0000000..2ed14d0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/add_contacts_txt.png differ diff --git a/app/src/main/res/drawable-xhdpi/add_new_contacts_btn_bg.png b/app/src/main/res/drawable-xhdpi/add_new_contacts_btn_bg.png new file mode 100644 index 0000000..ed9b911 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/add_new_contacts_btn_bg.png differ diff --git a/app/src/main/res/drawable-xhdpi/enter_amount_txt.png b/app/src/main/res/drawable-xhdpi/enter_amount_txt.png new file mode 100644 index 0000000..cb9066f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/enter_amount_txt.png differ diff --git a/app/src/main/res/drawable-xhdpi/home_txt.png b/app/src/main/res/drawable-xhdpi/home_txt.png new file mode 100644 index 0000000..921d26e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/home_txt.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_arrow_back.png b/app/src/main/res/drawable-xhdpi/ic_arrow_back.png new file mode 100644 index 0000000..9999f72 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_arrow_back.png differ diff --git a/app/src/main/res/drawable-xhdpi/key_in_phone_number_txt.png b/app/src/main/res/drawable-xhdpi/key_in_phone_number_txt.png new file mode 100644 index 0000000..f219ace Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/key_in_phone_number_txt.png differ diff --git a/app/src/main/res/drawable-xhdpi/list_of_contacts_youve_just_added_txt.png b/app/src/main/res/drawable-xhdpi/list_of_contacts_youve_just_added_txt.png new file mode 100644 index 0000000..4d1c3fb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/list_of_contacts_youve_just_added_txt.png differ diff --git a/app/src/main/res/drawable-xhdpi/log_in_txt.png b/app/src/main/res/drawable-xhdpi/log_in_txt.png new file mode 100644 index 0000000..20acff9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/log_in_txt.png differ diff --git a/app/src/main/res/drawable-xhdpi/log_out_btn_bg.png b/app/src/main/res/drawable-xhdpi/log_out_btn_bg.png new file mode 100644 index 0000000..019b512 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/log_out_btn_bg.png differ diff --git a/app/src/main/res/drawable-xhdpi/login_btn_bg.png b/app/src/main/res/drawable-xhdpi/login_btn_bg.png new file mode 100644 index 0000000..0b8a6a3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/login_btn_bg.png differ diff --git a/app/src/main/res/drawable-xhdpi/name_txt.png b/app/src/main/res/drawable-xhdpi/name_txt.png new file mode 100644 index 0000000..23f148a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/name_txt.png differ diff --git a/app/src/main/res/drawable-xhdpi/open_an_acc_txt.png b/app/src/main/res/drawable-xhdpi/open_an_acc_txt.png new file mode 100644 index 0000000..2d7c0a7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/open_an_acc_txt.png differ diff --git a/app/src/main/res/drawable-xhdpi/phone_number_txt.png b/app/src/main/res/drawable-xhdpi/phone_number_txt.png new file mode 100644 index 0000000..f0e0007 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/phone_number_txt.png differ diff --git a/app/src/main/res/drawable-xhdpi/red_warning_icon.png b/app/src/main/res/drawable-xhdpi/red_warning_icon.png new file mode 100644 index 0000000..570e5ee Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/red_warning_icon.png differ diff --git a/app/src/main/res/drawable-xhdpi/sambaza_header.png b/app/src/main/res/drawable-xhdpi/sambaza_header.png new file mode 100644 index 0000000..b78ea44 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/sambaza_header.png differ diff --git a/app/src/main/res/drawable-xhdpi/selected_contacts_txt.png b/app/src/main/res/drawable-xhdpi/selected_contacts_txt.png new file mode 100644 index 0000000..43c6f77 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/selected_contacts_txt.png differ diff --git a/app/src/main/res/drawable-xhdpi/send_airtime_btn_bg.png b/app/src/main/res/drawable-xhdpi/send_airtime_btn_bg.png new file mode 100644 index 0000000..9f1ddde Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/send_airtime_btn_bg.png differ diff --git a/app/src/main/res/drawable-xhdpi/send_airtime_txt.png b/app/src/main/res/drawable-xhdpi/send_airtime_txt.png new file mode 100644 index 0000000..7fff027 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/send_airtime_txt.png differ diff --git a/app/src/main/res/drawable-xhdpi/send_btn_bg.png b/app/src/main/res/drawable-xhdpi/send_btn_bg.png new file mode 100644 index 0000000..8b05cdf Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/send_btn_bg.png differ diff --git a/app/src/main/res/drawable-xhdpi/sign_up_btn_bg.png b/app/src/main/res/drawable-xhdpi/sign_up_btn_bg.png new file mode 100644 index 0000000..cccab5c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/sign_up_btn_bg.png differ diff --git a/app/src/main/res/drawable-xhdpi/sign_up_txt.png b/app/src/main/res/drawable-xhdpi/sign_up_txt.png new file mode 100644 index 0000000..2d3e4a4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/sign_up_txt.png differ diff --git a/app/src/main/res/drawable-xxhdpi/add_another_contact_btn_bg.png b/app/src/main/res/drawable-xxhdpi/add_another_contact_btn_bg.png new file mode 100644 index 0000000..54fa614 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/add_another_contact_btn_bg.png differ diff --git a/app/src/main/res/drawable-xxhdpi/add_btn_bg.png b/app/src/main/res/drawable-xxhdpi/add_btn_bg.png new file mode 100644 index 0000000..e2befd8 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/add_btn_bg.png differ diff --git a/app/src/main/res/drawable-xxhdpi/add_contacts_txt.png b/app/src/main/res/drawable-xxhdpi/add_contacts_txt.png new file mode 100644 index 0000000..ffa6ec8 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/add_contacts_txt.png differ diff --git a/app/src/main/res/drawable-xxhdpi/add_new_contacts_btn_bg.png b/app/src/main/res/drawable-xxhdpi/add_new_contacts_btn_bg.png new file mode 100644 index 0000000..74b2a60 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/add_new_contacts_btn_bg.png differ diff --git a/app/src/main/res/drawable-xxhdpi/enter_amount_txt.png b/app/src/main/res/drawable-xxhdpi/enter_amount_txt.png new file mode 100644 index 0000000..832febe Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/enter_amount_txt.png differ diff --git a/app/src/main/res/drawable-xxhdpi/home_txt.png b/app/src/main/res/drawable-xxhdpi/home_txt.png new file mode 100644 index 0000000..473f34c Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/home_txt.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_arrow_back.png b/app/src/main/res/drawable-xxhdpi/ic_arrow_back.png new file mode 100644 index 0000000..2a2303a Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_arrow_back.png differ diff --git a/app/src/main/res/drawable-xxhdpi/key_in_phone_number_txt.png b/app/src/main/res/drawable-xxhdpi/key_in_phone_number_txt.png new file mode 100644 index 0000000..fbc1e1d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/key_in_phone_number_txt.png differ diff --git a/app/src/main/res/drawable-xxhdpi/list_of_contacts_youve_just_added_txt.png b/app/src/main/res/drawable-xxhdpi/list_of_contacts_youve_just_added_txt.png new file mode 100644 index 0000000..221666c Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/list_of_contacts_youve_just_added_txt.png differ diff --git a/app/src/main/res/drawable-xxhdpi/log_in_txt.png b/app/src/main/res/drawable-xxhdpi/log_in_txt.png new file mode 100644 index 0000000..6ee98d6 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/log_in_txt.png differ diff --git a/app/src/main/res/drawable-xxhdpi/log_out_btn_bg.png b/app/src/main/res/drawable-xxhdpi/log_out_btn_bg.png new file mode 100644 index 0000000..79c5355 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/log_out_btn_bg.png differ diff --git a/app/src/main/res/drawable-xxhdpi/login_btn_bg.png b/app/src/main/res/drawable-xxhdpi/login_btn_bg.png new file mode 100644 index 0000000..e0173c8 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/login_btn_bg.png differ diff --git a/app/src/main/res/drawable-xxhdpi/name_txt.png b/app/src/main/res/drawable-xxhdpi/name_txt.png new file mode 100644 index 0000000..33d9800 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/name_txt.png differ diff --git a/app/src/main/res/drawable-xxhdpi/open_an_acc_txt.png b/app/src/main/res/drawable-xxhdpi/open_an_acc_txt.png new file mode 100644 index 0000000..8184807 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/open_an_acc_txt.png differ diff --git a/app/src/main/res/drawable-xxhdpi/phone_number_txt.png b/app/src/main/res/drawable-xxhdpi/phone_number_txt.png new file mode 100644 index 0000000..b4abb7a Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/phone_number_txt.png differ diff --git a/app/src/main/res/drawable-xxhdpi/red_warning_icon.png b/app/src/main/res/drawable-xxhdpi/red_warning_icon.png new file mode 100644 index 0000000..3ce4308 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/red_warning_icon.png differ diff --git a/app/src/main/res/drawable-xxhdpi/sambaza_header.png b/app/src/main/res/drawable-xxhdpi/sambaza_header.png new file mode 100644 index 0000000..8cbe063 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/sambaza_header.png differ diff --git a/app/src/main/res/drawable-xxhdpi/selected_contacts_txt.png b/app/src/main/res/drawable-xxhdpi/selected_contacts_txt.png new file mode 100644 index 0000000..48e1116 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/selected_contacts_txt.png differ diff --git a/app/src/main/res/drawable-xxhdpi/send_airtime_btn_bg.png b/app/src/main/res/drawable-xxhdpi/send_airtime_btn_bg.png new file mode 100644 index 0000000..d90d82b Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/send_airtime_btn_bg.png differ diff --git a/app/src/main/res/drawable-xxhdpi/send_airtime_txt.png b/app/src/main/res/drawable-xxhdpi/send_airtime_txt.png new file mode 100644 index 0000000..81864fb Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/send_airtime_txt.png differ diff --git a/app/src/main/res/drawable-xxhdpi/send_btn_bg.png b/app/src/main/res/drawable-xxhdpi/send_btn_bg.png new file mode 100644 index 0000000..1b26f89 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/send_btn_bg.png differ diff --git a/app/src/main/res/drawable-xxhdpi/sign_up_btn_bg.png b/app/src/main/res/drawable-xxhdpi/sign_up_btn_bg.png new file mode 100644 index 0000000..c357207 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/sign_up_btn_bg.png differ diff --git a/app/src/main/res/drawable-xxhdpi/sign_up_txt.png b/app/src/main/res/drawable-xxhdpi/sign_up_txt.png new file mode 100644 index 0000000..eeb98ac Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/sign_up_txt.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/add_another_contact_btn_bg.png b/app/src/main/res/drawable-xxxhdpi/add_another_contact_btn_bg.png new file mode 100644 index 0000000..e1ecb21 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/add_another_contact_btn_bg.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/add_btn_bg.png b/app/src/main/res/drawable-xxxhdpi/add_btn_bg.png new file mode 100644 index 0000000..d18cbed Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/add_btn_bg.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/add_contacts_txt.png b/app/src/main/res/drawable-xxxhdpi/add_contacts_txt.png new file mode 100644 index 0000000..771974f Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/add_contacts_txt.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/add_new_contacts_btn_bg.png b/app/src/main/res/drawable-xxxhdpi/add_new_contacts_btn_bg.png new file mode 100644 index 0000000..3a03b70 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/add_new_contacts_btn_bg.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/enter_amount_txt.png b/app/src/main/res/drawable-xxxhdpi/enter_amount_txt.png new file mode 100644 index 0000000..eb20585 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/enter_amount_txt.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/home_txt.png b/app/src/main/res/drawable-xxxhdpi/home_txt.png new file mode 100644 index 0000000..8fbb709 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/home_txt.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_arrow_back.png b/app/src/main/res/drawable-xxxhdpi/ic_arrow_back.png new file mode 100644 index 0000000..3ea26df Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_arrow_back.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/key_in_phone_number_txt.png b/app/src/main/res/drawable-xxxhdpi/key_in_phone_number_txt.png new file mode 100644 index 0000000..697aa43 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/key_in_phone_number_txt.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/list_of_contacts_youve_just_added_txt.png b/app/src/main/res/drawable-xxxhdpi/list_of_contacts_youve_just_added_txt.png new file mode 100644 index 0000000..e9cb22e Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/list_of_contacts_youve_just_added_txt.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/log_in_txt.png b/app/src/main/res/drawable-xxxhdpi/log_in_txt.png new file mode 100644 index 0000000..2b5477d Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/log_in_txt.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/log_out_btn_bg.png b/app/src/main/res/drawable-xxxhdpi/log_out_btn_bg.png new file mode 100644 index 0000000..c9d2807 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/log_out_btn_bg.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/login_btn_bg.png b/app/src/main/res/drawable-xxxhdpi/login_btn_bg.png new file mode 100644 index 0000000..03a8b17 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/login_btn_bg.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/name_txt.png b/app/src/main/res/drawable-xxxhdpi/name_txt.png new file mode 100644 index 0000000..b4c29b9 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/name_txt.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/open_an_acc_txt.png b/app/src/main/res/drawable-xxxhdpi/open_an_acc_txt.png new file mode 100644 index 0000000..0d609f0 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/open_an_acc_txt.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/phone_number_txt.png b/app/src/main/res/drawable-xxxhdpi/phone_number_txt.png new file mode 100644 index 0000000..ae07b5b Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/phone_number_txt.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/red_warning_icon.png b/app/src/main/res/drawable-xxxhdpi/red_warning_icon.png new file mode 100644 index 0000000..a9d4c64 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/red_warning_icon.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/sambaza_header.png b/app/src/main/res/drawable-xxxhdpi/sambaza_header.png new file mode 100644 index 0000000..6bccfb0 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/sambaza_header.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/selected_contacts_txt.png b/app/src/main/res/drawable-xxxhdpi/selected_contacts_txt.png new file mode 100644 index 0000000..75f034c Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/selected_contacts_txt.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/send_airtime_btn_bg.png b/app/src/main/res/drawable-xxxhdpi/send_airtime_btn_bg.png new file mode 100644 index 0000000..b60e06c Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/send_airtime_btn_bg.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/send_airtime_txt.png b/app/src/main/res/drawable-xxxhdpi/send_airtime_txt.png new file mode 100644 index 0000000..90f38e7 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/send_airtime_txt.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/send_btn_bg.png b/app/src/main/res/drawable-xxxhdpi/send_btn_bg.png new file mode 100644 index 0000000..765a086 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/send_btn_bg.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/sign_up_btn_bg.png b/app/src/main/res/drawable-xxxhdpi/sign_up_btn_bg.png new file mode 100644 index 0000000..d357d43 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/sign_up_btn_bg.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/sign_up_txt.png b/app/src/main/res/drawable-xxxhdpi/sign_up_txt.png new file mode 100644 index 0000000..4e6cbfe Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/sign_up_txt.png differ diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..d5fccc5 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..e375185 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/add_contacts_fragment.xml b/app/src/main/res/layout/add_contacts_fragment.xml new file mode 100644 index 0000000..a488147 --- /dev/null +++ b/app/src/main/res/layout/add_contacts_fragment.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + +