android设备中的通讯录应用程序是已安装在android设备上的系统应用程序。不同的设备针对联系人应用程序具有不同的UI。在本文中,我们将介绍如何在Android Studio中构建自己的联系人应用程序。
我们将在本文中构建什么?
我们将构建一个简单的应用程序,其中将显示存储在用户设备中的联系人列表。除此之外,我们还将添加一项功能来保存新联系人,使用搜索栏从列表中过滤联系人,等等。下面是视频,我们将在其中观看我们将要构建的内容。
分步实施
步骤1:创建一个新项目
要在Android Studio中创建新项目,请参阅如何在Android Studio中创建/启动新项目。请注意,选择Java作为编程语言。
步骤2:添加依赖项和JitPack存储库
由于我们必须请求用户的权限才能从应用程序中的设备显示联系人,因此我们必须请求用户的权限。因此,为了获取用户的权限,我们将使用Dexter在运行时获取用户的权限。为了使用Dexter,我们还将使用text drawable依赖项在drawable中显示文本,现在我们在build.gradle文件中添加了以下依赖项。导航到Gradle脚本> build.gradle(Module:app)并将以下依赖项添加到“依赖项”部分。
implementation ‘com.github.mukeshsolanki:photofilter:1.0.2’
implementation ‘com.karumi:dexter:6.2.2’
将JitPack存储库添加到您的构建文件中。将其添加到allprojects {}部分中存储库末尾的根build.gradle中。
allprojects {
repositories {
…
maven { url “https://jitpack.io” }
}
}
现在同步您的项目,我们将进一步处理AndroidManifest.xml文件。
步骤3:在AndroidManifest.xml中添加权限
导航至应用程序> AndroidManifest.xml文件,然后向其添加以下权限。在代码中添加了注释,以便更详细地了解。
XML
XML
Java
public class ContactsModal {
// variables for our user name
// and contact number.
private String userName;
private String contactNumber;
// constructor
public ContactsModal(String userName, String contactNumber) {
this.userName = userName;
this.contactNumber = contactNumber;
}
// on below line we have
// created getter and setter
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getContactNumber() {
return contactNumber;
}
public void setContactNumber(String contactNumber) {
this.contactNumber = contactNumber;
}
}
XML
Java
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;
import java.util.ArrayList;
class ContactRVAdapter extends RecyclerView.Adapter {
// creating variables for context and array list.
private Context context;
private ArrayList contactsModalArrayList;
// creating a constructor
public ContactRVAdapter(Context context, ArrayList contactsModalArrayList) {
this.context = context;
this.contactsModalArrayList = contactsModalArrayList;
}
@NonNull
@Override
public ContactRVAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// passing our layout file for displaying our card item
return new ContactRVAdapter.ViewHolder(LayoutInflater.from(context).inflate(R.layout.contacts_rv_item, parent, false));
}
// below method is use for filtering data in our array list
public void filterList(ArrayList filterllist) {
// on below line we are passing filtered
// array list in our original array list
contactsModalArrayList = filterllist;
notifyDataSetChanged();
}
@Override
public void onBindViewHolder(@NonNull ContactRVAdapter.ViewHolder holder, int position) {
// getting data from array list in our modal.
ContactsModal modal = contactsModalArrayList.get(position);
// on below line we are setting data to our text view.
holder.contactTV.setText(modal.getUserName());
ColorGenerator generator = ColorGenerator.MATERIAL; // or use DEFAULT
// generate random color
int color = generator.getRandomColor();
// below text drawable is a circular.
TextDrawable drawable2 = TextDrawable.builder().beginConfig()
.width(100) // width in px
.height(100) // height in px
.endConfig()
// as we are building a circular drawable
// we are calling a build round method.
// in that method we are passing our text and color.
.buildRound(modal.getUserName().substring(0, 1), color);
// setting image to our image view on below line.
holder.contactIV.setImageDrawable(drawable2);
// on below line we are adding on click listener to our item of recycler view.
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// on below line we are opening a new activity and passing data to it.
Intent i = new Intent(context, ContactDetailActivity.class);
i.putExtra("name", modal.getUserName());
i.putExtra("contact", modal.getContactNumber());
// on below line we are starting a new activity,
context.startActivity(i);
}
});
}
@Override
public int getItemCount() {
return contactsModalArrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
// on below line creating a variable
// for our image view and text view.
private ImageView contactIV;
private TextView contactTV;
public ViewHolder(@NonNull View itemView) {
super(itemView);
// initializing our image view and text view.
contactIV = itemView.findViewById(R.id.idIVContact);
contactTV = itemView.findViewById(R.id.idTVContactName);
}
}
}
XML
Java
import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.Settings;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.SearchView;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.MenuItemCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.karumi.dexter.Dexter;
import com.karumi.dexter.MultiplePermissionsReport;
import com.karumi.dexter.PermissionToken;
import com.karumi.dexter.listener.DexterError;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.PermissionRequestErrorListener;
import com.karumi.dexter.listener.multi.MultiplePermissionsListener;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
// creating variables for our array list, recycler view progress bar and adapter.
private ArrayList contactsModalArrayList;
private RecyclerView contactRV;
private ContactRVAdapter contactRVAdapter;
private ProgressBar loadingPB;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// on below line we are initializing our variables.
contactsModalArrayList = new ArrayList<>();
contactRV = findViewById(R.id.idRVContacts);
FloatingActionButton addNewContactFAB = findViewById(R.id.idFABadd);
loadingPB = findViewById(R.id.idPBLoading);
// calling method to prepare our recycler view.
prepareContactRV();
// calling a method to request permissions.
requestPermissions();
// adding on click listener for our fab.
addNewContactFAB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// opening a new activity on below line.
Intent i = new Intent(MainActivity.this, CreateNewContactActivity.class);
startActivity(i);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// in this on create options menu we are calling
// a menu inflater and inflating our menu file.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.search_menu, menu);
// on below line we are getting our menu item as search view item
MenuItem searchViewItem = menu.findItem(R.id.app_bar_search);
// on below line we are creating a variable for our search view.
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchViewItem);
// on below line we are setting on query text listener for our search view.
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
// on query submit we are clearing the focus for our search view.
searchView.clearFocus();
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
// on changing the text in our search view we are calling
// a filter method to filter our array list.
filter(newText.toLowerCase());
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
private void filter(String text) {
// in this method we are filtering our array list.
// on below line we are creating a new filtered array list.
ArrayList filteredlist = new ArrayList<>();
// on below line we are running a loop for checking if the item is present in array list.
for (ContactsModal item : contactsModalArrayList) {
if (item.getUserName().toLowerCase().contains(text.toLowerCase())) {
// on below line we are adding item to our filtered array list.
filteredlist.add(item);
}
}
// on below line we are checking if the filtered list is empty or not.
if (filteredlist.isEmpty()) {
Toast.makeText(this, "No Contact Found", Toast.LENGTH_SHORT).show();
} else {
// passing this filtered list to our adapter with filter list method.
contactRVAdapter.filterList(filteredlist);
}
}
private void prepareContactRV() {
// in this method we are preparing our recycler view with adapter.
contactRVAdapter = new ContactRVAdapter(this, contactsModalArrayList);
// on below line we are setting layout manager.
contactRV.setLayoutManager(new LinearLayoutManager(this));
// on below line we are setting adapter to our recycler view.
contactRV.setAdapter(contactRVAdapter);
}
private void requestPermissions() {
// below line is use to request
// permission in the current activity.
Dexter.withActivity(this)
// below line is use to request the number of
// permissions which are required in our app.
.withPermissions(Manifest.permission.READ_CONTACTS,
// below is the list of permissions
Manifest.permission.CALL_PHONE,
Manifest.permission.SEND_SMS, Manifest.permission.WRITE_CONTACTS)
// after adding permissions we are
// calling an with listener method.
.withListener(new MultiplePermissionsListener() {
@Override
public void onPermissionsChecked(MultiplePermissionsReport multiplePermissionsReport) {
// this method is called when all permissions are granted
if (multiplePermissionsReport.areAllPermissionsGranted()) {
// do you work now
getContacts();
Toast.makeText(MainActivity.this, "All the permissions are granted..", Toast.LENGTH_SHORT).show();
}
// check for permanent denial of any permission
if (multiplePermissionsReport.isAnyPermissionPermanentlyDenied()) {
// permission is denied permanently,
// we will show user a dialog message.
showSettingsDialog();
}
}
@Override
public void onPermissionRationaleShouldBeShown(List list, PermissionToken permissionToken) {
// this method is called when user grants some
// permission and denies some of them.
permissionToken.continuePermissionRequest();
}
}).withErrorListener(new PermissionRequestErrorListener() {
// this method is use to handle error
// in runtime permissions
@Override
public void onError(DexterError error) {
// we are displaying a toast message for error message.
Toast.makeText(getApplicationContext(), "Error occurred! ", Toast.LENGTH_SHORT).show();
}
})
// below line is use to run the permissions
// on same thread and to check the permissions
.onSameThread().check();
}
// below is the shoe setting dialog
// method which is use to display a
// dialogue message.
private void showSettingsDialog() {
// we are displaying an alert dialog for permissions
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
// below line is the title
// for our alert dialog.
builder.setTitle("Need Permissions");
// below line is our message for our dialog
builder.setMessage("This app needs permission to use this feature. You can grant them in app settings.");
builder.setPositiveButton("GOTO SETTINGS", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// this method is called on click on positive
// button and on clicking shit button we
// are redirecting our user from our app to the
// settings page of our app.
dialog.cancel();
// below is the intent from which we
// are redirecting our user.
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, 101);
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// this method is called when
// user click on negative button.
dialog.cancel();
}
});
// below line is used
// to display our dialog
builder.show();
}
private void getContacts() {
// this method is use to read contact from users device.
// on below line we are creating a string variables for
// our contact id and display name.
String contactId = "";
String displayName = "";
// on below line we are calling our content resolver for getting contacts
Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
// on blow line we are checking the count for our cursor.
if (cursor.getCount() > 0) {
// if the count is greater than 0 then we are running a loop to move our cursor to next.
while (cursor.moveToNext()) {
// on below line we are getting the phone number.
int hasPhoneNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)));
if (hasPhoneNumber > 0) {
// we are checking if the has phone number is > 0
// on below line we are getting our contact id and user name for that contact
contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
// on below line we are calling a content resolver and making a query
Cursor phoneCursor = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{contactId},
null);
// on below line we are moving our cursor to next position.
if (phoneCursor.moveToNext()) {
// on below line we are getting the phone number for our users and then adding the name along with phone number in array list.
String phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactsModalArrayList.add(new ContactsModal(displayName, phoneNumber));
}
// on below line we are closing our phone cursor.
phoneCursor.close();
}
}
}
// on below line we are closing our cursor.
cursor.close();
// on below line we are hiding our progress bar and notifying our adapter class.
loadingPB.setVisibility(View.GONE);
contactRVAdapter.notifyDataSetChanged();
}
}
XML
Java
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class CreateNewContactActivity extends AppCompatActivity {
// creating a new variable for our edit text and button.
private EditText nameEdt, phoneEdt, emailEdt;
private Button addContactEdt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_new_contact);
// on below line we are initializing our variables.
nameEdt = findViewById(R.id.idEdtName);
phoneEdt = findViewById(R.id.idEdtPhoneNumber);
emailEdt = findViewById(R.id.idEdtEmail);
addContactEdt = findViewById(R.id.idBtnAddContact);
// on below line we are adding on click listener for our button.
addContactEdt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// on below line we are getting text from our edit text.
String name = nameEdt.getText().toString();
String phone = phoneEdt.getText().toString();
String email = emailEdt.getText().toString();
// on below line we are making a text validation.
if (TextUtils.isEmpty(name) && TextUtils.isEmpty(email) && TextUtils.isEmpty(phone)) {
Toast.makeText(CreateNewContactActivity.this, "Please enter the data in all fields. ", Toast.LENGTH_SHORT).show();
} else {
// calling a method to add contact.
addContact(name, email, phone);
}
}
});
}
private void addContact(String name, String email, String phone) {
// in this method we are calling an intent and passing data to that
// intent for adding a new contact.
Intent contactIntent = new Intent(ContactsContract.Intents.Insert.ACTION);
contactIntent.setType(ContactsContract.RawContacts.CONTENT_TYPE);
contactIntent
.putExtra(ContactsContract.Intents.Insert.NAME, name)
.putExtra(ContactsContract.Intents.Insert.PHONE, phone)
.putExtra(ContactsContract.Intents.Insert.EMAIL, email);
startActivityForResult(contactIntent, 1);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// in on activity result method.
if (requestCode == 1) {
// we are checking if the request code is 1
if (resultCode == Activity.RESULT_OK) {
// if the result is ok we are displaying a toast message.
Toast.makeText(this, "Contact has been added.", Toast.LENGTH_SHORT).show();
Intent i = new Intent(CreateNewContactActivity.this, MainActivity.class);
startActivity(i);
}
// else we are displaying a message as contact addition has cancelled.
if (resultCode == Activity.RESULT_CANCELED) {
Toast.makeText(this, "Cancelled Added Contact",
Toast.LENGTH_SHORT).show();
}
}
}
}
XML
Java
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
public class ContactDetailActivity extends AppCompatActivity {
// creating variables for our image view and text view and string. .
private String contactName, contactNumber;
private TextView contactTV, nameTV;
private ImageView contactIV, callIV, messageIV;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact_detail);
// on below line we are getting data which
// we passed in our adapter class with intent.
contactName = getIntent().getStringExtra("name");
contactNumber = getIntent().getStringExtra("contact");
// initializing our views.
nameTV = findViewById(R.id.idTVName);
contactIV = findViewById(R.id.idIVContact);
contactTV = findViewById(R.id.idTVPhone);
nameTV.setText(contactName);
contactTV.setText(contactNumber);
callIV = findViewById(R.id.idIVCall);
messageIV = findViewById(R.id.idIVMessage);
// on below line adding click listener for our calling image view.
callIV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// calling a method to make a call.
makeCall(contactNumber);
}
});
// on below line adding on click listener for our message image view.
messageIV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// calling a method to send message
sendMessage(contactNumber);
}
});
}
private void sendMessage(String contactNumber) {
// in this method we are calling an intent to send sms.
// on below line we are passing our contact number.
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("sms:" + contactNumber));
intent.putExtra("sms_body", "Enter your messaage");
startActivity(intent);
}
private void makeCall(String contactNumber) {
// this method is called for making a call.
// on below line we are calling an intent to make a call.
Intent callIntent = new Intent(Intent.ACTION_CALL);
// on below line we are setting data to it.
callIntent.setData(Uri.parse("tel:" + contactNumber));
// on below line we are checking if the calling permissions are granted not.
if (ActivityCompat.checkSelfPermission(ContactDetailActivity.this,
Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
return;
}
// at last we are starting activity.
startActivity(callIntent);
}
}
添加权限后,我们将朝着在应用程序中为不同屏幕创建新活动的方向发展。
步骤4:建立新的空白活动
创建用于保存新联系人的新活动:
请参阅如何在Android Studio中创建新活动并将您的活动命名为CreateNewContactActivity。此活动将用于为我们的应用创建新联系人。
创建一个新活动以显示联系人详细信息:
同样,创建另一个空活动,并将您的活动命名为ContactDetailActivity 。此活动将用于呼叫该联系人或发送SMS。
步骤5:使用activity_main.xml文件
导航到应用程序> res>布局> activity_main.xml,然后将以下代码添加到该文件中。以下是activity_main.xml文件的代码。
XML格式
步骤6:创建用于存储联系人的模式类
导航到应用程序> Java >应用程序的程序包名称>右键单击它>新建> Java类,并将其命名为ContactsModal ,并向其添加以下代码。在代码中添加了注释,以便更详细地了解。
Java
public class ContactsModal {
// variables for our user name
// and contact number.
private String userName;
private String contactNumber;
// constructor
public ContactsModal(String userName, String contactNumber) {
this.userName = userName;
this.contactNumber = contactNumber;
}
// on below line we have
// created getter and setter
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getContactNumber() {
return contactNumber;
}
public void setContactNumber(String contactNumber) {
this.contactNumber = contactNumber;
}
}
步骤7:为要在RecyclerView中显示的项目创建一个布局文件
导航到应用程序> res>布局>右键单击它>新建>布局资源文件,并将其命名为contacts_rv_item,然后将以下代码添加到其中。在代码中添加了注释,以便更详细地了解。
XML格式
步骤8:创建用于将数据设置为每个项目的适配器类
导航到应用程序> Java >应用程序的程序包名称>右键单击它>新建> Java类,并将其命名为ContactsRVAdapter,然后将以下代码添加到其中。在代码中添加了注释,以便更详细地了解。
Java
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;
import java.util.ArrayList;
class ContactRVAdapter extends RecyclerView.Adapter {
// creating variables for context and array list.
private Context context;
private ArrayList contactsModalArrayList;
// creating a constructor
public ContactRVAdapter(Context context, ArrayList contactsModalArrayList) {
this.context = context;
this.contactsModalArrayList = contactsModalArrayList;
}
@NonNull
@Override
public ContactRVAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// passing our layout file for displaying our card item
return new ContactRVAdapter.ViewHolder(LayoutInflater.from(context).inflate(R.layout.contacts_rv_item, parent, false));
}
// below method is use for filtering data in our array list
public void filterList(ArrayList filterllist) {
// on below line we are passing filtered
// array list in our original array list
contactsModalArrayList = filterllist;
notifyDataSetChanged();
}
@Override
public void onBindViewHolder(@NonNull ContactRVAdapter.ViewHolder holder, int position) {
// getting data from array list in our modal.
ContactsModal modal = contactsModalArrayList.get(position);
// on below line we are setting data to our text view.
holder.contactTV.setText(modal.getUserName());
ColorGenerator generator = ColorGenerator.MATERIAL; // or use DEFAULT
// generate random color
int color = generator.getRandomColor();
// below text drawable is a circular.
TextDrawable drawable2 = TextDrawable.builder().beginConfig()
.width(100) // width in px
.height(100) // height in px
.endConfig()
// as we are building a circular drawable
// we are calling a build round method.
// in that method we are passing our text and color.
.buildRound(modal.getUserName().substring(0, 1), color);
// setting image to our image view on below line.
holder.contactIV.setImageDrawable(drawable2);
// on below line we are adding on click listener to our item of recycler view.
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// on below line we are opening a new activity and passing data to it.
Intent i = new Intent(context, ContactDetailActivity.class);
i.putExtra("name", modal.getUserName());
i.putExtra("contact", modal.getContactNumber());
// on below line we are starting a new activity,
context.startActivity(i);
}
});
}
@Override
public int getItemCount() {
return contactsModalArrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
// on below line creating a variable
// for our image view and text view.
private ImageView contactIV;
private TextView contactTV;
public ViewHolder(@NonNull View itemView) {
super(itemView);
// initializing our image view and text view.
contactIV = itemView.findViewById(R.id.idIVContact);
contactTV = itemView.findViewById(R.id.idTVContactName);
}
}
}
步骤9:创建新的菜单资源文件以在工具栏中添加搜索视图
导航至应用程序> res>右键单击它> New> Android Resource目录,并将其命名为菜单,然后右键单击菜单,然后单击New> Menu resource directory 。在该名称之后,该文件将命名为search_menu,并在其中添加以下代码。在代码中添加了注释,以便更详细地了解。或者您可以参考本文如何在Android Studio中创建菜单文件夹和菜单文件?
XML格式
步骤10:使用MainActivity。 Java文件
转到MainActivity。 Java文件并参考以下代码。下面是MainActivity的代码。 Java文件。在代码内部添加了注释,以更详细地了解代码。
Java
import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.Settings;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.SearchView;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.MenuItemCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.karumi.dexter.Dexter;
import com.karumi.dexter.MultiplePermissionsReport;
import com.karumi.dexter.PermissionToken;
import com.karumi.dexter.listener.DexterError;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.PermissionRequestErrorListener;
import com.karumi.dexter.listener.multi.MultiplePermissionsListener;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
// creating variables for our array list, recycler view progress bar and adapter.
private ArrayList contactsModalArrayList;
private RecyclerView contactRV;
private ContactRVAdapter contactRVAdapter;
private ProgressBar loadingPB;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// on below line we are initializing our variables.
contactsModalArrayList = new ArrayList<>();
contactRV = findViewById(R.id.idRVContacts);
FloatingActionButton addNewContactFAB = findViewById(R.id.idFABadd);
loadingPB = findViewById(R.id.idPBLoading);
// calling method to prepare our recycler view.
prepareContactRV();
// calling a method to request permissions.
requestPermissions();
// adding on click listener for our fab.
addNewContactFAB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// opening a new activity on below line.
Intent i = new Intent(MainActivity.this, CreateNewContactActivity.class);
startActivity(i);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// in this on create options menu we are calling
// a menu inflater and inflating our menu file.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.search_menu, menu);
// on below line we are getting our menu item as search view item
MenuItem searchViewItem = menu.findItem(R.id.app_bar_search);
// on below line we are creating a variable for our search view.
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchViewItem);
// on below line we are setting on query text listener for our search view.
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
// on query submit we are clearing the focus for our search view.
searchView.clearFocus();
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
// on changing the text in our search view we are calling
// a filter method to filter our array list.
filter(newText.toLowerCase());
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
private void filter(String text) {
// in this method we are filtering our array list.
// on below line we are creating a new filtered array list.
ArrayList filteredlist = new ArrayList<>();
// on below line we are running a loop for checking if the item is present in array list.
for (ContactsModal item : contactsModalArrayList) {
if (item.getUserName().toLowerCase().contains(text.toLowerCase())) {
// on below line we are adding item to our filtered array list.
filteredlist.add(item);
}
}
// on below line we are checking if the filtered list is empty or not.
if (filteredlist.isEmpty()) {
Toast.makeText(this, "No Contact Found", Toast.LENGTH_SHORT).show();
} else {
// passing this filtered list to our adapter with filter list method.
contactRVAdapter.filterList(filteredlist);
}
}
private void prepareContactRV() {
// in this method we are preparing our recycler view with adapter.
contactRVAdapter = new ContactRVAdapter(this, contactsModalArrayList);
// on below line we are setting layout manager.
contactRV.setLayoutManager(new LinearLayoutManager(this));
// on below line we are setting adapter to our recycler view.
contactRV.setAdapter(contactRVAdapter);
}
private void requestPermissions() {
// below line is use to request
// permission in the current activity.
Dexter.withActivity(this)
// below line is use to request the number of
// permissions which are required in our app.
.withPermissions(Manifest.permission.READ_CONTACTS,
// below is the list of permissions
Manifest.permission.CALL_PHONE,
Manifest.permission.SEND_SMS, Manifest.permission.WRITE_CONTACTS)
// after adding permissions we are
// calling an with listener method.
.withListener(new MultiplePermissionsListener() {
@Override
public void onPermissionsChecked(MultiplePermissionsReport multiplePermissionsReport) {
// this method is called when all permissions are granted
if (multiplePermissionsReport.areAllPermissionsGranted()) {
// do you work now
getContacts();
Toast.makeText(MainActivity.this, "All the permissions are granted..", Toast.LENGTH_SHORT).show();
}
// check for permanent denial of any permission
if (multiplePermissionsReport.isAnyPermissionPermanentlyDenied()) {
// permission is denied permanently,
// we will show user a dialog message.
showSettingsDialog();
}
}
@Override
public void onPermissionRationaleShouldBeShown(List list, PermissionToken permissionToken) {
// this method is called when user grants some
// permission and denies some of them.
permissionToken.continuePermissionRequest();
}
}).withErrorListener(new PermissionRequestErrorListener() {
// this method is use to handle error
// in runtime permissions
@Override
public void onError(DexterError error) {
// we are displaying a toast message for error message.
Toast.makeText(getApplicationContext(), "Error occurred! ", Toast.LENGTH_SHORT).show();
}
})
// below line is use to run the permissions
// on same thread and to check the permissions
.onSameThread().check();
}
// below is the shoe setting dialog
// method which is use to display a
// dialogue message.
private void showSettingsDialog() {
// we are displaying an alert dialog for permissions
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
// below line is the title
// for our alert dialog.
builder.setTitle("Need Permissions");
// below line is our message for our dialog
builder.setMessage("This app needs permission to use this feature. You can grant them in app settings.");
builder.setPositiveButton("GOTO SETTINGS", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// this method is called on click on positive
// button and on clicking shit button we
// are redirecting our user from our app to the
// settings page of our app.
dialog.cancel();
// below is the intent from which we
// are redirecting our user.
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, 101);
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// this method is called when
// user click on negative button.
dialog.cancel();
}
});
// below line is used
// to display our dialog
builder.show();
}
private void getContacts() {
// this method is use to read contact from users device.
// on below line we are creating a string variables for
// our contact id and display name.
String contactId = "";
String displayName = "";
// on below line we are calling our content resolver for getting contacts
Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
// on blow line we are checking the count for our cursor.
if (cursor.getCount() > 0) {
// if the count is greater than 0 then we are running a loop to move our cursor to next.
while (cursor.moveToNext()) {
// on below line we are getting the phone number.
int hasPhoneNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)));
if (hasPhoneNumber > 0) {
// we are checking if the has phone number is > 0
// on below line we are getting our contact id and user name for that contact
contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
// on below line we are calling a content resolver and making a query
Cursor phoneCursor = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{contactId},
null);
// on below line we are moving our cursor to next position.
if (phoneCursor.moveToNext()) {
// on below line we are getting the phone number for our users and then adding the name along with phone number in array list.
String phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactsModalArrayList.add(new ContactsModal(displayName, phoneNumber));
}
// on below line we are closing our phone cursor.
phoneCursor.close();
}
}
}
// on below line we are closing our cursor.
cursor.close();
// on below line we are hiding our progress bar and notifying our adapter class.
loadingPB.setVisibility(View.GONE);
contactRVAdapter.notifyDataSetChanged();
}
}
步骤11:使用CreateNewContactActivity
以下是activity_create_new_contact.xml和CreateNewContactActivity的代码。 Java文件。在代码内部添加了注释,以更详细地了解代码。
XML格式
Java
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class CreateNewContactActivity extends AppCompatActivity {
// creating a new variable for our edit text and button.
private EditText nameEdt, phoneEdt, emailEdt;
private Button addContactEdt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_new_contact);
// on below line we are initializing our variables.
nameEdt = findViewById(R.id.idEdtName);
phoneEdt = findViewById(R.id.idEdtPhoneNumber);
emailEdt = findViewById(R.id.idEdtEmail);
addContactEdt = findViewById(R.id.idBtnAddContact);
// on below line we are adding on click listener for our button.
addContactEdt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// on below line we are getting text from our edit text.
String name = nameEdt.getText().toString();
String phone = phoneEdt.getText().toString();
String email = emailEdt.getText().toString();
// on below line we are making a text validation.
if (TextUtils.isEmpty(name) && TextUtils.isEmpty(email) && TextUtils.isEmpty(phone)) {
Toast.makeText(CreateNewContactActivity.this, "Please enter the data in all fields. ", Toast.LENGTH_SHORT).show();
} else {
// calling a method to add contact.
addContact(name, email, phone);
}
}
});
}
private void addContact(String name, String email, String phone) {
// in this method we are calling an intent and passing data to that
// intent for adding a new contact.
Intent contactIntent = new Intent(ContactsContract.Intents.Insert.ACTION);
contactIntent.setType(ContactsContract.RawContacts.CONTENT_TYPE);
contactIntent
.putExtra(ContactsContract.Intents.Insert.NAME, name)
.putExtra(ContactsContract.Intents.Insert.PHONE, phone)
.putExtra(ContactsContract.Intents.Insert.EMAIL, email);
startActivityForResult(contactIntent, 1);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// in on activity result method.
if (requestCode == 1) {
// we are checking if the request code is 1
if (resultCode == Activity.RESULT_OK) {
// if the result is ok we are displaying a toast message.
Toast.makeText(this, "Contact has been added.", Toast.LENGTH_SHORT).show();
Intent i = new Intent(CreateNewContactActivity.this, MainActivity.class);
startActivity(i);
}
// else we are displaying a message as contact addition has cancelled.
if (resultCode == Activity.RESULT_CANCELED) {
Toast.makeText(this, "Cancelled Added Contact",
Toast.LENGTH_SHORT).show();
}
}
}
}
步骤12:使用ContactDetailActivity
以下是activity_contact_detail.xml和ContactDetailActivity的代码。 Java文件。在代码内部添加了注释,以更详细地了解代码。
XML格式
Java
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
public class ContactDetailActivity extends AppCompatActivity {
// creating variables for our image view and text view and string. .
private String contactName, contactNumber;
private TextView contactTV, nameTV;
private ImageView contactIV, callIV, messageIV;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact_detail);
// on below line we are getting data which
// we passed in our adapter class with intent.
contactName = getIntent().getStringExtra("name");
contactNumber = getIntent().getStringExtra("contact");
// initializing our views.
nameTV = findViewById(R.id.idTVName);
contactIV = findViewById(R.id.idIVContact);
contactTV = findViewById(R.id.idTVPhone);
nameTV.setText(contactName);
contactTV.setText(contactNumber);
callIV = findViewById(R.id.idIVCall);
messageIV = findViewById(R.id.idIVMessage);
// on below line adding click listener for our calling image view.
callIV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// calling a method to make a call.
makeCall(contactNumber);
}
});
// on below line adding on click listener for our message image view.
messageIV.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// calling a method to send message
sendMessage(contactNumber);
}
});
}
private void sendMessage(String contactNumber) {
// in this method we are calling an intent to send sms.
// on below line we are passing our contact number.
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("sms:" + contactNumber));
intent.putExtra("sms_body", "Enter your messaage");
startActivity(intent);
}
private void makeCall(String contactNumber) {
// this method is called for making a call.
// on below line we are calling an intent to make a call.
Intent callIntent = new Intent(Intent.ACTION_CALL);
// on below line we are setting data to it.
callIntent.setData(Uri.parse("tel:" + contactNumber));
// on below line we are checking if the calling permissions are granted not.
if (ActivityCompat.checkSelfPermission(ContactDetailActivity.this,
Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
return;
}
// at last we are starting activity.
startActivity(callIntent);
}
}
现在运行您的应用程序,并查看该应用程序的输出。
Note: For all the drawable files you may refer to the GitHub link or you may add it of your own.
输出:
在Github链接上查看该项目: https : //github.com/ChaitanyaMunje/GFG-Back4App/tree/ContactsApp