添加通话记录和联系人

This commit is contained in:
ZhanGSKen 2025-02-26 14:10:16 +08:00
parent d4135f0104
commit 2f0293103c
20 changed files with 469 additions and 167 deletions

View File

@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Wed Feb 26 05:10:50 HKT 2025
#Wed Feb 26 06:08:35 GMT 2025
stageCount=4
libraryProject=
baseVersion=1.0
publishVersion=1.0.3
buildCount=0
buildCount=5
baseBetaVersion=1.0.4

View File

@ -29,9 +29,10 @@
<!-- 更改您的音频设置 -->
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<!-- 读取通话记录 -->
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
<application
android:name=".App"
android:allowBackup="true"
@ -184,4 +185,4 @@
</application>
</manifest>
</manifest>

View File

@ -1,36 +1,26 @@
package cc.winboll.studio.contacts;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.role.RoleManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.telecom.TelecomManager;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Switch;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.viewpager.widget.ViewPager;
import cc.winboll.studio.contacts.R;
import cc.winboll.studio.contacts.activities.CallActivity;
import cc.winboll.studio.contacts.activities.SettingsActivity;
import cc.winboll.studio.contacts.adapters.MyPagerAdapter;
import cc.winboll.studio.contacts.beans.MainServiceBean;
import cc.winboll.studio.contacts.services.MainService;
@ -40,15 +30,9 @@ import cc.winboll.studio.libapputils.app.IWinBollActivity;
import cc.winboll.studio.libapputils.app.WinBollActivityManager;
import cc.winboll.studio.libapputils.bean.APPInfo;
import cc.winboll.studio.libapputils.view.YesNoAlertDialog;
import cc.winboll.studio.contacts.listenphonecall.CallListenerService;
import com.google.android.material.tabs.TabLayout;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import android.content.DialogInterface;
import cc.winboll.studio.contacts.activities.SettingsActivity;
import cc.winboll.studio.contacts.beans.MainServiceBean;
import cc.winboll.studio.contacts.services.MainService;
final public class MainActivity extends AppCompatActivity implements IWinBollActivity, ViewPager.OnPageChangeListener, View.OnClickListener {
@ -171,7 +155,7 @@ final public class MainActivity extends AppCompatActivity implements IWinBollAct
void initData() {
ViewPager viewPager = findViewById(R.id.activitymainViewPager1);
LayoutInflater inflater = LayoutInflater.from(getActivity());
View view1 = inflater.inflate(R.layout.fragment_call, viewPager, false);
View view1 = inflater.inflate(R.layout.fragment_call_log, viewPager, false);
View view2 = inflater.inflate(R.layout.fragment_contacts, viewPager, false);
View view3 = inflater.inflate(R.layout.fragment_log, viewPager, false);

View File

@ -1,35 +0,0 @@
package cc.winboll.studio.contacts;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/20 21:14:52
* @Describe PhoneCallManager
*/
import android.telecom.Call;
import android.telecom.VideoProfile;
public class PhoneCallManager {
public static final String TAG = "PhoneCallManager";
public static Call call;
/**
* 接听电话
*/
public void answer() {
if (call != null) {
call.answer(VideoProfile.STATE_AUDIO_ONLY);
}
}
/**
* 断开电话包括来电时的拒接以及接听后的挂断
*/
public void disconnect() {
if (call != null) {
call.disconnect();
}
}
}

View File

@ -0,0 +1,61 @@
package cc.winboll.studio.contacts.adapters;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/26 13:09:32
* @Describe CallLogAdapter
*/
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import cc.winboll.studio.contacts.R;
import cc.winboll.studio.contacts.beans.CallLogModel;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
public class CallLogAdapter extends RecyclerView.Adapter<CallLogAdapter.CallLogViewHolder> {
public static final String TAG = "CallLogAdapter";
private List<CallLogModel> callLogList;
public CallLogAdapter(List<CallLogModel> callLogList) {
this.callLogList = callLogList;
}
@NonNull
@Override
public CallLogViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_call_log, parent, false);
return new CallLogViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull CallLogViewHolder holder, int position) {
CallLogModel callLog = callLogList.get(position);
holder.phoneNumber.setText(callLog.getPhoneNumber());
holder.callStatus.setText(callLog.getCallStatus());
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
holder.callDate.setText(dateFormat.format(callLog.getCallDate()));
}
@Override
public int getItemCount() {
return callLogList.size();
}
public class CallLogViewHolder extends RecyclerView.ViewHolder {
TextView phoneNumber, callStatus, callDate;
public CallLogViewHolder(@NonNull View itemView) {
super(itemView);
phoneNumber = itemView.findViewById(R.id.phone_number);
callStatus = itemView.findViewById(R.id.call_status);
callDate = itemView.findViewById(R.id.call_date);
}
}
}

View File

@ -0,0 +1,57 @@
package cc.winboll.studio.contacts.adapters;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/26 13:35:44
* @Describe ContactAdapter
*/
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import cc.winboll.studio.contacts.R;
import cc.winboll.studio.contacts.beans.ContactModel;
import java.util.List;
public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactViewHolder> {
public static final String TAG = "ContactAdapter";
private List<ContactModel> contactList;
public ContactAdapter(List<ContactModel> contactList) {
this.contactList = contactList;
}
@NonNull
@Override
public ContactViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_contact, parent, false);
return new ContactViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ContactViewHolder holder, int position) {
ContactModel contact = contactList.get(position);
holder.contactName.setText(contact.getName());
holder.contactNumber.setText(contact.getNumber());
}
@Override
public int getItemCount() {
return contactList.size();
}
public class ContactViewHolder extends RecyclerView.ViewHolder {
TextView contactName;
TextView contactNumber;
public ContactViewHolder(@NonNull View itemView) {
super(itemView);
contactName = itemView.findViewById(R.id.contact_name);
contactNumber = itemView.findViewById(R.id.contact_number);
}
}
}

View File

@ -9,7 +9,7 @@ import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import cc.winboll.studio.contacts.fragments.CallFragment;
import cc.winboll.studio.contacts.fragments.CallLogFragment;
import cc.winboll.studio.contacts.fragments.ContactsFragment;
import cc.winboll.studio.contacts.fragments.LogFragment;
@ -30,7 +30,7 @@ public class MyPagerAdapter extends FragmentPagerAdapter {
} else if(position == 2) {
return LogFragment.newInstance(position);
} else {
return CallFragment.newInstance(position);
return CallLogFragment.newInstance(position);
}
}

View File

@ -0,0 +1,36 @@
package cc.winboll.studio.contacts.beans;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/26 13:10:57
* @Describe CallLogModel
*/
import java.util.Date;
public class CallLogModel {
public static final String TAG = "CallLogModel";
private String phoneNumber;
private String callStatus;
private Date callDate;
public CallLogModel(String phoneNumber, String callStatus, Date callDate) {
this.phoneNumber = phoneNumber;
this.callStatus = callStatus;
this.callDate = callDate;
}
public String getPhoneNumber() {
return phoneNumber;
}
public String getCallStatus() {
return callStatus;
}
public Date getCallDate() {
return callDate;
}
}

View File

@ -0,0 +1,28 @@
package cc.winboll.studio.contacts.beans;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/26 13:37:00
* @Describe ContactModel
*/
public class ContactModel {
public static final String TAG = "ContactModel";
private String name;
private String number;
public ContactModel(String name, String number) {
this.name = name;
this.number = number;
}
public String getName() {
return name;
}
public String getNumber() {
return number;
}
}

View File

@ -1,51 +0,0 @@
package cc.winboll.studio.contacts.fragments;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/20 12:57:00
* @Describe 拨号
*/
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import cc.winboll.studio.contacts.R;
import cc.winboll.studio.libappbase.LogView;
import androidx.annotation.Nullable;
import androidx.annotation.NonNull;
import android.widget.TextView;
public class CallFragment extends Fragment {
public static final String TAG = "CallFragment";
private static final String ARG_PAGE = "ARG_PAGE";
private int mPage;
public static CallFragment newInstance(int page) {
Bundle args = new Bundle();
args.putInt(ARG_PAGE, page);
CallFragment fragment = new CallFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments()!= null) {
mPage = getArguments().getInt(ARG_PAGE);
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_call, container, false);
TextView textView = view.findViewById(R.id.page_text);
textView.setText("这是第 " + mPage + "");
return view;
}
}

View File

@ -0,0 +1,125 @@
package cc.winboll.studio.contacts.fragments;
/**
* @Author ZhanGSKen@AliYun.Com
* @Date 2025/02/20 12:57:00
* @Describe 拨号
*/
import android.Manifest;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.CallLog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import cc.winboll.studio.contacts.R;
import cc.winboll.studio.contacts.adapters.CallLogAdapter;
import cc.winboll.studio.contacts.beans.CallLogModel;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class CallLogFragment extends Fragment {
public static final String TAG = "CallFragment";
private static final String ARG_PAGE = "ARG_PAGE";
private int mPage;
private static final int REQUEST_READ_CALL_LOG = 1;
private RecyclerView recyclerView;
private CallLogAdapter callLogAdapter;
private List<CallLogModel> callLogList = new ArrayList<>();
public static CallLogFragment newInstance(int page) {
Bundle args = new Bundle();
args.putInt(ARG_PAGE, page);
CallLogFragment fragment = new CallLogFragment();
fragment.setArguments(args);
return fragment;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_call_log, container, false);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments()!= null) {
mPage = getArguments().getInt(ARG_PAGE);
}
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView = view.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
callLogAdapter = new CallLogAdapter(callLogList);
recyclerView.setAdapter(callLogAdapter);
if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_CALL_LOG)!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(requireActivity(), new String[]{Manifest.permission.READ_CALL_LOG}, REQUEST_READ_CALL_LOG);
} else {
readCallLog();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_READ_CALL_LOG) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
readCallLog();
}
}
}
private void readCallLog() {
Cursor cursor = requireContext().getContentResolver().query(
CallLog.Calls.CONTENT_URI,
null,
null,
null,
CallLog.Calls.DATE + " DESC");
if (cursor!= null) {
while (cursor.moveToNext()) {
String phoneNumber = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));
int callType = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.TYPE));
long callDateLong = cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DATE));
Date callDate = new Date(callDateLong);
String callStatus = getCallStatus(callType);
callLogList.add(new CallLogModel(phoneNumber, callStatus, callDate));
}
cursor.close();
callLogAdapter.notifyDataSetChanged();
}
}
private String getCallStatus(int callType) {
switch (callType) {
case CallLog.Calls.OUTGOING_TYPE:
return "Outgoing";
case CallLog.Calls.INCOMING_TYPE:
return "Incoming";
case CallLog.Calls.MISSED_TYPE:
return "Missed";
default:
return "Unknown";
}
}
}

View File

@ -5,23 +5,39 @@ package cc.winboll.studio.contacts.fragments;
* @Date 2025/02/20 12:57:50
* @Describe 联系人
*/
import android.Manifest;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import cc.winboll.studio.contacts.R;
import cc.winboll.studio.contacts.adapters.ContactAdapter;
import cc.winboll.studio.contacts.beans.ContactModel;
import java.util.ArrayList;
import java.util.List;
public class ContactsFragment extends Fragment {
public static final String TAG = "ContactsFragment";
private static final String ARG_PAGE = "ARG_PAGE";
private int mPage;
private static final int REQUEST_READ_CONTACTS = 1;
private RecyclerView recyclerView;
private ContactAdapter contactAdapter;
private List<ContactModel> contactList = new ArrayList<>();
public static ContactsFragment newInstance(int page) {
Bundle args = new Bundle();
args.putInt(ARG_PAGE, page);
@ -33,18 +49,63 @@ public class ContactsFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments()!= null) {
if (getArguments() != null) {
mPage = getArguments().getInt(ARG_PAGE);
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_contacts, container, false);
TextView textView = view.findViewById(R.id.page_text);
textView.setText("这是第 " + mPage + "");
return view;
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_contacts, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView = view.findViewById(R.id.contacts_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
contactAdapter = new ContactAdapter(contactList);
recyclerView.setAdapter(contactAdapter);
if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(requireActivity(), new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_READ_CONTACTS);
} else {
readContacts();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_READ_CONTACTS) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
readContacts();
}
}
}
private void readContacts() {
contactList.clear();
Cursor cursor = requireContext().getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
null,
null,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
if (cursor != null) {
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactList.add(new ContactModel(name, number));
}
cursor.close();
contactAdapter.notifyDataSetChanged();
}
}
}

View File

@ -9,9 +9,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import cc.winboll.studio.contacts.services.MainService;
import cc.winboll.studio.libappbase.LogUtils;
import com.hjq.toast.ToastUtils;
import java.lang.ref.WeakReference;

View File

@ -15,8 +15,6 @@ import android.os.IBinder;
import cc.winboll.studio.contacts.beans.MainServiceBean;
import cc.winboll.studio.contacts.services.MainService;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.SOS;
import cc.winboll.studio.libappbase.bean.APPSOSBean;
public class AssistantService extends Service {

View File

@ -11,28 +11,26 @@ package cc.winboll.studio.contacts.services;
* https://blog.csdn.net/cyp331203/article/details/38920491
*/
import android.app.Service;
import cc.winboll.studio.contacts.listenphonecall.CallListenerService;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.media.AudioManager;
import android.os.Binder;
import android.os.IBinder;
import cc.winboll.studio.contacts.beans.MainServiceBean;
import cc.winboll.studio.contacts.beans.RingTongBean;
import cc.winboll.studio.contacts.dun.Rules;
import cc.winboll.studio.contacts.handlers.MainServiceHandler;
import cc.winboll.studio.contacts.listenphonecall.CallListenerService;
import cc.winboll.studio.contacts.receivers.MainReceiver;
import cc.winboll.studio.contacts.services.MainService;
import cc.winboll.studio.contacts.threads.MainServiceThread;
import cc.winboll.studio.contacts.widgets.APPStatusWidget;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.libappbase.SOS;
import cc.winboll.studio.libappbase.bean.APPSOSBean;
import cc.winboll.studio.contacts.dun.Rules;
import android.media.AudioManager;
import com.hjq.toast.ToastUtils;
import java.util.Timer;
import java.util.TimerTask;
import cc.winboll.studio.contacts.beans.RingTongBean;
public class MainService extends Service {

View File

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="0dp"
android:ems="10"
android:layout_height="wrap_content"
android:layout_weight="1.0"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text"
android:id="@+id/page_text"/>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

View File

@ -6,10 +6,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text"
android:id="@+id/page_text"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/contacts_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
android:padding="16dp">
<TextView
android:id="@+id/phone_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="@+id/call_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_marginTop="4dp" />
<TextView
android:id="@+id/call_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_marginTop="4dp" />
</LinearLayout>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/contact_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold"/>
<TextView
android:id="@+id/contact_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_marginTop="4dp"/>
</LinearLayout>