Java tutorial
/*** * Copyright (c) 2015 Oscar Salguero www.oscarsalguero.com * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.oscarsalguero.dialer; import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.Snackbar; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.Button; import android.widget.RelativeLayout; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import com.oscarsalguero.dialer.adapter.CustomSpinnerAdapter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** * Main Activity * <p/> * This app serves as an alternative phone dialer. * <p/> * This activity presents the user with a a spinner to select a country, a display that shows the phone number, * a delete button, a phone keypad, a cancel and call buttons. * <p/> * The phone number is validated before calling/dialing the phone. * <p/> * Created by RacZo on 9/28/15. */ public class MainActivity extends AppCompatActivity implements View.OnClickListener { private static final String LOG_TAG = MainActivity.class.getName(); private static final String URI_PREFIX_TEL = "tel:"; private static final String SYMBOL_STAR = "*"; private static final String SYMBOL_POUND = "#"; private static final int PERMISSIONS_REQUEST_CALL_PHONE = 100; private RelativeLayout mLayout; private Spinner spinnerCountryCode; private TextView textViewDisplay; private Button buttonDel; private Button button1; private Button button2; private Button button3; private Button button4; private Button button5; private Button button6; private Button button7; private Button button8; private Button button9; private Button buttonStar; private Button buttonZero; private Button buttonPound; private Button buttonCancel; private Button buttonCall; private List<HashMap<String, Object>> spinnerList = new ArrayList<HashMap<String, Object>>(); private CustomSpinnerAdapter adapter; private static Integer[] flagDatabase = { R.drawable.us_normal, R.drawable.sv_normal, R.drawable.au_normal, R.drawable.br_normal, R.drawable.de_normal, R.drawable.es_normal, R.drawable.fr_normal, R.drawable.it_normal, R.drawable.jp_normal, R.drawable.mx_normal }; private String[] countryCodeDatabase = { "+1", "+503", "+61", "+55", "+49", "+34", "+33", "+39", "+81", "+52" }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mLayout = (RelativeLayout) findViewById(R.id.relative_layout_dialer); spinnerCountryCode = (Spinner) findViewById(R.id.spinner_country_code); textViewDisplay = (TextView) findViewById(R.id.text_view_display); textViewDisplay.setOnClickListener(this); buttonDel = (Button) findViewById(R.id.button_del); buttonDel.setOnClickListener(this); button1 = (Button) findViewById(R.id.button_1); button1.setOnClickListener(this); button2 = (Button) findViewById(R.id.button_2); button2.setOnClickListener(this); button3 = (Button) findViewById(R.id.button_3); button3.setOnClickListener(this); button4 = (Button) findViewById(R.id.button_4); button4.setOnClickListener(this); button5 = (Button) findViewById(R.id.button_5); button5.setOnClickListener(this); button6 = (Button) findViewById(R.id.button_6); button6.setOnClickListener(this); button7 = (Button) findViewById(R.id.button_7); button7.setOnClickListener(this); button8 = (Button) findViewById(R.id.button_8); button8.setOnClickListener(this); button9 = (Button) findViewById(R.id.button_9); button9.setOnClickListener(this); buttonZero = (Button) findViewById(R.id.button_zero); buttonZero.setOnClickListener(this); buttonStar = (Button) findViewById(R.id.button_star); buttonStar.setOnClickListener(this); buttonPound = (Button) findViewById(R.id.button_pound); buttonPound.setOnClickListener(this); buttonCancel = (Button) findViewById(R.id.button_cancel); buttonCancel.setOnClickListener(this); buttonCall = (Button) findViewById(R.id.button_call); buttonCall.setOnClickListener(this); initializeCountryList(); adapter = new CustomSpinnerAdapter(this, spinnerList, R.layout.spinner_view, new String[] { "flag", "code" }, new int[] { R.id.image_view_flag, R.id.text_view_code }); spinnerCountryCode.setAdapter(adapter); spinnerCountryCode.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { HashMap<String, Object> map = (HashMap) adapter.getItem(position); String code = (String) map.get("code"); textViewDisplay.setText(code); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); } /** * Handle UI clicks. */ @Override public void onClick(View v) { switch (v.getId()) { case R.id.text_view_display: // Nothing happens when the display is tapped break; case R.id.button_del: deleteCharacter(); break; case R.id.button_1: appendDigitAndFormat(1); break; case R.id.button_2: appendDigitAndFormat(2); break; case R.id.button_3: appendDigitAndFormat(3); break; case R.id.button_4: appendDigitAndFormat(4); break; case R.id.button_5: appendDigitAndFormat(5); break; case R.id.button_6: appendDigitAndFormat(6); break; case R.id.button_7: appendDigitAndFormat(7); break; case R.id.button_8: appendDigitAndFormat(8); break; case R.id.button_9: appendDigitAndFormat(9); break; case R.id.button_zero: appendDigitAndFormat(0); break; case R.id.button_star: appenSymbolAndFormat(SYMBOL_STAR); break; case R.id.button_pound: appenSymbolAndFormat(SYMBOL_POUND); break; case R.id.button_cancel: cancel(); break; case R.id.button_call: call(); break; default: break; } } /** * Callback received when a permissions request has been completed. */ @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PERMISSIONS_REQUEST_CALL_PHONE) { if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Snackbar.make(mLayout, R.string.permission_available_call_phone, Snackbar.LENGTH_SHORT).show(); callPhone(); } else { Snackbar.make(mLayout, R.string.permissions_not_granted, Snackbar.LENGTH_SHORT).show(); } } } /** * Requests the CALL_PHONE permission. The CALL_PHONE permission is * required in order to make outbound calls. */ private void requestCallPhonePermissions() { if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CALL_PHONE)) { Snackbar.make(mLayout, R.string.permission_contacts_rationale, Snackbar.LENGTH_INDEFINITE) .setAction(R.string.button_ok, new View.OnClickListener() { @Override public void onClick(View view) { ActivityCompat.requestPermissions(MainActivity.this, new String[] { Manifest.permission.CALL_PHONE }, PERMISSIONS_REQUEST_CALL_PHONE); } }).show(); } else { ActivityCompat.requestPermissions(MainActivity.this, new String[] { Manifest.permission.CALL_PHONE }, PERMISSIONS_REQUEST_CALL_PHONE); } } /** * Validates phone number and initiates the phone call */ private void call() { if (textViewDisplay.getText() != null) { if (textViewDisplay.getText().toString().length() > 0) { if (validPhoneNumber(textViewDisplay.getText().toString())) { try { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { requestCallPhonePermissions(); } else { callPhone(); } } catch (Exception e) { Log.e(LOG_TAG, "Could not start CALL intent. Will try to start DIAL intent.", e); dialPhone(); } } else { showPhoneValidationToast(); } } else { showPhoneValidationToast(); } } else { showPhoneValidationToast(); } } /** * Validates the phone number */ private boolean validPhoneNumber(String phoneNumber) { //TODO Validate the phone number return true; } /** * Shows a toast saying the phone number is not valid */ private void showPhoneValidationToast() { Toast.makeText(MainActivity.this, getString(R.string.validation_enter_phone_number), Toast.LENGTH_SHORT) .show(); } /** * Cancels the call and clears the display */ private void cancel() { spinnerCountryCode.setSelection(0); textViewDisplay.setText(""); } /** * Appends a symbol to the dialer's display and tries to format the phone number * * @param symbol The symbol to append */ private void appenSymbolAndFormat(String symbol) { textViewDisplay.append(symbol); // TODO Format phone number } /** * Appends a digit to the dialer's display and tries to format the phone number * * @param digit The digit to append */ private void appendDigitAndFormat(int digit) { textViewDisplay.append(String.valueOf(digit)); // TODO Format phone number } /** * Deletes the last character from the dialer's display */ private void deleteCharacter() { if (textViewDisplay.getText() != null) { String phoneNumber = textViewDisplay.getText().toString(); if (phoneNumber.length() > 0) { phoneNumber = phoneNumber.substring(0, phoneNumber.length() - 1); textViewDisplay.setText(phoneNumber); } } } /** * Creates a list with hash maps of flags and country codes that serves as the data for the spinner. */ private void initializeCountryList() { for (int i = 0; i < flagDatabase.length; i++) { HashMap<String, Object> map = new HashMap<String, Object>(); map.put("flag", flagDatabase[i]); map.put("code", countryCodeDatabase[i]); spinnerList.add(map); } } /** * Dials a phone number using the ACTION_DIAL intent (does not require permission). */ private void dialPhone() { try { String phoneNumber = textViewDisplay.getText().toString(); Intent dialIntent = new Intent(Intent.ACTION_DIAL); dialIntent.setData(Uri.parse(URI_PREFIX_TEL + Uri.encode(phoneNumber))); dialIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(dialIntent); logPhoneNumber(phoneNumber); } catch (Exception e) { Log.e(LOG_TAG, "An exception occurred trying to execute the DIAL intent.", e); } } /** * Dials a phone number using the ACTION_CALL intent (requires CALL_PHONE permission). */ private void callPhone() { try { String phoneNumber = textViewDisplay.getText().toString(); Intent callIntent = new Intent(Intent.ACTION_CALL); callIntent.setData(Uri.parse(URI_PREFIX_TEL + Uri.encode(phoneNumber))); startActivity(callIntent); logPhoneNumber(phoneNumber); } catch (SecurityException e) { Log.e(LOG_TAG, "An exception occurred trying to execute the CALL intent.", e); } } /** * Logs the phone number that was handed to the phone dialer. * * @param phoneNumber The phone number the user dialed */ private void logPhoneNumber(String phoneNumber) { Log.d(LOG_TAG, "The user dialed: " + phoneNumber); // TODO Do whatever you want with the phone number (keep track of calls, create stats, etc...) } }