version:3.2

fix:
update:增加拨号,添加联系人,通话记录
This commit is contained in:
2023-04-28 10:52:38 +08:00
parent dee497c0a2
commit 2a0fa9f4dc
104 changed files with 3170 additions and 177 deletions

View File

@@ -21,7 +21,7 @@ import com.uiuios.aios.bean.Contact;
import com.uiuios.aios.config.CommonConfig;
import com.uiuios.aios.disklrucache.CacheHelper;
import com.uiuios.aios.network.NetInterfaceManager;
import com.uiuios.aios.network.URLAddress;
import com.uiuios.aios.network.UrlAddress;
import com.uiuios.aios.receiver.BootReceiver;
import com.uiuios.aios.utils.ToastUtil;
@@ -71,7 +71,7 @@ public class EmergencyActivity extends AppCompatActivity {
// return;
// }
String jsonString = mCacheHelper.getAsString(URLAddress.GET_MAIL_LIST);
String jsonString = mCacheHelper.getAsString(UrlAddress.GET_MAIL_LIST);
//为 "" 是已经请求成功的
if (jsonString == null) {
return;

View File

@@ -0,0 +1,266 @@
package com.uiuios.aios.activity.contact;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import com.luck.picture.lib.basic.PictureSelector;
import com.luck.picture.lib.config.SelectMimeType;
import com.luck.picture.lib.entity.LocalMedia;
import com.luck.picture.lib.interfaces.OnResultCallbackListener;
import com.shehuan.niv.NiceImageView;
import com.trello.rxlifecycle4.RxLifecycle;
import com.trello.rxlifecycle4.android.ActivityEvent;
import com.uiuios.aios.R;
import com.uiuios.aios.base.BaseLightActivity;
import com.uiuios.aios.base.GlideEngine;
import com.uiuios.aios.bean.BaseResponse;
import com.uiuios.aios.network.NetInterfaceManager;
import com.uiuios.aios.utils.GlideLoadUtils;
import com.uiuios.aios.utils.ToastUtil;
import com.uiuios.aios.utils.Utils;
import com.uiuios.aios.view.ToggleButton;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
public class AddContactActivity extends BaseLightActivity {
private static final String TAG = AddContactActivity.class.getSimpleName();
@BindView(R.id.iv_cancel)
ImageView iv_cancel;
@BindView(R.id.iv_confirm)
ImageView iv_confirm;
@BindView(R.id.nv_avatar)
NiceImageView nv_avatar;
@BindView(R.id.et_name)
EditText et_name;
@BindView(R.id.et_phone)
EditText et_phone;
@BindView(R.id.toggleButton)
ToggleButton toggleButton;
private String avatarFilePath;
private boolean urgent = false;
@Override
public int getLayoutId() {
return R.layout.activity_add_contact;
}
@Override
public void initView() {
ButterKnife.bind(this);
}
@Override
public void initData() {
nv_avatar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
selectPicture();
}
});
iv_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
iv_confirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
checkContact();
}
});
iv_confirm.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
checkContact();
}
});
}
private void selectPicture() {
PictureSelector.create(this)
.openGallery(SelectMimeType.ofImage())
.setSelectionMode(1)
.setImageEngine(GlideEngine.createGlideEngine())
.forResult(new OnResultCallbackListener<LocalMedia>() {
@Override
public void onResult(ArrayList<LocalMedia> result) {
avatarFilePath = result.get(0).getPath();
Log.e("selectPicture", "onResult: " + avatarFilePath);
GlideLoadUtils.getInstance().glideLoad(AddContactActivity.this, avatarFilePath, nv_avatar, R.drawable.default_avatar);
}
@Override
public void onCancel() {
}
});
}
private void checkContact() {
String name = et_name.getText().toString();
if (TextUtils.isEmpty(name)) {
ToastUtil.show("请输入联系人姓名");
return;
}
String phone = et_phone.getText().toString();
if (TextUtils.isEmpty(phone)) {
ToastUtil.show("请输入手机号码");
return;
}
File avatarFile;
Log.e("checkContact", "avatarFilePath: " + avatarFilePath);
if (TextUtils.isEmpty(avatarFilePath)) {
avatarFile = drawableToFile(R.drawable.default_avatar, "avatar");
} else {
Uri uri = Uri.parse(avatarFilePath);
avatarFile = uriToFile(uri, AddContactActivity.this);
}
MediaType mediaType = MediaType.Companion.parse("image/png");
RequestBody requestBody = RequestBody.Companion.create(avatarFile, mediaType);
MultipartBody.Part body = MultipartBody.Part.createFormData("avatar", avatarFile.getName(), requestBody);
Map<String, String> params = new HashMap<>();
params.put("sn", Utils.getSerial());
params.put("name", name);
params.put("mobile", phone);
params.put("is_urgent", String.valueOf(toggleButton.isToggleOn()));
NetInterfaceManager.getInstance()
.getMailListAddObservable(params, body)
.compose(RxLifecycle.bindUntilEvent(lifecycleSubject, ActivityEvent.DESTROY))
.subscribe(new Observer<BaseResponse>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
Log.e("checkContact", "onSubscribe: ");
}
@Override
public void onNext(@NonNull BaseResponse baseResponse) {
Log.e("checkContact", "onNext: " + baseResponse);
if (baseResponse.code == 200) {
ToastUtil.show("已添加");
finish();
} else {
ToastUtil.show(baseResponse.msg);
}
}
@Override
public void onError(@NonNull Throwable e) {
Log.e("checkContact", "onError: " + e.getMessage());
}
@Override
public void onComplete() {
Log.e("checkContact", "onComplete: ");
}
});
}
/**
* drawable转为file
*
* @param drawableId drawable的ID
* @param fileName 转换后的文件名
* @return
*/
public File drawableToFile(int drawableId, String fileName) {
// InputStream is = view.getContext().getResources().openRawResource(R.drawable.logo);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), drawableId);
// Bitmap bitmap = BitmapFactory.decodeStream(is);
String defaultPath = getFilesDir().getAbsolutePath() + "/defaultGoodInfo";
File file = new File(defaultPath);
if (!file.exists()) {
file.mkdirs();
}
String defaultImgPath = defaultPath + "/" + fileName;
file = new File(defaultImgPath);
try {
file.createNewFile();
FileOutputStream fOut = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 20, fOut);
// is.close();
fOut.flush();
fOut.close();
} catch (Exception e) {
e.printStackTrace();
}
return file;
}
public static File uriToFile(Uri uri, Context context) {
String path = null;
if ("file".equals(uri.getScheme())) {
path = uri.getEncodedPath();
if (path != null) {
path = Uri.decode(path);
ContentResolver cr = context.getContentResolver();
StringBuffer buff = new StringBuffer();
buff.append("(").append(MediaStore.Images.ImageColumns.DATA).append("=").append("'" + path + "'").append(")");
Cursor cur = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[]{MediaStore.Images.ImageColumns._ID, MediaStore.Images.ImageColumns.DATA}, buff.toString(), null, null);
int index = 0;
int dataIdx = 0;
for (cur.moveToFirst(); !cur.isAfterLast(); cur.moveToNext()) {
index = cur.getColumnIndex(MediaStore.Images.ImageColumns._ID);
index = cur.getInt(index);
dataIdx = cur.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
path = cur.getString(dataIdx);
}
cur.close();
if (index == 0) {
} else {
Uri u = Uri.parse("content://media/external/images/media/" + index);
System.out.println("temp uri is :" + u);
}
}
if (path != null) {
return new File(path);
}
} else if ("content".equals(uri.getScheme())) {
// 4.2.2以后
String[] proj = {MediaStore.Images.Media.DATA};
Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null);
if (cursor.moveToFirst()) {
int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
path = cursor.getString(columnIndex);
}
cursor.close();
return new File(path);
} else {
//Log.i(TAG, "Uri Scheme:" + uri.getScheme());
}
return null;
}
}

View File

@@ -1,5 +1,6 @@
package com.uiuios.aios.activity.contact;
import android.content.Intent;
import android.content.res.Configuration;
import android.view.View;
import android.widget.ImageView;
@@ -26,6 +27,8 @@ public class ContactActivity extends BaseActivity implements ContactContact.Cont
TextView tv_people;
@BindView(R.id.iv_back)
ImageView iv_back;
@BindView(R.id.tv_add)
TextView tv_add;
@OnClick({R.id.iv_back})
public void onClick(View view) {
@@ -58,10 +61,23 @@ public class ContactActivity extends BaseActivity implements ContactContact.Cont
rv_contact.setLayoutManager(new GridLayoutManager(this, 2));
}
rv_contact.setAdapter(mContactAdapter);
tv_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(ContactActivity.this, AddContactActivity.class);
startActivity(intent);
}
});
}
@Override
public void initData() {
}
@Override
protected void onResume() {
super.onResume();
mContactPresenter.getContact();
}

View File

@@ -12,7 +12,7 @@ import com.uiuios.aios.bean.BaseResponse;
import com.uiuios.aios.bean.Contact;
import com.uiuios.aios.config.CommonConfig;
import com.uiuios.aios.network.NetInterfaceManager;
import com.uiuios.aios.network.URLAddress;
import com.uiuios.aios.network.UrlAddress;
import com.uiuios.aios.utils.GsonUtils;
import java.lang.reflect.Type;
@@ -68,10 +68,10 @@ public class ContactPresenter implements ContactContact.Presenter {
public void onNext(@NonNull BaseResponse<List<Contact>> listBaseResponse) {
Log.e("getContactList", "onNext: " + listBaseResponse);
if (listBaseResponse.code == 200) {
mMMKV.putString(URLAddress.GET_MAIL_LIST, GsonUtils.toJsonString(listBaseResponse.data));
mMMKV.putString(UrlAddress.GET_MAIL_LIST, GsonUtils.toJsonString(listBaseResponse.data));
mView.setContact(listBaseResponse.data);
} else {
mMMKV.putString(URLAddress.GET_MAIL_LIST, "");
mMMKV.putString(UrlAddress.GET_MAIL_LIST, "");
mView.setContact(new ArrayList<>());
}
}
@@ -79,7 +79,7 @@ public class ContactPresenter implements ContactContact.Presenter {
@Override
public void onError(@NonNull Throwable e) {
Log.e("getContactList", "onError: " + e.getMessage());
String jsonString = mMMKV.getString(URLAddress.GET_MAIL_LIST, null);
String jsonString = mMMKV.getString(UrlAddress.GET_MAIL_LIST, null);
Gson gson = new Gson();
Type type = new TypeToken<List<Contact>>() {
}.getType();

View File

@@ -0,0 +1,218 @@
package com.uiuios.aios.activity.dialer;
import android.content.Intent;
import android.media.AudioAttributes;
import android.media.SoundPool;
import android.net.Uri;
import android.text.TextUtils;
import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.shehuan.niv.NiceImageView;
import com.uiuios.aios.R;
import com.uiuios.aios.activity.contact.ContactActivity;
import com.uiuios.aios.base.BaseActivity;
import java.util.HashMap;
import butterknife.BindView;
import butterknife.ButterKnife;
public class DialerActivity extends BaseActivity {
@BindView(R.id.et_phone)
EditText et_phone;
@BindView(R.id.iv_delete)
ImageView iv_delete;
@BindView(R.id.nv_dialer)
NiceImageView nv_dialer;
@BindView(R.id.iv_contact)
ImageView iv_contact;
@BindView(R.id.tv_contact)
TextView tv_contact;
@BindView(R.id.cl_0)
ConstraintLayout cl_0;
@BindView(R.id.cl_1)
ConstraintLayout cl_1;
@BindView(R.id.cl_2)
ConstraintLayout cl_2;
@BindView(R.id.cl_3)
ConstraintLayout cl_3;
@BindView(R.id.cl_4)
ConstraintLayout cl_4;
@BindView(R.id.cl_5)
ConstraintLayout cl_5;
@BindView(R.id.cl_6)
ConstraintLayout cl_6;
@BindView(R.id.cl_7)
ConstraintLayout cl_7;
@BindView(R.id.cl_8)
ConstraintLayout cl_8;
@BindView(R.id.cl_9)
ConstraintLayout cl_9;
@BindView(R.id.cl_11)
ConstraintLayout cl_11;
@BindView(R.id.cl_12)
ConstraintLayout cl_12;
private SoundPool soundPool;
private HashMap<Integer, Integer> soundMap = new HashMap<>();
@Override
public int getLayoutId() {
return R.layout.activity_dialer;
}
@Override
public void initView() {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
ButterKnife.bind(this);
AudioAttributes attr = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_GAME) // 设置音效使用场景
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build(); // 设置音效的类型
soundPool = new SoundPool.Builder().setAudioAttributes(attr) // 设置音效池的属性
.setMaxStreams(12) // 设置最多可容纳10个音频流
.build(); // ①
// load方法加载指定音频文件并返回所加载的音效ID
// 此处使用HashMap来管理这些音频流
soundMap.put(0, soundPool.load(this, R.raw.s_0, 1));
soundMap.put(1, soundPool.load(this, R.raw.s_1, 1));
soundMap.put(2, soundPool.load(this, R.raw.s_2, 1));
soundMap.put(3, soundPool.load(this, R.raw.s_3, 1));
soundMap.put(4, soundPool.load(this, R.raw.s_4, 1));
soundMap.put(5, soundPool.load(this, R.raw.s_5, 1));
soundMap.put(6, soundPool.load(this, R.raw.s_6, 1));
soundMap.put(7, soundPool.load(this, R.raw.s_7, 1));
soundMap.put(8, soundPool.load(this, R.raw.s_8, 1));
soundMap.put(9, soundPool.load(this, R.raw.s_9, 1));
soundMap.put(10, soundPool.load(this, R.raw.s_x, 1));
soundMap.put(11, soundPool.load(this, R.raw.s_j, 1));
}
@Override
public void initData() {
cl_0.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addNumber("0", 0);
}
});
cl_1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addNumber("1", 1);
}
});
cl_2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addNumber("2", 2);
}
});
cl_3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addNumber("3", 3);
}
});
cl_4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addNumber("4", 4);
}
});
cl_5.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addNumber("5", 5);
}
});
cl_6.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addNumber("6", 6);
}
});
cl_7.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addNumber("7", 7);
}
});
cl_8.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addNumber("8", 8);
}
});
cl_9.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addNumber("9", 9);
}
});
cl_11.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addNumber("*", 10);
}
});
cl_12.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addNumber("#", 11);
}
});
nv_dialer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String phone = et_phone.getText().toString();
Intent dialIntent = new Intent(Intent.ACTION_CALL);
Uri data = Uri.parse("tel:" + phone);
dialIntent.setData(data);
startActivity(dialIntent);
}
});
iv_delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String tmp = et_phone.getText().toString();
if (TextUtils.isEmpty(tmp)) {
et_phone.setText("");
} else {
et_phone.setText(tmp.substring(0, tmp.length() - 1));
}
}
});
iv_contact.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(DialerActivity.this, ContactActivity.class);
startActivity(intent);
}
});
tv_contact.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(DialerActivity.this, ContactActivity.class);
startActivity(intent);
}
});
}
private void addNumber(String number, int position) {
String tmp = et_phone.getText().toString();
if (TextUtils.isEmpty(tmp)) {
et_phone.setText(number);
} else {
et_phone.setText(tmp + number);
}
soundPool.play(soundMap.get(position), 1, 1, 0, 0, 1);
}
}

View File

@@ -0,0 +1,167 @@
package com.uiuios.aios.activity.records;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.CallLog;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.shehuan.niv.NiceImageView;
import com.uiuios.aios.R;
import com.uiuios.aios.activity.dialer.DialerActivity;
import com.uiuios.aios.adapter.CallRecordAdapter;
import com.uiuios.aios.bean.RecordsInfo;
import com.zackratos.ultimatebarx.ultimatebarx.java.UltimateBarX;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
public class RecordsActivity extends AppCompatActivity {
private static final String TAG = RecordsActivity.class.getSimpleName();
@BindView(R.id.recyclerView)
RecyclerView recyclerView;
@BindView(R.id.iv_cancel)
ImageView iv_cancel;
@BindView(R.id.iv_clear)
ImageView iv_clear;
@BindView(R.id.nv_dialer)
NiceImageView nv_dialer;
@BindView(R.id.tv_nodata)
TextView tv_nodata;
private CallRecordAdapter mCallRecordAdapter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_records);
UltimateBarX.statusBarOnly(this)
.colorRes(R.color.default_blue)
.fitWindow(true)
.apply();
ButterKnife.bind(this);
Log.e(TAG, "initData: " + dataList);
mCallRecordAdapter = new CallRecordAdapter();
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(RecordsActivity.this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(mCallRecordAdapter);
iv_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
nv_dialer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(RecordsActivity.this, DialerActivity.class));
}
});
iv_clear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
for (RecordsInfo recordsInfo : dataList) {
String queryString = "NUMBER=" + recordsInfo.getNumber();
getContentResolver().delete(CallLog.Calls.CONTENT_URI, queryString, null);
}
getData();
}
});
}
@Override
protected void onResume() {
super.onResume();
getData();
}
private void getData() {
dataList = getDataList();
if (dataList.size() == 0) {
tv_nodata.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
} else {
tv_nodata.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
}
mCallRecordAdapter.setRecordsInfoList(dataList);
}
private List<RecordsInfo> dataList;
/**
* 读取数据
*
* @return 读取到的数据
*/
private List<RecordsInfo> getDataList() {
// 1.获得ContentResolver
ContentResolver resolver = getContentResolver();
// 2.利用ContentResolver的query方法查询通话记录数据库
/**
* @param uri 需要查询的URI这个URI是ContentProvider提供的
* @param projection 需要查询的字段
* @param selection sql语句where之后的语句
* @param selectionArgs ?占位符代表的数据
* @param sortOrder 排序方式
*
*/
Cursor cursor = resolver.query(CallLog.Calls.CONTENT_URI, // 查询通话记录的URI
new String[]{CallLog.Calls.CACHED_NAME// 通话记录的联系人
, CallLog.Calls.NUMBER// 通话记录的电话号码
, CallLog.Calls.DATE// 通话记录的日期
, CallLog.Calls.DURATION// 通话时长
, CallLog.Calls.TYPE}// 通话类型
, null, null, CallLog.Calls.DEFAULT_SORT_ORDER// 按照时间逆序排列,最近打的最先显示
);
// 3.通过Cursor获得数据
List<RecordsInfo> list = new ArrayList<>();
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex(CallLog.Calls.CACHED_NAME));
String number = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));
long dateLong = cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DATE));
// String date = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss").format(new Date(dateLong));
int duration = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.DURATION));
int type = cursor.getInt(cursor.getColumnIndex(CallLog.Calls.TYPE));
RecordsInfo recordsInfo = new RecordsInfo();
recordsInfo.setName(name);
recordsInfo.setNumber(number);
recordsInfo.setDate(dateLong);
recordsInfo.setDuration(duration);
recordsInfo.setType(type);
list.add(recordsInfo);
String typeString = "";
switch (type) {
case CallLog.Calls.INCOMING_TYPE:
typeString = "打入";
break;
case CallLog.Calls.OUTGOING_TYPE:
typeString = "打出";
break;
case CallLog.Calls.MISSED_TYPE:
typeString = "未接";
break;
default:
break;
}
}
return list;
}
}