增加app在内外显示,支持长按显示隐藏,优化命名,主页app显示还有问题
This commit is contained in:
@@ -8,9 +8,9 @@ import com.tencent.mmkv.MMKV;
|
|||||||
import com.ttstd.dialer.R;
|
import com.ttstd.dialer.R;
|
||||||
import com.ttstd.dialer.adapter.MoreAppAdapter;
|
import com.ttstd.dialer.adapter.MoreAppAdapter;
|
||||||
import com.ttstd.dialer.base.mvvm.BaseMvvmActivity;
|
import com.ttstd.dialer.base.mvvm.BaseMvvmActivity;
|
||||||
import com.ttstd.dialer.db.app.DesktopSortApp;
|
|
||||||
import com.ttstd.dialer.config.CommonConfig;
|
import com.ttstd.dialer.config.CommonConfig;
|
||||||
import com.ttstd.dialer.databinding.ActivityAppListBinding;
|
import com.ttstd.dialer.databinding.ActivityAppListBinding;
|
||||||
|
import com.ttstd.dialer.db.app.AppInfo;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -48,6 +48,13 @@ public class AppListActivity extends BaseMvvmActivity<AppListViewModel, Activity
|
|||||||
@Override
|
@Override
|
||||||
protected void initView() {
|
protected void initView() {
|
||||||
mMoreAppAdapter = new MoreAppAdapter(LoaderManager.getInstance(this));
|
mMoreAppAdapter = new MoreAppAdapter(LoaderManager.getInstance(this));
|
||||||
|
mMoreAppAdapter.setShortcutCallback(new MoreAppAdapter.ShortcutCallback() {
|
||||||
|
@Override
|
||||||
|
public void setAppOutside(AppInfo appInfo) {
|
||||||
|
appInfo.setOutside(1);
|
||||||
|
mViewModel.updateAppInfo(appInfo);
|
||||||
|
}
|
||||||
|
});
|
||||||
mViewDataBinding.recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
|
mViewDataBinding.recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
|
||||||
mViewDataBinding.recyclerView.setAdapter(mMoreAppAdapter);
|
mViewDataBinding.recyclerView.setAdapter(mMoreAppAdapter);
|
||||||
|
|
||||||
@@ -55,15 +62,24 @@ public class AppListActivity extends BaseMvvmActivity<AppListViewModel, Activity
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initData() {
|
protected void initData() {
|
||||||
mViewModel.mDesktopSortAppData.observe(this, new Observer<List<DesktopSortApp>>() {
|
mViewModel.mDesktopSortAppData.observe(this, new Observer<List<AppInfo>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(List<DesktopSortApp> desktopSortApps) {
|
public void onChanged(List<AppInfo> appInfos) {
|
||||||
mMoreAppAdapter.setDesktopSortApps(desktopSortApps);
|
mMoreAppAdapter.setAppInfos(appInfos);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// mViewModel.getLauncherAppList();
|
|
||||||
mViewModel.getDbAppList();
|
mViewModel.getDbAppList();
|
||||||
|
|
||||||
|
mViewModel.mAppUpdateData.observe(this, new Observer<Integer>() {
|
||||||
|
@Override
|
||||||
|
public void onChanged(Integer integer) {
|
||||||
|
if (integer > 0) {
|
||||||
|
|
||||||
|
}
|
||||||
|
mViewModel.getDbAppList();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import com.trello.rxlifecycle4.RxLifecycle;
|
|||||||
import com.trello.rxlifecycle4.android.ActivityEvent;
|
import com.trello.rxlifecycle4.android.ActivityEvent;
|
||||||
import com.ttstd.dialer.base.mvvm.BaseViewModel;
|
import com.ttstd.dialer.base.mvvm.BaseViewModel;
|
||||||
import com.ttstd.dialer.databinding.ActivityAppListBinding;
|
import com.ttstd.dialer.databinding.ActivityAppListBinding;
|
||||||
|
import com.ttstd.dialer.db.app.AppInfo;
|
||||||
import com.ttstd.dialer.db.app.AppRepository;
|
import com.ttstd.dialer.db.app.AppRepository;
|
||||||
import com.ttstd.dialer.db.app.DesktopSortApp;
|
|
||||||
import com.ttstd.dialer.utils.ApkUtils;
|
import com.ttstd.dialer.utils.ApkUtils;
|
||||||
|
|
||||||
import java.text.Collator;
|
import java.text.Collator;
|
||||||
@@ -41,27 +41,27 @@ public class AppListViewModel extends BaseViewModel<ActivityAppListBinding, Acti
|
|||||||
mAppRepository = new AppRepository(context);
|
mAppRepository = new AppRepository(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MutableLiveData<List<DesktopSortApp>> mDesktopSortAppData = new MutableLiveData<>();
|
public MutableLiveData<List<AppInfo>> mDesktopSortAppData = new MutableLiveData<>();
|
||||||
|
|
||||||
public void getDbAppList() {
|
public void getDbAppList() {
|
||||||
Observable.fromCallable(new Callable<List<DesktopSortApp>>() {
|
Observable.fromCallable(new Callable<List<AppInfo>>() {
|
||||||
@Override
|
@Override
|
||||||
public List<DesktopSortApp> call() throws Exception {
|
public List<AppInfo> call() throws Exception {
|
||||||
return mAppRepository.getAllApp();
|
return mAppRepository.getInsideApp();
|
||||||
}
|
}
|
||||||
}).compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY))
|
}).compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(new Observer<List<DesktopSortApp>>() {
|
.subscribe(new Observer<List<AppInfo>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSubscribe(@NonNull Disposable d) {
|
public void onSubscribe(@NonNull Disposable d) {
|
||||||
Log.e("getDbAppList", "onSubscribe: ");
|
Log.e("getDbAppList", "onSubscribe: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNext(@NonNull List<DesktopSortApp> desktopSortApps) {
|
public void onNext(@NonNull List<AppInfo> appInfos) {
|
||||||
Log.e("getDbAppList", "onNext: " + desktopSortApps);
|
Log.e("getDbAppList", "onNext: " + appInfos);
|
||||||
mDesktopSortAppData.setValue(desktopSortApps);
|
mDesktopSortAppData.setValue(appInfos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -74,80 +74,41 @@ public class AppListViewModel extends BaseViewModel<ActivityAppListBinding, Acti
|
|||||||
Log.e("getDbAppList", "onComplete: ");
|
Log.e("getDbAppList", "onComplete: ");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getLauncherAppList() {
|
public MutableLiveData<Integer> mAppUpdateData = new MutableLiveData<>();
|
||||||
Observable.fromCallable(new Callable<List<ResolveInfo>>() {
|
|
||||||
|
public void updateAppInfo(AppInfo appInfo){
|
||||||
|
Observable.fromCallable(new Callable<Integer>() {
|
||||||
@Override
|
@Override
|
||||||
public List<ResolveInfo> call() throws Exception {
|
public Integer call() throws Exception {
|
||||||
return ApkUtils.getAllLauncherResolveInfo(getSafeContext());
|
return mAppRepository.update(appInfo);
|
||||||
}
|
}
|
||||||
})
|
}).compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY))
|
||||||
.compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY))
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.map(new Function<List<ResolveInfo>, List<ComponentName>>() {
|
|
||||||
@Override
|
|
||||||
public List<ComponentName> apply(List<ResolveInfo> resolveInfos) throws Throwable {
|
|
||||||
List<ComponentName> componentNames = resolveInfos.stream().map(new java.util.function.Function<ResolveInfo, ComponentName>() {
|
|
||||||
@Override
|
|
||||||
public ComponentName apply(ResolveInfo resolveInfo) {
|
|
||||||
String packageName = resolveInfo.activityInfo.packageName;
|
|
||||||
String className = resolveInfo.activityInfo.name;
|
|
||||||
ComponentName componentName = new ComponentName(packageName, className);
|
|
||||||
return componentName;
|
|
||||||
}
|
|
||||||
}).collect(Collectors.toList());
|
|
||||||
return componentNames;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY))
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.map(new Function<List<ComponentName>, List<DesktopSortApp>>() {
|
|
||||||
@Override
|
|
||||||
public List<DesktopSortApp> apply(List<ComponentName> componentNames) throws Throwable {
|
|
||||||
List<DesktopSortApp> desktopSortApps = componentNames.stream().map(new java.util.function.Function<ComponentName, DesktopSortApp>() {
|
|
||||||
@Override
|
|
||||||
public DesktopSortApp apply(ComponentName componentName) {
|
|
||||||
DesktopSortApp desktopSortApp = new DesktopSortApp(getSafeContext(), componentName);
|
|
||||||
return desktopSortApp;
|
|
||||||
}
|
|
||||||
}).sorted(new Comparator<DesktopSortApp>() {
|
|
||||||
@Override
|
|
||||||
public int compare(DesktopSortApp o1, DesktopSortApp o2) {
|
|
||||||
return Collator.getInstance(Locale.CHINESE).compare(o1.getLabel(), o2.getLabel());
|
|
||||||
}
|
|
||||||
}).collect(Collectors.toList());
|
|
||||||
return desktopSortApps;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY))
|
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(new Observer<List<DesktopSortApp>>() {
|
.subscribe(new Observer<Integer>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSubscribe(@NonNull Disposable d) {
|
public void onSubscribe(@NonNull Disposable d) {
|
||||||
|
Log.e("updateAppInfo", "onSubscribe: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNext(@NonNull List<DesktopSortApp> desktopSortApps) {
|
public void onNext(@NonNull Integer row) {
|
||||||
Log.e(TAG, "getLauncherAppList" + "onNext: " + desktopSortApps);
|
Log.e("updateAppInfo", "onNext: " + row);
|
||||||
mDesktopSortAppData.setValue(desktopSortApps);
|
mAppUpdateData.setValue(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(@NonNull Throwable e) {
|
public void onError(@NonNull Throwable e) {
|
||||||
|
Log.e("updateAppInfo", "onError: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onComplete() {
|
public void onComplete() {
|
||||||
|
Log.e("updateAppInfo", "onComplete: ");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import com.trello.rxlifecycle4.RxLifecycle;
|
|||||||
import com.trello.rxlifecycle4.android.ActivityEvent;
|
import com.trello.rxlifecycle4.android.ActivityEvent;
|
||||||
import com.ttstd.dialer.base.mvvm.BaseViewModel;
|
import com.ttstd.dialer.base.mvvm.BaseViewModel;
|
||||||
import com.ttstd.dialer.databinding.ActivityContactAddBinding;
|
import com.ttstd.dialer.databinding.ActivityContactAddBinding;
|
||||||
import com.ttstd.dialer.db.contact.Contact;
|
import com.ttstd.dialer.db.contact.ContactInfo;
|
||||||
import com.ttstd.dialer.db.contact.ContactRepository;
|
import com.ttstd.dialer.db.contact.ContactRepository;
|
||||||
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
@@ -38,9 +38,9 @@ public class ContactAddViewModel extends BaseViewModel<ActivityContactAddBinding
|
|||||||
@Override
|
@Override
|
||||||
public void subscribe(@NonNull ObservableEmitter<Long> emitter) throws Throwable {
|
public void subscribe(@NonNull ObservableEmitter<Long> emitter) throws Throwable {
|
||||||
int count = mRepository.getTotalCount() + 1;
|
int count = mRepository.getTotalCount() + 1;
|
||||||
Contact contact = new Contact(name, phone, count);
|
ContactInfo contactInfo = new ContactInfo(name, phone, count);
|
||||||
Log.e(TAG, "saveContact: " + contact);
|
Log.e(TAG, "saveContact: " + contactInfo);
|
||||||
emitter.onNext(mRepository.insert(contact));
|
emitter.onNext(mRepository.insert(contactInfo));
|
||||||
emitter.onComplete();
|
emitter.onComplete();
|
||||||
}
|
}
|
||||||
}).compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY))
|
}).compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY))
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
package com.ttstd.dialer.activity.contact.list;
|
package com.ttstd.dialer.activity.contact.list;
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.Uri;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.core.app.ActivityCompat;
|
|
||||||
import androidx.lifecycle.Observer;
|
import androidx.lifecycle.Observer;
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
@@ -18,7 +15,7 @@ import com.ttstd.dialer.activity.contact.add.ContactAddActivity;
|
|||||||
import com.ttstd.dialer.adapter.ContactInfoAdapter;
|
import com.ttstd.dialer.adapter.ContactInfoAdapter;
|
||||||
import com.ttstd.dialer.base.mvvm.BaseMvvmActivity;
|
import com.ttstd.dialer.base.mvvm.BaseMvvmActivity;
|
||||||
import com.ttstd.dialer.databinding.ActivityContactListBinding;
|
import com.ttstd.dialer.databinding.ActivityContactListBinding;
|
||||||
import com.ttstd.dialer.db.contact.Contact;
|
import com.ttstd.dialer.db.contact.ContactInfo;
|
||||||
import com.ttstd.dialer.fragment.dialog.call.CallFragment;
|
import com.ttstd.dialer.fragment.dialog.call.CallFragment;
|
||||||
import com.ttstd.dialer.view.ItemTouchHelperCallback;
|
import com.ttstd.dialer.view.ItemTouchHelperCallback;
|
||||||
|
|
||||||
@@ -31,7 +28,7 @@ public class ContactListActivity extends BaseMvvmActivity<ContactListViewModel,
|
|||||||
|
|
||||||
private ContactInfoAdapter mContactInfoAdapter;
|
private ContactInfoAdapter mContactInfoAdapter;
|
||||||
|
|
||||||
private List<Contact> mContacts;
|
private List<ContactInfo> mContactInfos;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setNightMode() {
|
public boolean setNightMode() {
|
||||||
@@ -63,14 +60,14 @@ public class ContactListActivity extends BaseMvvmActivity<ContactListViewModel,
|
|||||||
@Override
|
@Override
|
||||||
public void onItemMove(int fromPosition, int toPosition) {
|
public void onItemMove(int fromPosition, int toPosition) {
|
||||||
Log.e(TAG, "onItemMove: ");
|
Log.e(TAG, "onItemMove: ");
|
||||||
Contact fromContact = mContacts.get(fromPosition);
|
ContactInfo fromContactInfo = mContactInfos.get(fromPosition);
|
||||||
int fromContactPosition = fromContact.getPosition();
|
int fromContactPosition = fromContactInfo.getPosition();
|
||||||
Contact toContact = mContacts.get(toPosition);
|
ContactInfo toContactInfo = mContactInfos.get(toPosition);
|
||||||
int toContactPosition = toContact.getPosition();
|
int toContactPosition = toContactInfo.getPosition();
|
||||||
fromContact.setPosition(toContactPosition);
|
fromContactInfo.setPosition(toContactPosition);
|
||||||
mViewModel.updateItemPosition(fromContact);
|
mViewModel.updateItemPosition(fromContactInfo);
|
||||||
toContact.setPosition(fromContactPosition);
|
toContactInfo.setPosition(fromContactPosition);
|
||||||
mViewModel.updateItemPosition(toContact);
|
mViewModel.updateItemPosition(toContactInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -81,8 +78,8 @@ public class ContactListActivity extends BaseMvvmActivity<ContactListViewModel,
|
|||||||
});
|
});
|
||||||
mContactInfoAdapter.setOnClickListener(new ContactInfoAdapter.OnClickListener() {
|
mContactInfoAdapter.setOnClickListener(new ContactInfoAdapter.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(Contact contact) {
|
public void onClick(ContactInfo contactInfo) {
|
||||||
new CallFragment(contact).show(getSupportFragmentManager(), "CallFragment");
|
new CallFragment(contactInfo).show(getSupportFragmentManager(), "CallFragment");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// 设置ItemTouchHelper,实现拖动和滑动删除
|
// 设置ItemTouchHelper,实现拖动和滑动删除
|
||||||
@@ -98,12 +95,12 @@ public class ContactListActivity extends BaseMvvmActivity<ContactListViewModel,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initData() {
|
protected void initData() {
|
||||||
mViewModel.mContactListData.observe(this, new Observer<List<Contact>>() {
|
mViewModel.mContactListData.observe(this, new Observer<List<ContactInfo>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(List<Contact> contacts) {
|
public void onChanged(List<ContactInfo> contactInfos) {
|
||||||
Log.e(TAG, "mContactListData: " + contacts);
|
Log.e(TAG, "mContactListData: " + contactInfos);
|
||||||
mContacts = contacts;
|
mContactInfos = contactInfos;
|
||||||
mContactInfoAdapter.setContacts(mContacts);
|
mContactInfoAdapter.setContactInfos(mContactInfos);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import com.trello.rxlifecycle4.RxLifecycle;
|
|||||||
import com.trello.rxlifecycle4.android.ActivityEvent;
|
import com.trello.rxlifecycle4.android.ActivityEvent;
|
||||||
import com.ttstd.dialer.base.mvvm.BaseViewModel;
|
import com.ttstd.dialer.base.mvvm.BaseViewModel;
|
||||||
import com.ttstd.dialer.databinding.ActivityContactListBinding;
|
import com.ttstd.dialer.databinding.ActivityContactListBinding;
|
||||||
import com.ttstd.dialer.db.contact.Contact;
|
import com.ttstd.dialer.db.contact.ContactInfo;
|
||||||
import com.ttstd.dialer.db.contact.ContactRepository;
|
import com.ttstd.dialer.db.contact.ContactRepository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -33,29 +33,29 @@ public class ContactListViewModel extends BaseViewModel<ActivityContactListBindi
|
|||||||
mRepository = new ContactRepository(context);
|
mRepository = new ContactRepository(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MutableLiveData<List<Contact>> mContactListData = new MutableLiveData<>();
|
public MutableLiveData<List<ContactInfo>> mContactListData = new MutableLiveData<>();
|
||||||
|
|
||||||
public void getAllContacts() {
|
public void getAllContacts() {
|
||||||
Observable.create(new ObservableOnSubscribe<List<Contact>>() {
|
Observable.create(new ObservableOnSubscribe<List<ContactInfo>>() {
|
||||||
@Override
|
@Override
|
||||||
public void subscribe(@NonNull ObservableEmitter<List<Contact>> emitter) throws Throwable {
|
public void subscribe(@NonNull ObservableEmitter<List<ContactInfo>> emitter) throws Throwable {
|
||||||
List<Contact> contacts = mRepository.getAllContacts();
|
List<ContactInfo> contactInfos = mRepository.getAllContacts();
|
||||||
emitter.onNext(contacts);
|
emitter.onNext(contactInfos);
|
||||||
emitter.onComplete();
|
emitter.onComplete();
|
||||||
}
|
}
|
||||||
}).compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY))
|
}).compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(new Observer<List<Contact>>() {
|
.subscribe(new Observer<List<ContactInfo>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSubscribe(@NonNull Disposable d) {
|
public void onSubscribe(@NonNull Disposable d) {
|
||||||
Log.e("getAllContacts", "onSubscribe: ");
|
Log.e("getAllContacts", "onSubscribe: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNext(@NonNull List<Contact> contacts) {
|
public void onNext(@NonNull List<ContactInfo> contactInfos) {
|
||||||
Log.e("getAllContacts", "onNext: ");
|
Log.e("getAllContacts", "onNext: ");
|
||||||
mContactListData.setValue(contacts);
|
mContactListData.setValue(contactInfos);
|
||||||
|
|
||||||
// List<Contact> sorted = contacts.stream().sorted(new Comparator<Contact>() {
|
// List<Contact> sorted = contacts.stream().sorted(new Comparator<Contact>() {
|
||||||
// @Override
|
// @Override
|
||||||
@@ -78,12 +78,12 @@ public class ContactListViewModel extends BaseViewModel<ActivityContactListBindi
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateItemPosition(Contact contact) {
|
public void updateItemPosition(ContactInfo contactInfo) {
|
||||||
Log.e(TAG, "updateItemPosition: " + contact);
|
Log.e(TAG, "updateItemPosition: " + contactInfo);
|
||||||
Observable.create(new ObservableOnSubscribe<Integer>() {
|
Observable.create(new ObservableOnSubscribe<Integer>() {
|
||||||
@Override
|
@Override
|
||||||
public void subscribe(@NonNull ObservableEmitter<Integer> emitter) throws Throwable {
|
public void subscribe(@NonNull ObservableEmitter<Integer> emitter) throws Throwable {
|
||||||
int id = mRepository.update(contact);
|
int id = mRepository.update(contactInfo);
|
||||||
emitter.onNext(id);
|
emitter.onNext(id);
|
||||||
emitter.onComplete();
|
emitter.onComplete();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,14 +4,19 @@ import android.util.Log;
|
|||||||
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
import androidx.lifecycle.Observer;
|
||||||
|
import androidx.loader.app.LoaderManager;
|
||||||
|
|
||||||
import com.tencent.mmkv.MMKV;
|
import com.tencent.mmkv.MMKV;
|
||||||
import com.ttstd.dialer.R;
|
import com.ttstd.dialer.R;
|
||||||
import com.ttstd.dialer.base.mvvm.BaseMvvmActivity;
|
import com.ttstd.dialer.base.mvvm.BaseMvvmActivity;
|
||||||
import com.ttstd.dialer.config.CommonConfig;
|
import com.ttstd.dialer.config.CommonConfig;
|
||||||
import com.ttstd.dialer.databinding.ActivityMainBinding;
|
import com.ttstd.dialer.databinding.ActivityMainBinding;
|
||||||
|
import com.ttstd.dialer.db.app.AppInfo;
|
||||||
|
import com.ttstd.dialer.fragment.app.AppFragment;
|
||||||
import com.ttstd.dialer.fragment.contact.ContactFragment;
|
import com.ttstd.dialer.fragment.contact.ContactFragment;
|
||||||
import com.ttstd.dialer.fragment.home.HomeFragment;
|
import com.ttstd.dialer.fragment.home.HomeFragment;
|
||||||
|
import com.ttstd.dialer.view.ApkPagerAdapter;
|
||||||
import com.ttstd.dialer.view.BaseFragmentPagerAdapter;
|
import com.ttstd.dialer.view.BaseFragmentPagerAdapter;
|
||||||
import com.ttstd.dialer.view.ScaleCircleNavigator;
|
import com.ttstd.dialer.view.ScaleCircleNavigator;
|
||||||
|
|
||||||
@@ -25,7 +30,8 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
|
|||||||
protected MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
|
protected MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
|
||||||
|
|
||||||
private FragmentManager mFragmentManager = getSupportFragmentManager();
|
private FragmentManager mFragmentManager = getSupportFragmentManager();
|
||||||
private BaseFragmentPagerAdapter mBaseFragmentPagerAdapter;
|
// private BaseFragmentPagerAdapter mBaseFragmentPagerAdapter;
|
||||||
|
private ApkPagerAdapter mApkPagerAdapter;
|
||||||
|
|
||||||
private List<Fragment> mFragments = new ArrayList<>();
|
private List<Fragment> mFragments = new ArrayList<>();
|
||||||
private HomeFragment mHomeFragment;
|
private HomeFragment mHomeFragment;
|
||||||
@@ -34,8 +40,12 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
|
|||||||
private int mCurrentIndex = 0;
|
private int mCurrentIndex = 0;
|
||||||
private int mFragmentSize = 0;
|
private int mFragmentSize = 0;
|
||||||
|
|
||||||
|
private int APK_PER_FRAGMENT = 9;
|
||||||
|
|
||||||
private ScaleCircleNavigator mScaleCircleNavigator;
|
private ScaleCircleNavigator mScaleCircleNavigator;
|
||||||
|
|
||||||
|
private List<AppInfo> mAppInfos;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setNightMode() {
|
public boolean setNightMode() {
|
||||||
@@ -62,18 +72,21 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initView() {
|
protected void initView() {
|
||||||
|
// mBaseFragmentPagerAdapter = new BaseFragmentPagerAdapter(mFragmentManager, mFragments);
|
||||||
|
mApkPagerAdapter = new ApkPagerAdapter(mFragmentManager);
|
||||||
|
|
||||||
mScaleCircleNavigator = new ScaleCircleNavigator(this);
|
mScaleCircleNavigator = new ScaleCircleNavigator(this);
|
||||||
|
|
||||||
|
boolean contactHome = mMMKV.decodeBool(CommonConfig.CONTACT_HOME_PAGE, false);
|
||||||
|
if (!contactHome) {
|
||||||
|
mCurrentIndex += 1;
|
||||||
|
}
|
||||||
if (mContactFragment == null) {
|
if (mContactFragment == null) {
|
||||||
mContactFragment = new ContactFragment();
|
mContactFragment = new ContactFragment();
|
||||||
mFragments.add(mContactFragment);
|
mFragments.add(mContactFragment);
|
||||||
mFragmentSize += 1;
|
mFragmentSize += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean contactHome = mMMKV.decodeBool(CommonConfig.CONTACT_HOME_PAGE, false);
|
|
||||||
if (!contactHome) {
|
|
||||||
mCurrentIndex += 1;
|
|
||||||
}
|
|
||||||
if (mHomeFragment == null) {
|
if (mHomeFragment == null) {
|
||||||
mHomeFragment = new HomeFragment();
|
mHomeFragment = new HomeFragment();
|
||||||
mFragments.add(mHomeFragment);
|
mFragments.add(mHomeFragment);
|
||||||
@@ -91,28 +104,64 @@ public class MainActivity extends BaseMvvmActivity<MainViewModel, ActivityMainBi
|
|||||||
mViewDataBinding.viewPager.setCurrentItem(index);
|
mViewDataBinding.viewPager.setCurrentItem(index);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mBaseFragmentPagerAdapter = new BaseFragmentPagerAdapter(mFragmentManager, mFragments);
|
|
||||||
mViewDataBinding.viewPager.setAdapter(mBaseFragmentPagerAdapter);
|
mViewDataBinding.viewPager.setAdapter(mApkPagerAdapter);
|
||||||
mViewDataBinding.viewPager.setOffscreenPageLimit(10);
|
mViewDataBinding.viewPager.setOffscreenPageLimit(10);
|
||||||
mViewDataBinding.viewPager.setCurrentItem(mCurrentIndex);
|
mViewDataBinding.viewPager.setCurrentItem(mCurrentIndex);
|
||||||
|
|
||||||
mViewDataBinding.magicIndicator.setNavigator(mScaleCircleNavigator);
|
mViewDataBinding.magicIndicator.setNavigator(mScaleCircleNavigator);
|
||||||
ViewPagerHelper.bind(mViewDataBinding.magicIndicator, mViewDataBinding.viewPager);
|
ViewPagerHelper.bind(mViewDataBinding.magicIndicator, mViewDataBinding.viewPager);
|
||||||
|
|
||||||
|
Log.e(TAG, "initView: mCurrentIndex = " + mCurrentIndex);
|
||||||
|
Log.e(TAG, "initView: mFragmentSize = " + mFragmentSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initData() {
|
protected void initData() {
|
||||||
|
mViewModel.mDesktopSortAppData.observe(this, new Observer<List<AppInfo>>() {
|
||||||
|
@Override
|
||||||
|
public void onChanged(List<AppInfo> appInfos) {
|
||||||
|
mAppInfos = appInfos;
|
||||||
|
Log.e(TAG, "onChanged: mAppInfos size = " + mAppInfos.size());
|
||||||
|
setAppList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mViewModel.getOutsideApp();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
Log.e(TAG, "onResume: ");
|
Log.e(TAG, "onResume: ");
|
||||||
setAppList();
|
mViewModel.getOutsideApp();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAppList() {
|
private void setAppList() {
|
||||||
|
Log.e(TAG, "setAppList: mFragments size = " + mFragments.size());
|
||||||
|
mFragments = mFragments.subList(0, mFragmentSize);
|
||||||
|
Log.e(TAG, "setAppList: subList mFragments size = " + mFragments.size());
|
||||||
|
int fragmentCount = (int) Math.ceil((double) mAppInfos.size() / APK_PER_FRAGMENT);
|
||||||
|
for (int i = 0; i < fragmentCount; i++) {
|
||||||
|
int start = i * APK_PER_FRAGMENT;
|
||||||
|
int end = Math.min(start + APK_PER_FRAGMENT, mAppInfos.size());
|
||||||
|
List<AppInfo> subList = new ArrayList<>(mAppInfos.subList(start, end));
|
||||||
|
Log.e(TAG, "setAppList: subList size = " + subList.size());
|
||||||
|
// AppFragment fragment = AppFragment.newInstance(subList);
|
||||||
|
AppFragment fragment = new AppFragment(subList);
|
||||||
|
fragment.setUpdateCallback(new AppFragment.UpdateCallback() {
|
||||||
|
@Override
|
||||||
|
public void onUpdate() {
|
||||||
|
mViewModel.getOutsideApp();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mFragments.add(fragment);
|
||||||
|
Log.e(TAG, "setAppList: add mFragments size = " + mFragments.size());
|
||||||
|
}
|
||||||
|
mScaleCircleNavigator.setCircleCount(mFragments.size());
|
||||||
|
mScaleCircleNavigator.notifyDataSetChanged();
|
||||||
|
|
||||||
|
mApkPagerAdapter.setFragments(mFragments);
|
||||||
|
mApkPagerAdapter.notifyDataSetChanged();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,28 @@
|
|||||||
package com.ttstd.dialer.activity.main;
|
package com.ttstd.dialer.activity.main;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
import com.trello.rxlifecycle4.RxLifecycle;
|
||||||
import com.trello.rxlifecycle4.android.ActivityEvent;
|
import com.trello.rxlifecycle4.android.ActivityEvent;
|
||||||
|
import com.trello.rxlifecycle4.android.FragmentEvent;
|
||||||
import com.ttstd.dialer.base.mvvm.BaseViewModel;
|
import com.ttstd.dialer.base.mvvm.BaseViewModel;
|
||||||
import com.ttstd.dialer.databinding.ActivityMainBinding;
|
import com.ttstd.dialer.databinding.ActivityMainBinding;
|
||||||
|
import com.ttstd.dialer.db.app.AppInfo;
|
||||||
import com.ttstd.dialer.db.app.AppRepository;
|
import com.ttstd.dialer.db.app.AppRepository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.rxjava3.annotations.NonNull;
|
||||||
|
import io.reactivex.rxjava3.core.Observable;
|
||||||
|
import io.reactivex.rxjava3.core.Observer;
|
||||||
|
import io.reactivex.rxjava3.disposables.Disposable;
|
||||||
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||||
|
|
||||||
public class MainViewModel extends BaseViewModel<ActivityMainBinding, ActivityEvent> {
|
public class MainViewModel extends BaseViewModel<ActivityMainBinding, ActivityEvent> {
|
||||||
private static final String TAG = "MainViewModel";
|
private static final String TAG = "MainViewModel";
|
||||||
|
|
||||||
@@ -18,4 +34,38 @@ public class MainViewModel extends BaseViewModel<ActivityMainBinding, ActivityEv
|
|||||||
mAppRepository = new AppRepository(context);
|
mAppRepository = new AppRepository(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MutableLiveData<List<AppInfo>> mDesktopSortAppData = new MutableLiveData<>();
|
||||||
|
|
||||||
|
public void getOutsideApp() {
|
||||||
|
Observable.fromCallable(new Callable<List<AppInfo>>() {
|
||||||
|
@Override
|
||||||
|
public List<AppInfo> call() throws Exception {
|
||||||
|
return mAppRepository.getOutsideApp();
|
||||||
|
}
|
||||||
|
}).compose(RxLifecycle.bindUntilEvent(getLifecycle(), ActivityEvent.DESTROY))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(new Observer<List<AppInfo>>() {
|
||||||
|
@Override
|
||||||
|
public void onSubscribe(@NonNull Disposable d) {
|
||||||
|
Log.e("getOutsideApp", "onSubscribe: ");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNext(@NonNull List<AppInfo> appInfos) {
|
||||||
|
Log.e("getOutsideApp", "onNext: " + appInfos);
|
||||||
|
mDesktopSortAppData.setValue(appInfos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(@NonNull Throwable e) {
|
||||||
|
Log.e("getOutsideApp", "onError: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete() {
|
||||||
|
Log.e("getOutsideApp", "onComplete: ");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
152
app/src/main/java/com/ttstd/dialer/adapter/AppAdapter.java
Normal file
152
app/src/main/java/com/ttstd/dialer/adapter/AppAdapter.java
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
package com.ttstd.dialer.adapter;
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
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.constraintlayout.widget.ConstraintLayout;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
import androidx.loader.app.LoaderManager;
|
||||||
|
import androidx.loader.content.Loader;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.shehuan.niv.NiceImageView;
|
||||||
|
import com.tencent.mmkv.MMKV;
|
||||||
|
import com.ttstd.dialer.R;
|
||||||
|
import com.ttstd.dialer.config.CommonConfig;
|
||||||
|
import com.ttstd.dialer.db.app.AppInfo;
|
||||||
|
import com.ttstd.dialer.fragment.dialog.shortcut.ShortcutDialogFagment;
|
||||||
|
import com.ttstd.dialer.utils.ApkUtils;
|
||||||
|
import com.ttstd.iconloader.IconCacheManager;
|
||||||
|
import com.ttstd.iconloader.IconLoader;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AppAdapter extends RecyclerView.Adapter<AppAdapter.AppHolder> implements LoaderManager.LoaderCallbacks<Drawable> {
|
||||||
|
private static final String TAG = "AppAdapter";
|
||||||
|
|
||||||
|
private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
|
||||||
|
|
||||||
|
private FragmentActivity mContext;
|
||||||
|
private LoaderManager mLoaderManager;
|
||||||
|
private IconCacheManager mIconCacheManager = IconCacheManager.getInstance();
|
||||||
|
|
||||||
|
public AppAdapter(LoaderManager loaderManager) {
|
||||||
|
mLoaderManager = loaderManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<AppInfo> mAppInfos;
|
||||||
|
|
||||||
|
public void setAppInfos(List<AppInfo> appInfos) {
|
||||||
|
mAppInfos = appInfos;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ShortcutCallback {
|
||||||
|
void setAppInside(AppInfo appInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ShortcutCallback mShortcutCallback;
|
||||||
|
|
||||||
|
public void setShortcutCallback(ShortcutCallback shortcutCallback) {
|
||||||
|
mShortcutCallback = shortcutCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public AppHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {
|
||||||
|
mContext = (FragmentActivity) parent.getContext();
|
||||||
|
return new AppHolder(LayoutInflater.from(mContext).inflate(R.layout.item_app, parent, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull @NotNull AppHolder holder, int position) {
|
||||||
|
AppInfo appInfo = mAppInfos.get(position);
|
||||||
|
Drawable drawable = mIconCacheManager.getIcon(appInfo.getComponentName().flattenToShortString());
|
||||||
|
if (drawable != null) {
|
||||||
|
holder.iv_icon.setImageDrawable(drawable);
|
||||||
|
} else {
|
||||||
|
mLoaderManager.restartLoader(position, null, this).forceLoad();
|
||||||
|
}
|
||||||
|
holder.tv_app_name.setText(appInfo.getLabel());
|
||||||
|
holder.root.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
ApkUtils.openApp(mContext, appInfo.getComponentName());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
holder.root.setOnLongClickListener(new View.OnLongClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onLongClick(View v) {
|
||||||
|
ShortcutDialogFagment shortcutDialogFagment = new ShortcutDialogFagment(appInfo);
|
||||||
|
shortcutDialogFagment.setTitil("温馨提示");
|
||||||
|
shortcutDialogFagment.setTips("是否将应用放入更多应用");
|
||||||
|
shortcutDialogFagment.setOnClickListener(new ShortcutDialogFagment.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onPositiveClick() {
|
||||||
|
if (mShortcutCallback != null)
|
||||||
|
mShortcutCallback.setAppInside(appInfo);
|
||||||
|
shortcutDialogFagment.dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNegativeClick() {
|
||||||
|
shortcutDialogFagment.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
shortcutDialogFagment.show(mContext.getSupportFragmentManager(), "ShortcutDialogFagment");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return mAppInfos == null ? 0 : mAppInfos.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Loader<Drawable> onCreateLoader(int id, @Nullable @org.jetbrains.annotations.Nullable Bundle args) {
|
||||||
|
AppInfo appInfo = mAppInfos.get(id);
|
||||||
|
ComponentName componentName = appInfo.getComponentName(); // 从数据项中获取 ComponentName
|
||||||
|
return new IconLoader(mContext, componentName, mIconCacheManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadFinished(@NonNull @NotNull Loader<Drawable> loader, Drawable data) {
|
||||||
|
int position = loader.getId();
|
||||||
|
notifyItemChanged(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoaderReset(@NonNull @NotNull Loader<Drawable> loader) {
|
||||||
|
Log.e(TAG, "onLoaderReset: ");
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AppHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
ConstraintLayout root;
|
||||||
|
NiceImageView iv_icon;
|
||||||
|
TextView tv_app_name;
|
||||||
|
|
||||||
|
public AppHolder(@NonNull @NotNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
root = itemView.findViewById(R.id.root);
|
||||||
|
iv_icon = itemView.findViewById(R.id.iv_icon);
|
||||||
|
tv_app_name = itemView.findViewById(R.id.tv_app_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,9 +1,5 @@
|
|||||||
package com.ttstd.dialer.adapter;
|
package com.ttstd.dialer.adapter;
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -12,13 +8,12 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
import androidx.core.app.ActivityCompat;
|
|
||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentActivity;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.shehuan.niv.NiceImageView;
|
import com.shehuan.niv.NiceImageView;
|
||||||
import com.ttstd.dialer.R;
|
import com.ttstd.dialer.R;
|
||||||
import com.ttstd.dialer.db.contact.Contact;
|
import com.ttstd.dialer.db.contact.ContactInfo;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -28,10 +23,10 @@ public class ContactInfoAdapter extends RecyclerView.Adapter<ContactInfoAdapter.
|
|||||||
|
|
||||||
private FragmentActivity mContext;
|
private FragmentActivity mContext;
|
||||||
|
|
||||||
private List<Contact> mContacts;
|
private List<ContactInfo> mContactInfos;
|
||||||
|
|
||||||
public void setContacts(List<Contact> contacts) {
|
public void setContactInfos(List<ContactInfo> contactInfos) {
|
||||||
mContacts = contacts;
|
mContactInfos = contactInfos;
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +43,7 @@ public class ContactInfoAdapter extends RecyclerView.Adapter<ContactInfoAdapter.
|
|||||||
}
|
}
|
||||||
|
|
||||||
public interface OnClickListener {
|
public interface OnClickListener {
|
||||||
void onClick(Contact contact);
|
void onClick(ContactInfo contactInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OnClickListener mOnClickListener;
|
private OnClickListener mOnClickListener;
|
||||||
@@ -66,17 +61,17 @@ public class ContactInfoAdapter extends RecyclerView.Adapter<ContactInfoAdapter.
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull ContactInfoHolder holder, int position) {
|
public void onBindViewHolder(@NonNull ContactInfoHolder holder, int position) {
|
||||||
Contact contact = mContacts.get(position);
|
ContactInfo contactInfo = mContactInfos.get(position);
|
||||||
String name = contact.getName();
|
String name = contactInfo.getName();
|
||||||
holder.tv_name.setText(name);
|
holder.tv_name.setText(name);
|
||||||
String phone = contact.getPhoneNumber();
|
String phone = contactInfo.getPhoneNumber();
|
||||||
holder.tv_phone.setText(phone);
|
holder.tv_phone.setText(phone);
|
||||||
holder.root.setOnClickListener(new View.OnClickListener() {
|
holder.root.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
Log.e(TAG, "onClick: " + contact);
|
Log.e(TAG, "onClick: " + contactInfo);
|
||||||
if (mOnClickListener != null) {
|
if (mOnClickListener != null) {
|
||||||
mOnClickListener.onClick(contact);
|
mOnClickListener.onClick(contactInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -84,7 +79,7 @@ public class ContactInfoAdapter extends RecyclerView.Adapter<ContactInfoAdapter.
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return mContacts == null ? 0 : mContacts.size();
|
return mContactInfos == null ? 0 : mContactInfos.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -98,11 +93,11 @@ public class ContactInfoAdapter extends RecyclerView.Adapter<ContactInfoAdapter.
|
|||||||
|
|
||||||
if (fromPosition < toPosition) {
|
if (fromPosition < toPosition) {
|
||||||
for (int i = fromPosition; i < toPosition; i++) {
|
for (int i = fromPosition; i < toPosition; i++) {
|
||||||
Collections.swap(mContacts, i, i + 1);
|
Collections.swap(mContactInfos, i, i + 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = fromPosition; i > toPosition; i--) {
|
for (int i = fromPosition; i > toPosition; i--) {
|
||||||
Collections.swap(mContacts, i, i - 1);
|
Collections.swap(mContactInfos, i, i - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notifyItemMoved(fromPosition, toPosition);
|
notifyItemMoved(fromPosition, toPosition);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||||||
|
|
||||||
import com.shehuan.niv.NiceImageView;
|
import com.shehuan.niv.NiceImageView;
|
||||||
import com.ttstd.dialer.R;
|
import com.ttstd.dialer.R;
|
||||||
import com.ttstd.dialer.db.contact.Contact;
|
import com.ttstd.dialer.db.contact.ContactInfo;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -23,10 +23,10 @@ public class HomeContactAdapter extends RecyclerView.Adapter<HomeContactAdapter.
|
|||||||
|
|
||||||
private FragmentActivity mContext;
|
private FragmentActivity mContext;
|
||||||
|
|
||||||
private List<Contact> mContacts;
|
private List<ContactInfo> mContactInfos;
|
||||||
|
|
||||||
public void setContacts(List<Contact> contacts) {
|
public void setContactInfos(List<ContactInfo> contactInfos) {
|
||||||
mContacts = contacts;
|
mContactInfos = contactInfos;
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ public class HomeContactAdapter extends RecyclerView.Adapter<HomeContactAdapter.
|
|||||||
}
|
}
|
||||||
|
|
||||||
public interface OnClickListener {
|
public interface OnClickListener {
|
||||||
void onClick(Contact contact);
|
void onClick(ContactInfo contactInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OnClickListener mOnClickListener;
|
private OnClickListener mOnClickListener;
|
||||||
@@ -61,17 +61,17 @@ public class HomeContactAdapter extends RecyclerView.Adapter<HomeContactAdapter.
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull ContactInfoHolder holder, int position) {
|
public void onBindViewHolder(@NonNull ContactInfoHolder holder, int position) {
|
||||||
Contact contact = mContacts.get(position);
|
ContactInfo contactInfo = mContactInfos.get(position);
|
||||||
String name = contact.getName();
|
String name = contactInfo.getName();
|
||||||
holder.tv_name.setText(name);
|
holder.tv_name.setText(name);
|
||||||
String phone = contact.getPhoneNumber();
|
String phone = contactInfo.getPhoneNumber();
|
||||||
holder.tv_phone.setText(phone);
|
holder.tv_phone.setText(phone);
|
||||||
holder.root.setOnClickListener(new View.OnClickListener() {
|
holder.root.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
Log.e(TAG, "onClick: " + contact);
|
Log.e(TAG, "onClick: " + contactInfo);
|
||||||
if (mOnClickListener != null) {
|
if (mOnClickListener != null) {
|
||||||
mOnClickListener.onClick(contact);
|
mOnClickListener.onClick(contactInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -79,7 +79,7 @@ public class HomeContactAdapter extends RecyclerView.Adapter<HomeContactAdapter.
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return mContacts == null ? 0 : mContacts.size();
|
return mContactInfos == null ? 0 : mContactInfos.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -93,11 +93,11 @@ public class HomeContactAdapter extends RecyclerView.Adapter<HomeContactAdapter.
|
|||||||
|
|
||||||
if (fromPosition < toPosition) {
|
if (fromPosition < toPosition) {
|
||||||
for (int i = fromPosition; i < toPosition; i++) {
|
for (int i = fromPosition; i < toPosition; i++) {
|
||||||
Collections.swap(mContacts, i, i + 1);
|
Collections.swap(mContactInfos, i, i + 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = fromPosition; i > toPosition; i--) {
|
for (int i = fromPosition; i > toPosition; i--) {
|
||||||
Collections.swap(mContacts, i, i - 1);
|
Collections.swap(mContactInfos, i, i - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notifyItemMoved(fromPosition, toPosition);
|
notifyItemMoved(fromPosition, toPosition);
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import android.util.Log;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@@ -18,10 +17,12 @@ import androidx.loader.app.LoaderManager;
|
|||||||
import androidx.loader.content.Loader;
|
import androidx.loader.content.Loader;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.shehuan.niv.NiceImageView;
|
||||||
import com.tencent.mmkv.MMKV;
|
import com.tencent.mmkv.MMKV;
|
||||||
import com.ttstd.dialer.R;
|
import com.ttstd.dialer.R;
|
||||||
import com.ttstd.dialer.db.app.DesktopSortApp;
|
|
||||||
import com.ttstd.dialer.config.CommonConfig;
|
import com.ttstd.dialer.config.CommonConfig;
|
||||||
|
import com.ttstd.dialer.db.app.AppInfo;
|
||||||
|
import com.ttstd.dialer.fragment.dialog.shortcut.ShortcutDialogFagment;
|
||||||
import com.ttstd.dialer.utils.ApkUtils;
|
import com.ttstd.dialer.utils.ApkUtils;
|
||||||
import com.ttstd.iconloader.IconCacheManager;
|
import com.ttstd.iconloader.IconCacheManager;
|
||||||
import com.ttstd.iconloader.IconLoader;
|
import com.ttstd.iconloader.IconLoader;
|
||||||
@@ -43,53 +44,87 @@ public class MoreAppAdapter extends RecyclerView.Adapter<MoreAppAdapter.AppHolde
|
|||||||
mLoaderManager = loaderManager;
|
mLoaderManager = loaderManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectApps(List<DesktopSortApp> selectApps) {
|
public void setSelectApps(List<AppInfo> selectApps) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<DesktopSortApp> mDesktopSortApps;
|
private List<AppInfo> mAppInfos;
|
||||||
|
|
||||||
public void setDesktopSortApps(List<DesktopSortApp> desktopSortApps) {
|
public void setAppInfos(List<AppInfo> appInfos) {
|
||||||
mDesktopSortApps = desktopSortApps;
|
mAppInfos = appInfos;
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ShortcutCallback {
|
||||||
|
void setAppOutside(AppInfo appInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ShortcutCallback mShortcutCallback;
|
||||||
|
|
||||||
|
public void setShortcutCallback(ShortcutCallback shortcutCallback) {
|
||||||
|
mShortcutCallback = shortcutCallback;
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public AppHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {
|
public AppHolder onCreateViewHolder(@NonNull @NotNull ViewGroup parent, int viewType) {
|
||||||
mContext = (FragmentActivity) parent.getContext();
|
mContext = (FragmentActivity) parent.getContext();
|
||||||
return new AppHolder(LayoutInflater.from(mContext).inflate(R.layout.item_app, parent, false));
|
return new AppHolder(LayoutInflater.from(mContext).inflate(R.layout.item_more_app, parent, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull @NotNull AppHolder holder, int position) {
|
public void onBindViewHolder(@NonNull @NotNull AppHolder holder, int position) {
|
||||||
DesktopSortApp desktopSortApp = mDesktopSortApps.get(position);
|
AppInfo appInfo = mAppInfos.get(position);
|
||||||
Drawable drawable = mIconCacheManager.getIcon(desktopSortApp.getComponentName().flattenToShortString());
|
Drawable drawable = mIconCacheManager.getIcon(appInfo.getComponentName().flattenToShortString());
|
||||||
if (drawable != null) {
|
if (drawable != null) {
|
||||||
holder.iv_icon.setImageDrawable(drawable);
|
holder.iv_icon.setImageDrawable(drawable);
|
||||||
} else {
|
} else {
|
||||||
mLoaderManager.restartLoader(position, null, this).forceLoad();
|
mLoaderManager.restartLoader(position, null, this).forceLoad();
|
||||||
}
|
}
|
||||||
holder.tv_app_name.setText(desktopSortApp.getLabel());
|
holder.tv_app_name.setText(appInfo.getLabel());
|
||||||
holder.root.setOnClickListener(new View.OnClickListener() {
|
holder.root.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
ApkUtils.openApp(mContext, desktopSortApp.getComponentName());
|
ApkUtils.openApp(mContext, appInfo.getComponentName());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
holder.root.setOnLongClickListener(new View.OnLongClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onLongClick(View v) {
|
||||||
|
ShortcutDialogFagment shortcutDialogFagment = new ShortcutDialogFagment(appInfo);
|
||||||
|
shortcutDialogFagment.setTitil("温馨提示");
|
||||||
|
shortcutDialogFagment.setTips("是否将应用放在桌面显示");
|
||||||
|
|
||||||
|
shortcutDialogFagment.setOnClickListener(new ShortcutDialogFagment.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onPositiveClick() {
|
||||||
|
if (mShortcutCallback != null)
|
||||||
|
mShortcutCallback.setAppOutside(appInfo);
|
||||||
|
shortcutDialogFagment.dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNegativeClick() {
|
||||||
|
shortcutDialogFagment.dismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
shortcutDialogFagment.show(mContext.getSupportFragmentManager(), "ShortcutDialogFagment");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return mDesktopSortApps == null ? 0 : mDesktopSortApps.size();
|
return mAppInfos == null ? 0 : mAppInfos.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Loader<Drawable> onCreateLoader(int id, @Nullable @org.jetbrains.annotations.Nullable Bundle args) {
|
public Loader<Drawable> onCreateLoader(int id, @Nullable @org.jetbrains.annotations.Nullable Bundle args) {
|
||||||
DesktopSortApp appInfo = mDesktopSortApps.get(id);
|
AppInfo appInfo = mAppInfos.get(id);
|
||||||
ComponentName componentName = appInfo.getComponentName(); // 从数据项中获取 ComponentName
|
ComponentName componentName = appInfo.getComponentName(); // 从数据项中获取 ComponentName
|
||||||
return new IconLoader(mContext, componentName, mIconCacheManager);
|
return new IconLoader(mContext, componentName, mIconCacheManager);
|
||||||
}
|
}
|
||||||
@@ -108,7 +143,7 @@ public class MoreAppAdapter extends RecyclerView.Adapter<MoreAppAdapter.AppHolde
|
|||||||
public class AppHolder extends RecyclerView.ViewHolder {
|
public class AppHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
ConstraintLayout root;
|
ConstraintLayout root;
|
||||||
ImageView iv_icon;
|
NiceImageView iv_icon;
|
||||||
TextView tv_app_name;
|
TextView tv_app_name;
|
||||||
|
|
||||||
public AppHolder(@NonNull @NotNull View itemView) {
|
public AppHolder(@NonNull @NotNull View itemView) {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public interface AppDao {
|
|||||||
Integer getCountById();
|
Integer getCountById();
|
||||||
|
|
||||||
@Query("SELECT * FROM app_list WHERE package_name = :packageName AND class_name = :className")
|
@Query("SELECT * FROM app_list WHERE package_name = :packageName AND class_name = :className")
|
||||||
DesktopSortApp getAppInfo(String packageName, String className);
|
AppInfo getAppInfo(String packageName, String className);
|
||||||
|
|
||||||
@Query("SELECT id FROM app_list WHERE package_name = :packageName AND class_name = :className")
|
@Query("SELECT id FROM app_list WHERE package_name = :packageName AND class_name = :className")
|
||||||
Integer getIdByPackageAndClass(String packageName, String className);
|
Integer getIdByPackageAndClass(String packageName, String className);
|
||||||
@@ -29,16 +29,16 @@ public interface AppDao {
|
|||||||
Integer checkAppInfoExists(String pkgName, String clsName);
|
Integer checkAppInfoExists(String pkgName, String clsName);
|
||||||
|
|
||||||
@Insert
|
@Insert
|
||||||
long insert(DesktopSortApp desktopSortApp);
|
long insert(AppInfo appInfo);
|
||||||
|
|
||||||
@Insert
|
@Insert
|
||||||
long[] insert(List<DesktopSortApp> desktopSortApps);
|
long[] insert(List<AppInfo> appInfos);
|
||||||
|
|
||||||
@Update
|
@Update
|
||||||
Integer update(DesktopSortApp desktopSortApp);
|
Integer update(AppInfo appInfo);
|
||||||
|
|
||||||
@Delete
|
@Delete
|
||||||
Integer delete(DesktopSortApp desktopSortApp);
|
Integer delete(AppInfo appInfo);
|
||||||
|
|
||||||
@Query("DELETE FROM app_list WHERE id = :id")
|
@Query("DELETE FROM app_list WHERE id = :id")
|
||||||
Integer deleteById(Integer id);
|
Integer deleteById(Integer id);
|
||||||
@@ -47,11 +47,17 @@ public interface AppDao {
|
|||||||
Integer deleteAll();
|
Integer deleteAll();
|
||||||
|
|
||||||
@Query("SELECT * FROM app_list ORDER BY position ASC")
|
@Query("SELECT * FROM app_list ORDER BY position ASC")
|
||||||
List<DesktopSortApp> getAllApp();
|
List<AppInfo> getAllApp();
|
||||||
|
|
||||||
|
@Query("SELECT * FROM app_list WHERE outside = 1 ORDER BY position ASC")
|
||||||
|
List<AppInfo> getOutsideApp();
|
||||||
|
|
||||||
|
@Query("SELECT * FROM app_list WHERE outside = 0 ORDER BY position ASC")
|
||||||
|
List<AppInfo> getInsideApp();
|
||||||
|
|
||||||
@Query("SELECT * FROM app_list WHERE id = :id")
|
@Query("SELECT * FROM app_list WHERE id = :id")
|
||||||
DesktopSortApp getAppById(Integer id);
|
AppInfo getAppById(Integer id);
|
||||||
|
|
||||||
@Query("SELECT * FROM app_list WHERE label LIKE :searchQuery OR package_name LIKE :searchQuery")
|
@Query("SELECT * FROM app_list WHERE label LIKE :searchQuery OR package_name LIKE :searchQuery")
|
||||||
List<DesktopSortApp> searchApp(String searchQuery);
|
List<AppInfo> searchApp(String searchQuery);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import androidx.room.RoomDatabase;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@Database(entities = {DesktopSortApp.class}, version = 2, exportSchema = false)
|
@Database(entities = {AppInfo.class}, version = 1, exportSchema = false)
|
||||||
public abstract class AppDatabase extends RoomDatabase {
|
public abstract class AppDatabase extends RoomDatabase {
|
||||||
public abstract AppDao appDao();
|
public abstract AppDao appDao();
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ package com.ttstd.dialer.db.app;
|
|||||||
|
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.room.ColumnInfo;
|
import androidx.room.ColumnInfo;
|
||||||
import androidx.room.Entity;
|
import androidx.room.Entity;
|
||||||
@@ -10,6 +13,8 @@ import androidx.room.Index;
|
|||||||
import androidx.room.PrimaryKey;
|
import androidx.room.PrimaryKey;
|
||||||
import androidx.room.TypeConverters;
|
import androidx.room.TypeConverters;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
import com.ttstd.dialer.utils.ApkUtils;
|
import com.ttstd.dialer.utils.ApkUtils;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -17,7 +22,7 @@ import java.util.Objects;
|
|||||||
|
|
||||||
@Entity(tableName = "app_list", indices = {@Index(value = "component_name", unique = true)})
|
@Entity(tableName = "app_list", indices = {@Index(value = "component_name", unique = true)})
|
||||||
@TypeConverters({ComponentNameConverter.class})
|
@TypeConverters({ComponentNameConverter.class})
|
||||||
public class DesktopSortApp implements Serializable {
|
public class AppInfo implements Serializable , Parcelable {
|
||||||
private static final long serialVersionUID = 9113517079637096245L;
|
private static final long serialVersionUID = 9113517079637096245L;
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
@@ -32,26 +37,53 @@ public class DesktopSortApp implements Serializable {
|
|||||||
private String mClassName;
|
private String mClassName;
|
||||||
@ColumnInfo(name = "position")
|
@ColumnInfo(name = "position")
|
||||||
private int mPosition;
|
private int mPosition;
|
||||||
|
@ColumnInfo(name = "outside")
|
||||||
|
private int outside;
|
||||||
|
|
||||||
|
public AppInfo() {
|
||||||
|
|
||||||
public DesktopSortApp() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DesktopSortApp(Context context, ComponentName componentName) {
|
public AppInfo(Context context, ComponentName componentName) {
|
||||||
this.componentName = componentName;
|
this.componentName = componentName;
|
||||||
mPackageName = componentName.getPackageName();
|
this.mLabel = ApkUtils.getAppName(context, componentName);
|
||||||
mClassName = componentName.getClassName();
|
this.mPackageName = componentName.getPackageName();
|
||||||
mPosition = 0;
|
this.mClassName = componentName.getClassName();
|
||||||
mLabel = ApkUtils.getAppName(context, componentName);
|
this.mPosition = 0;
|
||||||
|
this.outside = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DesktopSortApp(Context context, ComponentName componentName, int pos) {
|
public AppInfo(Context context, ComponentName componentName, int pos) {
|
||||||
this.componentName = componentName;
|
this.componentName = componentName;
|
||||||
mPackageName = componentName.getPackageName();
|
this.mLabel = ApkUtils.getAppName(context, componentName);
|
||||||
mClassName = componentName.getClassName();
|
this.mPackageName = componentName.getPackageName();
|
||||||
mPosition = pos;
|
this.mClassName = componentName.getClassName();
|
||||||
mLabel = ApkUtils.getAppName(context, componentName);
|
this.mPosition = pos;
|
||||||
|
this.outside = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected AppInfo(Parcel in) {
|
||||||
|
id = in.readInt();
|
||||||
|
componentName = in.readParcelable(ComponentName.class.getClassLoader());
|
||||||
|
mLabel = in.readString();
|
||||||
|
mPackageName = in.readString();
|
||||||
|
mClassName = in.readString();
|
||||||
|
mPosition = in.readInt();
|
||||||
|
outside = in.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<AppInfo> CREATOR = new Creator<AppInfo>() {
|
||||||
|
@Override
|
||||||
|
public AppInfo createFromParcel(Parcel in) {
|
||||||
|
return new AppInfo(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AppInfo[] newArray(int size) {
|
||||||
|
return new AppInfo[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@@ -100,10 +132,18 @@ public class DesktopSortApp implements Serializable {
|
|||||||
this.mPosition = position;
|
this.mPosition = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getOutside() {
|
||||||
|
return outside;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOutside(int outside) {
|
||||||
|
this.outside = outside;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(@Nullable @org.jetbrains.annotations.Nullable Object obj) {
|
public boolean equals(@Nullable @org.jetbrains.annotations.Nullable Object obj) {
|
||||||
if (obj instanceof DesktopSortApp) {
|
if (obj instanceof AppInfo) {
|
||||||
return Objects.equals(componentName, ((DesktopSortApp) obj).componentName);
|
return Objects.equals(componentName, ((AppInfo) obj).componentName);
|
||||||
} else if (obj instanceof ComponentName) {
|
} else if (obj instanceof ComponentName) {
|
||||||
return Objects.equals(componentName, obj);
|
return Objects.equals(componentName, obj);
|
||||||
} else {
|
} else {
|
||||||
@@ -115,4 +155,27 @@ public class DesktopSortApp implements Serializable {
|
|||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return componentName.hashCode();
|
return componentName.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return JsonParser.parseString(new Gson().toJson(this)).getAsJsonObject().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeInt(id);
|
||||||
|
dest.writeParcelable(componentName, flags);
|
||||||
|
dest.writeString(mLabel);
|
||||||
|
dest.writeString(mPackageName);
|
||||||
|
dest.writeString(mClassName);
|
||||||
|
dest.writeInt(mPosition);
|
||||||
|
dest.writeInt(outside);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@ public class AppRepository {
|
|||||||
return mAppDao.getCountById();
|
return mAppDao.getCountById();
|
||||||
}
|
}
|
||||||
|
|
||||||
public DesktopSortApp getAppInfo(String packageName, String className) {
|
public AppInfo getAppInfo(String packageName, String className) {
|
||||||
return mAppDao.getAppInfo(packageName, className);
|
return mAppDao.getAppInfo(packageName, className);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,37 +33,47 @@ public class AppRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取所有APP
|
// 获取所有APP
|
||||||
public List<DesktopSortApp> getAllApp() {
|
public List<AppInfo> getAllApp() {
|
||||||
return mAppDao.getAllApp();
|
return mAppDao.getAllApp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取在外面显示的APP
|
||||||
|
public List<AppInfo> getOutsideApp() {
|
||||||
|
return mAppDao.getOutsideApp();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取在里面显示的APP
|
||||||
|
public List<AppInfo> getInsideApp() {
|
||||||
|
return mAppDao.getInsideApp();
|
||||||
|
}
|
||||||
|
|
||||||
// 根据ID获取APP
|
// 根据ID获取APP
|
||||||
public DesktopSortApp getAppById(int id) {
|
public AppInfo getAppById(int id) {
|
||||||
return mAppDao.getAppById(id);
|
return mAppDao.getAppById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 搜索APP
|
// 搜索APP
|
||||||
public List<DesktopSortApp> searchApp(String query) {
|
public List<AppInfo> searchApp(String query) {
|
||||||
return mAppDao.searchApp("%" + query + "%");
|
return mAppDao.searchApp("%" + query + "%");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加APP
|
// 添加APP
|
||||||
public long insert(DesktopSortApp desktopSortApp) {
|
public long insert(AppInfo appInfo) {
|
||||||
return mAppDao.insert(desktopSortApp);
|
return mAppDao.insert(appInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long[] insert(List<DesktopSortApp> desktopSortApps) {
|
public long[] insert(List<AppInfo> appInfos) {
|
||||||
return mAppDao.insert(desktopSortApps);
|
return mAppDao.insert(appInfos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新APP
|
// 更新APP
|
||||||
public int update(DesktopSortApp desktopSortApp) {
|
public int update(AppInfo appInfo) {
|
||||||
return mAppDao.update(desktopSortApp);
|
return mAppDao.update(appInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除APP
|
// 删除APP
|
||||||
public int delete(DesktopSortApp desktopSortApp) {
|
public int delete(AppInfo appInfo) {
|
||||||
return mAppDao.delete(desktopSortApp);
|
return mAppDao.delete(appInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据ID删除APP
|
// 根据ID删除APP
|
||||||
|
|||||||
@@ -19,13 +19,13 @@ public interface ContactDao {
|
|||||||
int getCountById();
|
int getCountById();
|
||||||
|
|
||||||
@Insert
|
@Insert
|
||||||
long insert(Contact contact);
|
long insert(ContactInfo contactInfo);
|
||||||
|
|
||||||
@Update
|
@Update
|
||||||
int update(Contact contact);
|
int update(ContactInfo contactInfo);
|
||||||
|
|
||||||
@Delete
|
@Delete
|
||||||
int delete(Contact contact);
|
int delete(ContactInfo contactInfo);
|
||||||
|
|
||||||
@Query("DELETE FROM contacts WHERE id = :id")
|
@Query("DELETE FROM contacts WHERE id = :id")
|
||||||
int deleteById(int id);
|
int deleteById(int id);
|
||||||
@@ -34,12 +34,12 @@ public interface ContactDao {
|
|||||||
int deleteAll();
|
int deleteAll();
|
||||||
|
|
||||||
@Query("SELECT * FROM contacts ORDER BY position ASC")
|
@Query("SELECT * FROM contacts ORDER BY position ASC")
|
||||||
List<Contact> getAllContacts();
|
List<ContactInfo> getAllContacts();
|
||||||
|
|
||||||
@Query("SELECT * FROM contacts WHERE id = :id")
|
@Query("SELECT * FROM contacts WHERE id = :id")
|
||||||
Contact getContactById(int id);
|
ContactInfo getContactById(int id);
|
||||||
|
|
||||||
@Query("SELECT * FROM contacts WHERE name LIKE :searchQuery OR phoneNumber LIKE :searchQuery")
|
@Query("SELECT * FROM contacts WHERE name LIKE :searchQuery OR phoneNumber LIKE :searchQuery")
|
||||||
List<Contact> searchContacts(String searchQuery);
|
List<ContactInfo> searchContacts(String searchQuery);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import androidx.room.RoomDatabase;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@Database(entities = {Contact.class}, version = 1, exportSchema = false)
|
@Database(entities = {ContactInfo.class}, version = 1, exportSchema = false)
|
||||||
public abstract class ContactDatabase extends RoomDatabase {
|
public abstract class ContactDatabase extends RoomDatabase {
|
||||||
public abstract ContactDao contactDao();
|
public abstract ContactDao contactDao();
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import java.io.Serializable;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@Entity(tableName = "contacts")
|
@Entity(tableName = "contacts")
|
||||||
public class Contact implements Serializable {
|
public class ContactInfo implements Serializable {
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
private int id;
|
private int id;
|
||||||
@@ -22,7 +22,7 @@ public class Contact implements Serializable {
|
|||||||
private String wxid;
|
private String wxid;
|
||||||
private int position;
|
private int position;
|
||||||
|
|
||||||
public Contact(String name, String phoneNumber, int position) {
|
public ContactInfo(String name, String phoneNumber, int position) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.phoneNumber = phoneNumber;
|
this.phoneNumber = phoneNumber;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
@@ -78,9 +78,9 @@ public class Contact implements Serializable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(@Nullable Object obj) {
|
public boolean equals(@Nullable Object obj) {
|
||||||
if (obj instanceof Contact) {
|
if (obj instanceof ContactInfo) {
|
||||||
return Objects.equals(((Contact) obj).phoneNumber, phoneNumber)
|
return Objects.equals(((ContactInfo) obj).phoneNumber, phoneNumber)
|
||||||
|| ((Contact) obj).id == id;
|
|| ((ContactInfo) obj).id == id;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -22,33 +22,33 @@ public class ContactRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取所有联系人
|
// 获取所有联系人
|
||||||
public List<Contact> getAllContacts() {
|
public List<ContactInfo> getAllContacts() {
|
||||||
return mContactDao.getAllContacts();
|
return mContactDao.getAllContacts();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据ID获取联系人
|
// 根据ID获取联系人
|
||||||
public Contact getContactById(int id) {
|
public ContactInfo getContactById(int id) {
|
||||||
return mContactDao.getContactById(id);
|
return mContactDao.getContactById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 搜索联系人
|
// 搜索联系人
|
||||||
public List<Contact> searchContacts(String query) {
|
public List<ContactInfo> searchContacts(String query) {
|
||||||
return mContactDao.searchContacts("%" + query + "%");
|
return mContactDao.searchContacts("%" + query + "%");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加联系人
|
// 添加联系人
|
||||||
public long insert(Contact contact) {
|
public long insert(ContactInfo contactInfo) {
|
||||||
return mContactDao.insert(contact);
|
return mContactDao.insert(contactInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新联系人
|
// 更新联系人
|
||||||
public int update(Contact contact) {
|
public int update(ContactInfo contactInfo) {
|
||||||
return mContactDao.update(contact);
|
return mContactDao.update(contactInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除联系人
|
// 删除联系人
|
||||||
public int delete(Contact contact) {
|
public int delete(ContactInfo contactInfo) {
|
||||||
return mContactDao.delete(contact);
|
return mContactDao.delete(contactInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据ID删除联系人
|
// 根据ID删除联系人
|
||||||
|
|||||||
@@ -14,28 +14,28 @@ public class ContactViewModel extends AndroidViewModel {
|
|||||||
mRepository = new ContactRepository(application);
|
mRepository = new ContactRepository(application);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Contact> getAllContacts() {
|
public List<ContactInfo> getAllContacts() {
|
||||||
return mRepository.getAllContacts();
|
return mRepository.getAllContacts();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Contact getContactById(int id) {
|
public ContactInfo getContactById(int id) {
|
||||||
return mRepository.getContactById(id);
|
return mRepository.getContactById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Contact> searchContacts(String query) {
|
public List<ContactInfo> searchContacts(String query) {
|
||||||
return mRepository.searchContacts(query);
|
return mRepository.searchContacts(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void insert(Contact contact) {
|
public void insert(ContactInfo contactInfo) {
|
||||||
mRepository.insert(contact);
|
mRepository.insert(contactInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(Contact contact) {
|
public void update(ContactInfo contactInfo) {
|
||||||
mRepository.update(contact);
|
mRepository.update(contactInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete(Contact contact) {
|
public void delete(ContactInfo contactInfo) {
|
||||||
mRepository.delete(contact);
|
mRepository.delete(contactInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteById(int id) {
|
public void deleteById(int id) {
|
||||||
|
|||||||
@@ -2,14 +2,56 @@ package com.ttstd.dialer.fragment.app;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.lifecycle.Observer;
|
||||||
|
import androidx.loader.app.LoaderManager;
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
|
||||||
import com.ttstd.dialer.R;
|
import com.ttstd.dialer.R;
|
||||||
|
import com.ttstd.dialer.adapter.AppAdapter;
|
||||||
import com.ttstd.dialer.base.mvvm.fragment.BaseMvvmFragment;
|
import com.ttstd.dialer.base.mvvm.fragment.BaseMvvmFragment;
|
||||||
import com.ttstd.dialer.databinding.FragmentAppBinding;
|
import com.ttstd.dialer.databinding.FragmentAppBinding;
|
||||||
|
import com.ttstd.dialer.db.app.AppInfo;
|
||||||
|
import com.ttstd.dialer.view.EqualHeightDecoration;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class AppFragment extends BaseMvvmFragment<AppViewModel, FragmentAppBinding> {
|
public class AppFragment extends BaseMvvmFragment<AppViewModel, FragmentAppBinding> {
|
||||||
|
private static final String TAG = "AppFragment";
|
||||||
|
|
||||||
|
private static final String ARG_APP_LIST = "app_list";
|
||||||
|
|
||||||
private Activity mContext;
|
private Activity mContext;
|
||||||
|
|
||||||
|
private AppAdapter mAppAdapter;
|
||||||
|
private List<AppInfo> mAppInfos;
|
||||||
|
|
||||||
|
// public static AppFragment newInstance(List<AppInfo> apkList) {
|
||||||
|
// AppFragment appFragment = new AppFragment();
|
||||||
|
// Log.e(TAG, "newInstance: " + appFragment);
|
||||||
|
// Bundle args = new Bundle();
|
||||||
|
// args.putSerializable(ARG_APP_LIST, (Serializable) apkList);
|
||||||
|
// appFragment.setArguments(args);
|
||||||
|
// return appFragment;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
public AppFragment(List<AppInfo> appInfos) {
|
||||||
|
mAppInfos = appInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface UpdateCallback {
|
||||||
|
void onUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private UpdateCallback mUpdateCallback;
|
||||||
|
|
||||||
|
public void setUpdateCallback(UpdateCallback updateCallback) {
|
||||||
|
mUpdateCallback = updateCallback;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getLayoutId() {
|
protected int getLayoutId() {
|
||||||
return R.layout.fragment_app;
|
return R.layout.fragment_app;
|
||||||
@@ -26,20 +68,68 @@ public class AppFragment extends BaseMvvmFragment<AppViewModel, FragmentAppBindi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initView(Bundle bundle) {
|
protected void initView(Bundle bundle) {
|
||||||
|
Log.e(TAG, "initView: ");
|
||||||
|
|
||||||
|
mAppAdapter = new AppAdapter(LoaderManager.getInstance(this));
|
||||||
|
mAppAdapter.setShortcutCallback(new AppAdapter.ShortcutCallback() {
|
||||||
|
@Override
|
||||||
|
public void setAppInside(AppInfo appInfo) {
|
||||||
|
appInfo.setOutside(0);
|
||||||
|
mViewModel.updateAppInfo(appInfo);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mViewDataBinding.recyclerView.setLayoutManager(new GridLayoutManager(mContext, 3));
|
||||||
|
mViewDataBinding.recyclerView.addItemDecoration(new EqualHeightDecoration(3));
|
||||||
|
mViewDataBinding.recyclerView.setAdapter(mAppAdapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initData(Bundle savedInstanceState) {
|
protected void initData(Bundle savedInstanceState) {
|
||||||
|
Log.e(TAG, "initData: ");
|
||||||
|
Log.e(TAG, "initData: " + mViewModel.mAppUpdateData);
|
||||||
|
mViewModel.mAppUpdateData.observe(this, new Observer<Integer>() {
|
||||||
|
@Override
|
||||||
|
public void onChanged(Integer integer) {
|
||||||
|
if (integer > 0) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if (mUpdateCallback != null) {
|
||||||
|
mUpdateCallback.onUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// if (getArguments() != null) {
|
||||||
|
// mAppInfos = (List<AppInfo>) getArguments().getSerializable(ARG_APP_LIST);
|
||||||
|
// }
|
||||||
|
if (mAppInfos != null) {
|
||||||
|
Log.e(TAG, "initData: mAppInfos size = " + mAppInfos.size());
|
||||||
|
mAppAdapter.setAppInfos(mAppInfos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fetchData() {
|
public void fetchData() {
|
||||||
|
Log.e(TAG, "fetchData: ");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BtnClick{
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
Log.e(TAG, "onResume: ");
|
||||||
|
if (mAppInfos != null) {
|
||||||
|
mAppAdapter.setAppInfos(mAppInfos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
Log.e(TAG, "onDestroyView: ");
|
||||||
|
mViewModel.resetLiveData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BtnClick {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,74 @@
|
|||||||
package com.ttstd.dialer.fragment.app;
|
package com.ttstd.dialer.fragment.app;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
import com.trello.rxlifecycle4.RxLifecycle;
|
||||||
|
import com.trello.rxlifecycle4.android.ActivityEvent;
|
||||||
import com.trello.rxlifecycle4.android.FragmentEvent;
|
import com.trello.rxlifecycle4.android.FragmentEvent;
|
||||||
import com.ttstd.dialer.base.mvvm.BaseViewModel;
|
import com.ttstd.dialer.base.mvvm.BaseViewModel;
|
||||||
import com.ttstd.dialer.databinding.FragmentAppBinding;
|
import com.ttstd.dialer.databinding.FragmentAppBinding;
|
||||||
|
import com.ttstd.dialer.db.app.AppInfo;
|
||||||
|
import com.ttstd.dialer.db.app.AppRepository;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.rxjava3.annotations.NonNull;
|
||||||
|
import io.reactivex.rxjava3.core.Observable;
|
||||||
|
import io.reactivex.rxjava3.core.Observer;
|
||||||
|
import io.reactivex.rxjava3.disposables.Disposable;
|
||||||
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||||
|
|
||||||
public class AppViewModel extends BaseViewModel<FragmentAppBinding, FragmentEvent> {
|
public class AppViewModel extends BaseViewModel<FragmentAppBinding, FragmentEvent> {
|
||||||
|
private static final String TAG = "AppViewModel";
|
||||||
|
|
||||||
|
private AppRepository mAppRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setContext(Context context) {
|
||||||
|
super.setContext(context);
|
||||||
|
mAppRepository = new AppRepository(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableLiveData<Integer> mAppUpdateData = new MutableLiveData<>();
|
||||||
|
|
||||||
|
public void resetLiveData() {
|
||||||
|
mAppUpdateData = new MutableLiveData<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateAppInfo(AppInfo appInfo) {
|
||||||
|
Observable.fromCallable(new Callable<Integer>() {
|
||||||
|
@Override
|
||||||
|
public Integer call() throws Exception {
|
||||||
|
return mAppRepository.update(appInfo);
|
||||||
|
}
|
||||||
|
}).compose(RxLifecycle.bindUntilEvent(getLifecycle(), FragmentEvent.DESTROY))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(new Observer<Integer>() {
|
||||||
|
@Override
|
||||||
|
public void onSubscribe(@NonNull Disposable d) {
|
||||||
|
Log.e("updateAppInfo", "onSubscribe: ");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNext(@NonNull Integer row) {
|
||||||
|
Log.e("updateAppInfo", "onNext: " + row);
|
||||||
|
mAppUpdateData.setValue(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(@NonNull Throwable e) {
|
||||||
|
Log.e("updateAppInfo", "onError: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete() {
|
||||||
|
Log.e("updateAppInfo", "onComplete: ");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,9 @@
|
|||||||
package com.ttstd.dialer.fragment.contact;
|
package com.ttstd.dialer.fragment.contact;
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.core.app.ActivityCompat;
|
|
||||||
import androidx.lifecycle.Observer;
|
import androidx.lifecycle.Observer;
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
|
||||||
@@ -16,9 +11,8 @@ import com.ttstd.dialer.R;
|
|||||||
import com.ttstd.dialer.adapter.HomeContactAdapter;
|
import com.ttstd.dialer.adapter.HomeContactAdapter;
|
||||||
import com.ttstd.dialer.base.mvvm.fragment.BaseMvvmFragment;
|
import com.ttstd.dialer.base.mvvm.fragment.BaseMvvmFragment;
|
||||||
import com.ttstd.dialer.databinding.FragmentContactBinding;
|
import com.ttstd.dialer.databinding.FragmentContactBinding;
|
||||||
import com.ttstd.dialer.db.contact.Contact;
|
import com.ttstd.dialer.db.contact.ContactInfo;
|
||||||
import com.ttstd.dialer.fragment.dialog.call.CallFragment;
|
import com.ttstd.dialer.fragment.dialog.call.CallFragment;
|
||||||
import com.ttstd.dialer.fragment.dialog.permission.PermissionDialogFragment;
|
|
||||||
import com.ttstd.dialer.view.EqualHeightDecoration;
|
import com.ttstd.dialer.view.EqualHeightDecoration;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -28,7 +22,7 @@ public class ContactFragment extends BaseMvvmFragment<ContactViewModel, Fragment
|
|||||||
|
|
||||||
private Activity mContext;
|
private Activity mContext;
|
||||||
private HomeContactAdapter mHomeContactAdapter;
|
private HomeContactAdapter mHomeContactAdapter;
|
||||||
private List<Contact> mContacts;
|
private List<ContactInfo> mContactInfos;
|
||||||
|
|
||||||
private static final int REQUEST_CODE_CALL = 7897;
|
private static final int REQUEST_CODE_CALL = 7897;
|
||||||
|
|
||||||
@@ -52,8 +46,8 @@ public class ContactFragment extends BaseMvvmFragment<ContactViewModel, Fragment
|
|||||||
mHomeContactAdapter = new HomeContactAdapter();
|
mHomeContactAdapter = new HomeContactAdapter();
|
||||||
mHomeContactAdapter.setOnClickListener(new HomeContactAdapter.OnClickListener() {
|
mHomeContactAdapter.setOnClickListener(new HomeContactAdapter.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(Contact contact) {
|
public void onClick(ContactInfo contactInfo) {
|
||||||
new CallFragment(contact).show(getChildFragmentManager(), "CallFragment");
|
new CallFragment(contactInfo).show(getChildFragmentManager(), "CallFragment");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
GridLayoutManager gridLayoutManager = new GridLayoutManager(mContext, 2);
|
GridLayoutManager gridLayoutManager = new GridLayoutManager(mContext, 2);
|
||||||
@@ -64,12 +58,12 @@ public class ContactFragment extends BaseMvvmFragment<ContactViewModel, Fragment
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initData(Bundle savedInstanceState) {
|
protected void initData(Bundle savedInstanceState) {
|
||||||
mViewModel.mContactListData.observe(this, new Observer<List<Contact>>() {
|
mViewModel.mContactListData.observe(this, new Observer<List<ContactInfo>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(List<Contact> contacts) {
|
public void onChanged(List<ContactInfo> contactInfos) {
|
||||||
Log.e(TAG, "mContactListData: " + contacts);
|
Log.e(TAG, "mContactListData: " + contactInfos);
|
||||||
mContacts = contacts;
|
mContactInfos = contactInfos;
|
||||||
mHomeContactAdapter.setContacts(mContacts);
|
mHomeContactAdapter.setContactInfos(mContactInfos);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,10 @@ import android.util.Log;
|
|||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
import com.trello.rxlifecycle4.RxLifecycle;
|
import com.trello.rxlifecycle4.RxLifecycle;
|
||||||
import com.trello.rxlifecycle4.android.ActivityEvent;
|
|
||||||
import com.trello.rxlifecycle4.android.FragmentEvent;
|
import com.trello.rxlifecycle4.android.FragmentEvent;
|
||||||
import com.ttstd.dialer.base.mvvm.BaseViewModel;
|
import com.ttstd.dialer.base.mvvm.BaseViewModel;
|
||||||
import com.ttstd.dialer.databinding.FragmentContactBinding;
|
import com.ttstd.dialer.databinding.FragmentContactBinding;
|
||||||
import com.ttstd.dialer.db.contact.Contact;
|
import com.ttstd.dialer.db.contact.ContactInfo;
|
||||||
import com.ttstd.dialer.db.contact.ContactRepository;
|
import com.ttstd.dialer.db.contact.ContactRepository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -33,29 +32,29 @@ public class ContactViewModel extends BaseViewModel<FragmentContactBinding, Frag
|
|||||||
mRepository = new ContactRepository(context);
|
mRepository = new ContactRepository(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MutableLiveData<List<Contact>> mContactListData = new MutableLiveData<>();
|
public MutableLiveData<List<ContactInfo>> mContactListData = new MutableLiveData<>();
|
||||||
|
|
||||||
public void getAllContacts() {
|
public void getAllContacts() {
|
||||||
Observable.create(new ObservableOnSubscribe<List<Contact>>() {
|
Observable.create(new ObservableOnSubscribe<List<ContactInfo>>() {
|
||||||
@Override
|
@Override
|
||||||
public void subscribe(@NonNull ObservableEmitter<List<Contact>> emitter) throws Throwable {
|
public void subscribe(@NonNull ObservableEmitter<List<ContactInfo>> emitter) throws Throwable {
|
||||||
List<Contact> contacts = mRepository.getAllContacts();
|
List<ContactInfo> contactInfos = mRepository.getAllContacts();
|
||||||
emitter.onNext(contacts);
|
emitter.onNext(contactInfos);
|
||||||
emitter.onComplete();
|
emitter.onComplete();
|
||||||
}
|
}
|
||||||
}).compose(RxLifecycle.bindUntilEvent(getLifecycle(), FragmentEvent.DESTROY))
|
}).compose(RxLifecycle.bindUntilEvent(getLifecycle(), FragmentEvent.DESTROY))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(new Observer<List<Contact>>() {
|
.subscribe(new Observer<List<ContactInfo>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSubscribe(@NonNull Disposable d) {
|
public void onSubscribe(@NonNull Disposable d) {
|
||||||
Log.e("getAllContacts", "onSubscribe: ");
|
Log.e("getAllContacts", "onSubscribe: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNext(@NonNull List<Contact> contacts) {
|
public void onNext(@NonNull List<ContactInfo> contactInfos) {
|
||||||
Log.e("getAllContacts", "onNext: ");
|
Log.e("getAllContacts", "onNext: ");
|
||||||
mContactListData.setValue(contacts);
|
mContactListData.setValue(contactInfos);
|
||||||
|
|
||||||
// List<Contact> sorted = contacts.stream().sorted(new Comparator<Contact>() {
|
// List<Contact> sorted = contacts.stream().sorted(new Comparator<Contact>() {
|
||||||
// @Override
|
// @Override
|
||||||
|
|||||||
@@ -21,10 +21,9 @@ import androidx.fragment.app.FragmentManager;
|
|||||||
import androidx.fragment.app.FragmentTransaction;
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
|
|
||||||
import com.ttstd.dialer.R;
|
import com.ttstd.dialer.R;
|
||||||
import com.ttstd.dialer.activity.contact.list.ContactListActivity;
|
|
||||||
import com.ttstd.dialer.base.mvvm.fragment.BaseMvvmDialogFragment;
|
import com.ttstd.dialer.base.mvvm.fragment.BaseMvvmDialogFragment;
|
||||||
import com.ttstd.dialer.databinding.FragmentCallBinding;
|
import com.ttstd.dialer.databinding.FragmentCallBinding;
|
||||||
import com.ttstd.dialer.db.contact.Contact;
|
import com.ttstd.dialer.db.contact.ContactInfo;
|
||||||
|
|
||||||
public class CallFragment extends BaseMvvmDialogFragment<CallViewModel, FragmentCallBinding> {
|
public class CallFragment extends BaseMvvmDialogFragment<CallViewModel, FragmentCallBinding> {
|
||||||
private static final String TAG = "CallFragment";
|
private static final String TAG = "CallFragment";
|
||||||
@@ -32,10 +31,10 @@ public class CallFragment extends BaseMvvmDialogFragment<CallViewModel, Fragment
|
|||||||
private static final int REQUEST_CODE_CALL = 7897;
|
private static final int REQUEST_CODE_CALL = 7897;
|
||||||
|
|
||||||
private Activity mContext;
|
private Activity mContext;
|
||||||
private Contact mContact;
|
private ContactInfo mContactInfo;
|
||||||
|
|
||||||
public CallFragment(Contact contact) {
|
public CallFragment(ContactInfo contactInfo) {
|
||||||
mContact = contact;
|
mContactInfo = contactInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -112,7 +111,7 @@ public class CallFragment extends BaseMvvmDialogFragment<CallViewModel, Fragment
|
|||||||
|
|
||||||
public void call() {
|
public void call() {
|
||||||
try {
|
try {
|
||||||
String phone = mContact.getPhoneNumber();
|
String phone = mContactInfo.getPhoneNumber();
|
||||||
Intent dialIntent = new Intent(Intent.ACTION_CALL);
|
Intent dialIntent = new Intent(Intent.ACTION_CALL);
|
||||||
Uri data = Uri.parse("tel:" + phone);
|
Uri data = Uri.parse("tel:" + phone);
|
||||||
dialIntent.setData(data);
|
dialIntent.setData(data);
|
||||||
|
|||||||
@@ -0,0 +1,183 @@
|
|||||||
|
package com.ttstd.dialer.fragment.dialog.shortcut;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.drawable.ColorDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
import androidx.fragment.app.DialogFragment;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
|
|
||||||
|
import com.ttstd.dialer.R;
|
||||||
|
import com.ttstd.dialer.base.mvvm.fragment.BaseMvvmDialogFragment;
|
||||||
|
import com.ttstd.dialer.databinding.FragmentDialogShortcutBinding;
|
||||||
|
import com.ttstd.dialer.db.app.AppInfo;
|
||||||
|
|
||||||
|
public class ShortcutDialogFagment extends BaseMvvmDialogFragment<ShortcutViewModel, FragmentDialogShortcutBinding> {
|
||||||
|
private static final String TAG = "ShortcutDialogFagment";
|
||||||
|
|
||||||
|
private Activity mContext;
|
||||||
|
private PackageManager mPackageManager;
|
||||||
|
|
||||||
|
private AppInfo mAppInfo;
|
||||||
|
private String mTitil;
|
||||||
|
private String mTips;
|
||||||
|
private String mNegativeText;
|
||||||
|
private String mPositiveText;
|
||||||
|
|
||||||
|
public ShortcutDialogFagment(AppInfo appInfo) {
|
||||||
|
mAppInfo = appInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitil(String titil) {
|
||||||
|
mTitil = titil;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTips(String tips) {
|
||||||
|
mTips = tips;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNegativeText(String negativeText) {
|
||||||
|
mNegativeText = negativeText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPositiveText(String positiveText) {
|
||||||
|
mPositiveText = positiveText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnClickListener {
|
||||||
|
void onPositiveClick();
|
||||||
|
|
||||||
|
void onNegativeClick();
|
||||||
|
}
|
||||||
|
|
||||||
|
private OnClickListener mOnClickListener;
|
||||||
|
|
||||||
|
public void setOnClickListener(OnClickListener onClickListener) {
|
||||||
|
mOnClickListener = onClickListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getLayoutId() {
|
||||||
|
return R.layout.fragment_dialog_shortcut;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initDataBinding() {
|
||||||
|
mContext = getActivity();
|
||||||
|
mPackageManager = mContext.getPackageManager();
|
||||||
|
mViewModel.setContext(mContext);
|
||||||
|
mViewModel.setVDBinding(mViewDataBinding);
|
||||||
|
mViewModel.setLifecycle(getLifecycleSubject());
|
||||||
|
mViewDataBinding.setClick(new BtnClick());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initView(Bundle bundle) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initData(Bundle savedInstanceState) {
|
||||||
|
if (TextUtils.isEmpty(mTitil)) {
|
||||||
|
mViewDataBinding.tvTitle.setText("提示");
|
||||||
|
} else {
|
||||||
|
mViewDataBinding.tvTitle.setText(mTitil);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TextUtils.isEmpty(mTips)) {
|
||||||
|
mViewDataBinding.tvMessage.setText("");
|
||||||
|
mViewDataBinding.tvMessage.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
mViewDataBinding.tvMessage.setText(mTips);
|
||||||
|
mViewDataBinding.tvMessage.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TextUtils.isEmpty(mNegativeText)){
|
||||||
|
mViewDataBinding.tvNegative.setText("取消");
|
||||||
|
}else {
|
||||||
|
mViewDataBinding.tvNegative.setText(mNegativeText);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TextUtils.isEmpty(mPositiveText)){
|
||||||
|
mViewDataBinding.tvPositive.setText("确定");
|
||||||
|
}else {
|
||||||
|
mViewDataBinding.tvPositive.setText(mPositiveText);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mAppInfo != null) {
|
||||||
|
try {
|
||||||
|
ActivityInfo info = mPackageManager.getActivityInfo(mAppInfo.getComponentName(), 0);
|
||||||
|
mViewDataBinding.tvAppName.setText(info.loadLabel(mPackageManager));
|
||||||
|
Drawable rawIcon = info.loadIcon(mPackageManager);
|
||||||
|
mViewDataBinding.ivIcon.setImageDrawable(rawIcon);
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
if (getDialog() != null) {
|
||||||
|
Window window = getDialog().getWindow();
|
||||||
|
if (window == null) return;
|
||||||
|
WindowManager.LayoutParams params = window.getAttributes();
|
||||||
|
params.width = WindowManager.LayoutParams.MATCH_PARENT;
|
||||||
|
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
||||||
|
params.gravity = Gravity.CENTER;
|
||||||
|
window.setAttributes(params);
|
||||||
|
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||||
|
getDialog().setCancelable(true);
|
||||||
|
getDialog().setCanceledOnTouchOutside(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void show(FragmentManager manager, String tag) {
|
||||||
|
DialogFragment fragment = (DialogFragment) manager.findFragmentByTag(tag);
|
||||||
|
if (fragment != null && fragment.isAdded()
|
||||||
|
&& fragment.getDialog() != null && fragment.getDialog().isShowing()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
FragmentTransaction ft = manager.beginTransaction();
|
||||||
|
ft.add(this, tag);
|
||||||
|
ft.commitAllowingStateLoss();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "show: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fetchData() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BtnClick {
|
||||||
|
public void onPositive(View view) {
|
||||||
|
if (mOnClickListener != null) {
|
||||||
|
mOnClickListener.onPositiveClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onNegative(View view) {
|
||||||
|
if (mOnClickListener != null) {
|
||||||
|
mOnClickListener.onNegativeClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.ttstd.dialer.fragment.dialog.shortcut;
|
||||||
|
|
||||||
|
import com.trello.rxlifecycle4.android.FragmentEvent;
|
||||||
|
import com.ttstd.dialer.base.mvvm.BaseViewModel;
|
||||||
|
import com.ttstd.dialer.databinding.FragmentDialogShortcutBinding;
|
||||||
|
|
||||||
|
public class ShortcutViewModel extends BaseViewModel <FragmentDialogShortcutBinding, FragmentEvent>{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,8 +9,8 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.tencent.mmkv.MMKV;
|
import com.tencent.mmkv.MMKV;
|
||||||
import com.ttstd.dialer.config.CommonConfig;
|
import com.ttstd.dialer.config.CommonConfig;
|
||||||
|
import com.ttstd.dialer.db.app.AppInfo;
|
||||||
import com.ttstd.dialer.db.app.AppRepository;
|
import com.ttstd.dialer.db.app.AppRepository;
|
||||||
import com.ttstd.dialer.db.app.DesktopSortApp;
|
|
||||||
import com.ttstd.dialer.gson.GsonUtils;
|
import com.ttstd.dialer.gson.GsonUtils;
|
||||||
import com.ttstd.dialer.utils.ApkUtils;
|
import com.ttstd.dialer.utils.ApkUtils;
|
||||||
|
|
||||||
@@ -27,6 +27,7 @@ import java.util.concurrent.CompletableFuture;
|
|||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.function.IntConsumer;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
@@ -73,6 +74,8 @@ public class AppManager {
|
|||||||
this.add("com.android.settings");
|
this.add("com.android.settings");
|
||||||
this.add("com.android.dialer");
|
this.add("com.android.dialer");
|
||||||
this.add("com.android.camera2");
|
this.add("com.android.camera2");
|
||||||
|
this.add("com.android.messaging");
|
||||||
|
this.add("com.android.contacts");
|
||||||
this.add("com.tencent.mm");
|
this.add("com.tencent.mm");
|
||||||
this.add("com.jiangjia.gif");
|
this.add("com.jiangjia.gif");
|
||||||
this.add("com.ss.android.ugc.aweme");
|
this.add("com.ss.android.ugc.aweme");
|
||||||
@@ -142,9 +145,9 @@ public class AppManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 第一步:获取所有桌面应用(空值安全处理)
|
// 第一步:获取所有桌面应用(空值安全处理)
|
||||||
private List<DesktopSortApp> getAllDesktopSortApps() {
|
private List<AppInfo> getAllDesktopSortApps() {
|
||||||
try {
|
try {
|
||||||
List<DesktopSortApp> result = mAppRepository.getAllApp();
|
List<AppInfo> result = mAppRepository.getAllApp();
|
||||||
return result != null ? result : Collections.emptyList();
|
return result != null ? result : Collections.emptyList();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, "获取桌面应用列表失败", e);
|
Log.e(TAG, "获取桌面应用列表失败", e);
|
||||||
@@ -166,16 +169,27 @@ public class AppManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<DesktopSortApp> allFirstApps = allLauncherApps.stream()
|
List<AppInfo> allFirstApps = allLauncherApps.stream()
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.map(this::resolveInfoToDesktopApp)
|
.map(this::resolveInfoToDesktopApp)
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.sorted((o1, o2) -> Boolean.compare(ApkUtils.isSystemApp(mContext, o1.getPackageName()), ApkUtils.isSystemApp(mContext, o2.getPackageName())))
|
.sorted((o1, o2) -> Boolean.compare(ApkUtils.isSystemApp(mContext, o2.getPackageName()), ApkUtils.isSystemApp(mContext, o1.getPackageName())))
|
||||||
.sorted(getAppComparator())
|
.sorted(getAppComparator())
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
IntStream.range(0, allFirstApps.size())
|
IntStream.range(0, allFirstApps.size())
|
||||||
.forEach(index -> allFirstApps.get(index).setPosition(index));
|
.forEach(new IntConsumer() {
|
||||||
|
@Override
|
||||||
|
public void accept(int index) {
|
||||||
|
AppInfo appInfo = allFirstApps.get(index);
|
||||||
|
if (DEFAULT_APP_PACKAGES.contains(appInfo.getPackageName())) {
|
||||||
|
appInfo.setOutside(1);
|
||||||
|
} else {
|
||||||
|
appInfo.setOutside(0);
|
||||||
|
}
|
||||||
|
appInfo.setPosition(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 批量插入首次数据
|
// 批量插入首次数据
|
||||||
allFirstApps.forEach(app -> {
|
allFirstApps.forEach(app -> {
|
||||||
@@ -195,15 +209,15 @@ public class AppManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 处理未安装的应用(删除操作)
|
// 处理未安装的应用(删除操作)
|
||||||
private CompletableFuture<Void> processUninstalledApps(List<DesktopSortApp> desktopSortApps) {
|
private CompletableFuture<Void> processUninstalledApps(List<AppInfo> appInfos) {
|
||||||
return CompletableFuture.runAsync(() -> {
|
return CompletableFuture.runAsync(() -> {
|
||||||
notifyProgress(STEP_REMOVE_UNINSTALLED, 1, TOTAL_STEPS_NORMAL);
|
notifyProgress(STEP_REMOVE_UNINSTALLED, 1, TOTAL_STEPS_NORMAL);
|
||||||
if (desktopSortApps.isEmpty()) {
|
if (appInfos.isEmpty()) {
|
||||||
Log.w(TAG, "桌面应用列表为空,跳过删除处理");
|
Log.w(TAG, "桌面应用列表为空,跳过删除处理");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Integer> ids = desktopSortApps.stream()
|
List<Integer> ids = appInfos.stream()
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.filter(app -> !ApkUtils.isInstalled(mContext, app.getPackageName()))
|
.filter(app -> !ApkUtils.isInstalled(mContext, app.getPackageName()))
|
||||||
.map(app -> {
|
.map(app -> {
|
||||||
@@ -240,7 +254,7 @@ public class AppManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<DesktopSortApp> newApps = resolveInfos.stream()
|
List<AppInfo> newApps = resolveInfos.stream()
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.map(this::resolveInfoToDesktopApp)
|
.map(this::resolveInfoToDesktopApp)
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
@@ -273,20 +287,20 @@ public class AppManager {
|
|||||||
private CompletableFuture<Void> updatePosition() {
|
private CompletableFuture<Void> updatePosition() {
|
||||||
return CompletableFuture.runAsync(() -> {
|
return CompletableFuture.runAsync(() -> {
|
||||||
try {
|
try {
|
||||||
List<DesktopSortApp> desktopSortApps = getAllDesktopSortApps();
|
List<AppInfo> appInfos = getAllDesktopSortApps();
|
||||||
if (desktopSortApps.isEmpty()) {
|
if (appInfos.isEmpty()) {
|
||||||
Log.w(TAG, "无应用数据,跳过位置更新");
|
Log.w(TAG, "无应用数据,跳过位置更新");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<DesktopSortApp> sortedApps = desktopSortApps.stream()
|
List<AppInfo> sortedApps = appInfos.stream()
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.sorted(Comparator.comparingInt(DesktopSortApp::getPosition))
|
.sorted(Comparator.comparingInt(AppInfo::getPosition))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
IntStream.range(0, sortedApps.size())
|
IntStream.range(0, sortedApps.size())
|
||||||
.forEach(index -> {
|
.forEach(index -> {
|
||||||
DesktopSortApp app = sortedApps.get(index);
|
AppInfo app = sortedApps.get(index);
|
||||||
app.setPosition(index);
|
app.setPosition(index);
|
||||||
try {
|
try {
|
||||||
mAppRepository.update(app);
|
mAppRepository.update(app);
|
||||||
@@ -303,16 +317,16 @@ public class AppManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 工具方法:ResolveInfo转换为DesktopSortApp
|
// 工具方法:ResolveInfo转换为DesktopSortApp
|
||||||
private DesktopSortApp resolveInfoToDesktopApp(ResolveInfo resolveInfo) {
|
private AppInfo resolveInfoToDesktopApp(ResolveInfo resolveInfo) {
|
||||||
ComponentName component = new ComponentName(
|
ComponentName component = new ComponentName(
|
||||||
resolveInfo.activityInfo.packageName,
|
resolveInfo.activityInfo.packageName,
|
||||||
resolveInfo.activityInfo.name
|
resolveInfo.activityInfo.name
|
||||||
);
|
);
|
||||||
return new DesktopSortApp(mContext, component);
|
return new AppInfo(mContext, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 工具方法:检查应用是否已存在
|
// 工具方法:检查应用是否已存在
|
||||||
private boolean isAppExists(DesktopSortApp app) {
|
private boolean isAppExists(AppInfo app) {
|
||||||
try {
|
try {
|
||||||
return mAppRepository.checkAppInfoExists(app.getPackageName(), app.getClassName()) > 0;
|
return mAppRepository.checkAppInfoExists(app.getPackageName(), app.getClassName()) > 0;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -322,8 +336,8 @@ public class AppManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 工具方法:获取应用排序器(统一排序逻辑)
|
// 工具方法:获取应用排序器(统一排序逻辑)
|
||||||
private Comparator<DesktopSortApp> getAppComparator() {
|
private Comparator<AppInfo> getAppComparator() {
|
||||||
return Comparator.comparing(DesktopSortApp::getLabel, Collator.getInstance(Locale.CHINESE));
|
return Comparator.comparing(AppInfo::getLabel, Collator.getInstance(Locale.CHINESE));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateApp(String packageName) {
|
public void updateApp(String packageName) {
|
||||||
@@ -347,7 +361,7 @@ public class AppManager {
|
|||||||
// 重构getAllApp方法,复用现有处理逻辑
|
// 重构getAllApp方法,复用现有处理逻辑
|
||||||
public void refreshAllApps() {
|
public void refreshAllApps() {
|
||||||
CompletableFuture.runAsync(() -> {
|
CompletableFuture.runAsync(() -> {
|
||||||
List<DesktopSortApp> allApps = getAllDesktopSortApps();
|
List<AppInfo> allApps = getAllDesktopSortApps();
|
||||||
if (allApps.isEmpty()) {
|
if (allApps.isEmpty()) {
|
||||||
processFirstTimeApps().join();
|
processFirstTimeApps().join();
|
||||||
} else {
|
} else {
|
||||||
@@ -362,12 +376,12 @@ public class AppManager {
|
|||||||
PackageManager pm = mContext.getPackageManager();
|
PackageManager pm = mContext.getPackageManager();
|
||||||
List<ResolveInfo> resolveInfos = ApkUtils.getAllLauncherResolveInfo(mContext);
|
List<ResolveInfo> resolveInfos = ApkUtils.getAllLauncherResolveInfo(mContext);
|
||||||
|
|
||||||
List<DesktopSortApp> defaultApps = resolveInfos.stream()
|
List<AppInfo> defaultApps = resolveInfos.stream()
|
||||||
.filter(ri -> DEFAULT_APP_PACKAGES.contains(ri.activityInfo.packageName))
|
.filter(ri -> DEFAULT_APP_PACKAGES.contains(ri.activityInfo.packageName))
|
||||||
.sorted((o1, o2) -> Collator.getInstance(Locale.CHINESE)
|
.sorted((o1, o2) -> Collator.getInstance(Locale.CHINESE)
|
||||||
.compare(o1.activityInfo.loadLabel(pm), o2.activityInfo.loadLabel(pm)))
|
.compare(o1.activityInfo.loadLabel(pm), o2.activityInfo.loadLabel(pm)))
|
||||||
.map(ri -> new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name))
|
.map(ri -> new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name))
|
||||||
.map(component -> new DesktopSortApp(mContext, component))
|
.map(component -> new AppInfo(mContext, component))
|
||||||
.sorted((a, b) -> Boolean.compare(
|
.sorted((a, b) -> Boolean.compare(
|
||||||
ApkUtils.isSystemApp(mContext, b.getPackageName()),
|
ApkUtils.isSystemApp(mContext, b.getPackageName()),
|
||||||
ApkUtils.isSystemApp(mContext, a.getPackageName())))
|
ApkUtils.isSystemApp(mContext, a.getPackageName())))
|
||||||
|
|||||||
36
app/src/main/java/com/ttstd/dialer/view/ApkPagerAdapter.java
Normal file
36
app/src/main/java/com/ttstd/dialer/view/ApkPagerAdapter.java
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package com.ttstd.dialer.view;
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
import androidx.fragment.app.FragmentPagerAdapter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ApkPagerAdapter extends FragmentPagerAdapter {
|
||||||
|
|
||||||
|
private List<Fragment> fragments;
|
||||||
|
|
||||||
|
public ApkPagerAdapter(FragmentManager fm) {
|
||||||
|
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFragments(List<Fragment> fragments) {
|
||||||
|
this.fragments = fragments;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Fragment getItem(int position) {
|
||||||
|
return fragments.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return fragments == null ? 0 : fragments.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解决数据更新不刷新的问题
|
||||||
|
@Override
|
||||||
|
public int getItemPosition(Object object) {
|
||||||
|
return POSITION_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
13
app/src/main/res/drawable/default_negative_background.xml
Normal file
13
app/src/main/res/drawable/default_negative_background.xml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!-- 内部颜色 -->
|
||||||
|
<solid android:color="@color/lightGray" />
|
||||||
|
<!-- 圆角的幅度 -->
|
||||||
|
<corners android:radius="32dp" />
|
||||||
|
|
||||||
|
<padding
|
||||||
|
android:bottom="4dp"
|
||||||
|
android:left="20dp"
|
||||||
|
android:right="20dp"
|
||||||
|
android:top="4dp" />
|
||||||
|
</shape>
|
||||||
13
app/src/main/res/drawable/default_positive_background.xml
Normal file
13
app/src/main/res/drawable/default_positive_background.xml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<!-- 内部颜色 -->
|
||||||
|
<solid android:color="#5591F3" />
|
||||||
|
<!-- 圆角的幅度 -->
|
||||||
|
<corners android:radius="32dp" />
|
||||||
|
|
||||||
|
<padding
|
||||||
|
android:bottom="4dp"
|
||||||
|
android:left="20dp"
|
||||||
|
android:right="20dp"
|
||||||
|
android:top="4dp" />
|
||||||
|
</shape>
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="300dp"
|
android:layout_width="300dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@drawable/bg_permissions"
|
android:background="@drawable/default_dialog_background"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
|||||||
@@ -15,7 +15,10 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="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"/>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|||||||
163
app/src/main/res/layout/fragment_dialog_shortcut.xml
Normal file
163
app/src/main/res/layout/fragment_dialog_shortcut.xml
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
tools:context=".fragment.dialog.shortcut.ShortcutDialogFagment">
|
||||||
|
|
||||||
|
<data>
|
||||||
|
|
||||||
|
<variable
|
||||||
|
name="click"
|
||||||
|
type="com.ttstd.dialer.fragment.dialog.shortcut.ShortcutDialogFagment.BtnClick" />
|
||||||
|
</data>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="300dp"
|
||||||
|
android:layout_height="240dp"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:background="@drawable/default_dialog_background"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/linearLayout"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:visibility="visible"
|
||||||
|
tools:text="消息" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_message"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:visibility="visible"
|
||||||
|
tools:text="消息" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/linearLayout2"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/linearLayout">
|
||||||
|
|
||||||
|
<com.shehuan.niv.NiceImageView
|
||||||
|
android:id="@+id/iv_icon"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:src="@mipmap/ic_launcher" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_app_icon"
|
||||||
|
android:layout_width="16dp"
|
||||||
|
android:layout_height="16dp"
|
||||||
|
android:layout_marginStart="26dp"
|
||||||
|
android:layout_marginTop="26dp"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/iv_icon"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:src="@mipmap/ic_launcher" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_app_name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:lineSpacingExtra="3dp"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="#676767"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/iv_icon"
|
||||||
|
tools:text="app" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/linearLayout2"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:layout_marginEnd="24dp"
|
||||||
|
android:layout_marginBottom="20dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_negative"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/default_negative_background"
|
||||||
|
android:gravity="center"
|
||||||
|
android:onClick="@{click::onNegative}"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="取消" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_positive"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/default_positive_background"
|
||||||
|
android:gravity="center"
|
||||||
|
android:onClick="@{click::onPositive}"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="确定" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</layout>
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
<ImageView
|
<com.shehuan.niv.NiceImageView
|
||||||
android:id="@+id/iv_icon"
|
android:id="@+id/iv_icon"
|
||||||
android:layout_width="60dp"
|
android:layout_width="60dp"
|
||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
|
|||||||
49
app/src/main/res/layout/item_more_app.xml
Normal file
49
app/src/main/res/layout/item_more_app.xml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="120dp">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/root"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<com.shehuan.niv.NiceImageView
|
||||||
|
android:id="@+id/iv_icon"
|
||||||
|
android:layout_width="60dp"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:src="@mipmap/ic_launcher"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_app_name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="appname"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="16sp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/iv_icon" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -129,19 +129,31 @@ public class IconCacheManager {
|
|||||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
if (icon instanceof AdaptiveIconDrawable) {
|
if (icon instanceof AdaptiveIconDrawable) {
|
||||||
// 分别获取背景和前景Drawable
|
// 分别获取背景和前景Drawable
|
||||||
Drawable[] layers = new Drawable[2];
|
// Drawable[] layers = new Drawable[2];
|
||||||
layers[0] = ((AdaptiveIconDrawable) icon).getBackground();
|
// layers[0] = ((AdaptiveIconDrawable) icon).getBackground();
|
||||||
layers[1] = ((AdaptiveIconDrawable) icon).getForeground();
|
// layers[1] = ((AdaptiveIconDrawable) icon).getForeground();
|
||||||
LayerDrawable layerDrawable = new LayerDrawable(layers);
|
// LayerDrawable layerDrawable = new LayerDrawable(layers);
|
||||||
|
//
|
||||||
|
// int width = icon.getIntrinsicWidth();
|
||||||
|
// int height = icon.getIntrinsicHeight();
|
||||||
|
//
|
||||||
|
// Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||||
|
// Canvas canvas = new Canvas(bitmap);
|
||||||
|
//
|
||||||
|
// layerDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
||||||
|
// layerDrawable.draw(canvas);
|
||||||
|
|
||||||
int width = icon.getIntrinsicWidth();
|
// 创建一个大小与原始Drawable相同的位图
|
||||||
int height = icon.getIntrinsicHeight();
|
Bitmap bitmap = Bitmap.createBitmap(
|
||||||
|
icon.getIntrinsicWidth(),
|
||||||
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
icon.getIntrinsicHeight(),
|
||||||
|
Bitmap.Config.ARGB_8888
|
||||||
|
);
|
||||||
Canvas canvas = new Canvas(bitmap);
|
Canvas canvas = new Canvas(bitmap);
|
||||||
|
// 关键步骤:设置Drawable的绘制边界
|
||||||
|
icon.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
||||||
|
icon.draw(canvas);
|
||||||
|
|
||||||
layerDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
|
||||||
layerDrawable.draw(canvas);
|
|
||||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, editor.newOutputStream(0));
|
bitmap.compress(Bitmap.CompressFormat.PNG, 100, editor.newOutputStream(0));
|
||||||
editor.commit();
|
editor.commit();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user