This commit is contained in:
wangcongtao
2020-01-08 18:08:42 +08:00
parent 2b2e998421
commit d5c87148a5
17 changed files with 408 additions and 114 deletions

View File

@@ -0,0 +1,20 @@
package com.mogo.module.apps;
import android.content.pm.PackageInfo;
/**
* @author congtaowang
* @since 2020-01-08
* <p>
* app 过滤规则
*/
public interface AppFilter {
/**
* 过滤包
*
* @param packageInfo
* @return true - 过滤 false - 不过滤
*/
boolean filter( PackageInfo packageInfo );
}

View File

@@ -0,0 +1,55 @@
package com.mogo.module.apps;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import java.util.Arrays;
import java.util.List;
/**
* @author congtaowang
* @since 2020-01-08
* <p>
* 过滤 app
*/
public class AppFilterImpl implements AppFilter {
private final Context mContext;
private List< String > mFilterPackages;
public AppFilterImpl( Context context ) {
mContext = context;
final String[] values = context.getResources().getStringArray( R.array.module_apps_array_filter_packages );
if ( values != null ) {
mFilterPackages = Arrays.asList( values );
}
}
@Override
public boolean filter( PackageInfo packageInfo ) {
// if ( isSystemApp( packageInfo ) ) {
// return true;
// }
if ( isFilterPackages( packageInfo ) ) {
return true;
}
if ( noLaunchIntent( packageInfo ) ) {
return true;
}
return false;
}
private boolean isSystemApp( PackageInfo packageInfo ) {
return ( packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM ) != 0;
}
private boolean isFilterPackages( PackageInfo packageInfo ) {
return mFilterPackages.contains( packageInfo.packageName );
}
private boolean noLaunchIntent( PackageInfo packageInfo ) {
return mContext.getPackageManager().getLaunchIntentForPackage( packageInfo.packageName ) == null;
}
}

View File

@@ -3,11 +3,11 @@ package com.mogo.module.apps;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.mogo.module.apps.model.AppInfo;
@@ -19,53 +19,59 @@ import java.util.List;
* <p>
* 描述
*/
public class AppsAdapter extends RecyclerView.Adapter< AppsAdapter.AppsViewHolder > {
public class AppsAdapter extends BaseAdapter {
private List< AppInfo > mAppInfos;
public AppsAdapter( List< AppInfo > appInfos ) {
this.mAppInfos = appInfos;
}
private View.OnClickListener onClickListener;
public void refreshAppInfos( List< AppInfo > mAppInfos ) {
this.mAppInfos = mAppInfos;
notifyDataSetChanged();
}
@NonNull
@Override
public AppsViewHolder onCreateViewHolder( @NonNull ViewGroup parent, int viewType ) {
return new AppsViewHolder( LayoutInflater.from( parent.getContext() ).inflate( R.layout.module_apps_item_app, null ) );
}
@Override
public void onBindViewHolder( @NonNull AppsViewHolder holder, int position ) {
final AppInfo appInfo = mAppInfos.get( position );
holder.mIcon.setImageDrawable( appInfo.getIcon() );
holder.mName.setText( appInfo.getName() );
holder.itemView.setTag(appInfo);
holder.itemView.setOnClickListener(onClickListener);
}
@Override
public int getItemCount() {
public int getCount() {
return mAppInfos == null ? 0 : mAppInfos.size();
}
public static class AppsViewHolder extends RecyclerView.ViewHolder {
@Override
public AppInfo getItem( int position ) {
return mAppInfos.get( position );
}
@Override
public long getItemId( int position ) {
return position;
}
@Override
public View getView( int position, View convertView, ViewGroup parent ) {
AppViewHolder holder = null;
if ( convertView == null ) {
holder = new AppViewHolder( LayoutInflater.from( parent.getContext() ).inflate( R.layout.module_apps_item_app, null ) );
} else {
holder = ( ( AppViewHolder ) convertView.getTag() );
}
AppInfo appInfo = getItem( position );
holder.mIcon.setImageDrawable( appInfo.getIcon() );
holder.mName.setText( appInfo.getName() );
return holder.mItemView;
}
public static class AppViewHolder {
private View mItemView;
public ImageView mIcon;
public TextView mName;
public AppsViewHolder( @NonNull View itemView ) {
super( itemView );
public AppViewHolder( @NonNull View itemView ) {
mItemView = itemView;
mIcon = itemView.findViewById( R.id.module_apps_id_app_icon );
mName = itemView.findViewById( R.id.module_apps_id_app_name );
mItemView.setTag( this );
}
}
public void setOnClickListener(View.OnClickListener onClickListener) {
this.onClickListener = onClickListener;
}
}

View File

@@ -0,0 +1,12 @@
package com.mogo.module.apps;
/**
* @author congtaowang
* @since 2020-01-08
* <p>
* 描述
*/
public class AppsConst {
public static final int TOTAL_SIZE_EACH_PAGE = 12;
}

View File

@@ -1,16 +1,21 @@
package com.mogo.module.apps;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager.widget.ViewPager;
import com.alibaba.android.arouter.launcher.ARouter;
import com.mogo.commons.mvp.MvpFragment;
import com.mogo.module.apps.model.AppInfo;
import com.mogo.service.MogoServicePaths;
import com.mogo.service.fragmentmanager.IMogoFragmentManager;
import com.mogo.utils.logger.Logger;
import java.util.List;
import java.util.Map;
/**
* @author congtaowang
@@ -23,8 +28,11 @@ public class AppsFragment extends MvpFragment< AppsView, AppsPresenter > impleme
public static final String TAG = "AppsFragment";
// private BottomSheetBehavior mBottomSheetBehavior;
private RecyclerView mAppsList;
private AppsAdapter mAppsAdapter;
private ViewPager mAppsPager;
private AppsPagerAdapter mAppsPagerAdapter;
private View mExit;
private IMogoFragmentManager mMogoFragmentManager;
@Override
protected int getLayoutId() {
@@ -33,8 +41,13 @@ public class AppsFragment extends MvpFragment< AppsView, AppsPresenter > impleme
@Override
protected void initViews() {
mAppsList = findViewById( R.id.module_apps_id_apps );
mAppsList.setLayoutManager( new GridLayoutManager( getContext(), 8 ) );
mAppsPager = findViewById( R.id.module_apps_id_apps_pager );
mExit = findViewById( R.id.module_apps_id_apps_exit );
mExit.setOnClickListener( view -> {
mMogoFragmentManager.pop();
} );
// mAppsList = findViewById( R.id.module_apps_id_apps );
// mAppsList.setLayoutManager( new GridLayoutManager( getContext(), 8 ) );
// mBottomSheetBehavior = BottomSheetBehavior.from( mAppsList );
// mBottomSheetBehavior.setSkipCollapsed( true );
// mBottomSheetBehavior.setBottomSheetCallback( new BottomSheetBehavior.BottomSheetCallback() {
@@ -60,23 +73,20 @@ public class AppsFragment extends MvpFragment< AppsView, AppsPresenter > impleme
@Override
public void onActivityCreated( @Nullable Bundle savedInstanceState ) {
super.onActivityCreated( savedInstanceState );
mMogoFragmentManager = ( IMogoFragmentManager ) ARouter.getInstance().build( MogoServicePaths.PATH_FRAGMENT_MANAGER ).navigation();
}
@Override
public void renderApps( List< AppInfo > appInfos ) {
if ( mAppsAdapter == null ) {
mAppsAdapter = new AppsAdapter( appInfos );
mAppsList.setAdapter( mAppsAdapter );
bindListener();
public void renderApps( Map< Integer, List< AppInfo > > appInfos ) {
if ( mAppsPagerAdapter == null ) {
mAppsPagerAdapter = new AppsPagerAdapter( appInfos );
mAppsPager.setAdapter( mAppsPagerAdapter );
mAppsPagerAdapter.setOnAppClickedListener( ( appInfo, position ) -> {
Logger.i( TAG, "position = %d clicked. name = %s", position, appInfo.getName() );
mPresenter.launch( appInfo );
} );
} else {
mAppsAdapter.refreshAppInfos( appInfos );
mAppsPagerAdapter.setPagedApps( appInfos );
}
}
private void bindListener() {
mAppsAdapter.setOnClickListener( view -> {
AppInfo app = ( AppInfo ) view.getTag();
mPresenter.launch( app );
} );
}
}

View File

@@ -0,0 +1,85 @@
package com.mogo.module.apps;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.GridView;
import androidx.annotation.NonNull;
import androidx.viewpager.widget.PagerAdapter;
import com.mogo.module.apps.model.AppInfo;
import java.util.List;
import java.util.Map;
/**
* @author congtaowang
* @since 2020-01-08
* <p>
* 描述
*/
public class AppsPagerAdapter extends PagerAdapter {
private Map< Integer, List< AppInfo > > mPagedApps;
private OnAppClickedListener mOnAppClickedListener;
public AppsPagerAdapter( Map< Integer, List< AppInfo > > apps ) {
this.mPagedApps = apps;
}
@Override
public int getCount() {
return mPagedApps == null ? 0 : mPagedApps.size();
}
public void setOnAppClickedListener( OnAppClickedListener onAppClickedListener ) {
this.mOnAppClickedListener = onAppClickedListener;
}
public OnAppClickedListener getOnAppClickedListener() {
return mOnAppClickedListener;
}
@Override
public boolean isViewFromObject( @NonNull View view, @NonNull Object object ) {
return view == object;
}
public void setPagedApps( Map< Integer, List< AppInfo > > pagedApps ) {
this.mPagedApps = pagedApps;
notifyDataSetChanged();
}
@NonNull
@Override
public Object instantiateItem( @NonNull ViewGroup container, int position ) {
View pager = LayoutInflater.from( container.getContext() ).inflate( R.layout.module_apps_item_app_pager, null );
GridView page = pager.findViewById( R.id.module_apps_id_apps_page );
page.setAdapter( new AppsAdapter( mPagedApps.get( position ) ) );
page.setOnItemClickListener( ( parent, view, appPosition, id ) -> {
if ( getOnAppClickedListener() != null ) {
getOnAppClickedListener().onClick( mPagedApps.get( position ).get( appPosition ), position * AppsConst.TOTAL_SIZE_EACH_PAGE + appPosition );
}
} );
container.addView( page );
return page;
}
@Override
public void destroyItem( @NonNull ViewGroup container, int position, @NonNull Object object ) {
if ( object instanceof View ) {
container.removeView( ( ( View ) object ) );
}
}
@Override
public int getItemPosition( @NonNull Object object ) {
return POSITION_NONE;
}
public interface OnAppClickedListener {
void onClick( AppInfo appInfo, int position );
}
}

View File

@@ -13,11 +13,14 @@ import androidx.lifecycle.Observer;
import com.mogo.commons.mvp.Presenter;
import com.mogo.module.apps.model.AppInfo;
import com.mogo.utils.ThreadPoolService;
import com.mogo.utils.TipToast;
import com.mogo.utils.UiThreadHandler;
import com.mogo.utils.logger.Logger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author congtaowang
@@ -29,13 +32,12 @@ public class AppsPresenter extends Presenter< AppsView > {
private static final String TAG = "AppsPresenter";
private AppFilter mAppFilter;
public AppsPresenter( AppsView view ) {
super( view );
RefreshAppsListLiveData.getInstance().observeForever( new Observer< String >() {
@Override
public void onChanged( String s ) {
renderAppsList();
}
RefreshAppsListLiveData.getInstance().observeForever( s -> {
renderAppsList();
} );
}
@@ -46,55 +48,58 @@ public class AppsPresenter extends Presenter< AppsView > {
}
private void renderAppsList() {
ThreadPoolService.execute( new Runnable() {
@Override
public void run() {
final List< AppInfo > appInfoList = loadAppsList();
UiThreadHandler.post( new Runnable() {
@Override
public void run() {
if ( mView != null ) {
mView.renderApps( appInfoList );
}
}
} );
}
ThreadPoolService.execute( () -> {
final Map< Integer, List< AppInfo > > appInfoList = loadAppsList();
UiThreadHandler.post( () -> {
if ( mView != null ) {
mView.renderApps( appInfoList );
}
} );
} );
}
private List< AppInfo > loadAppsList() {
private Map< Integer, List< AppInfo > > loadAppsList() {
Logger.i( TAG, "load apps list." );
final List< AppInfo > appInfos = new ArrayList<>();
if ( mAppFilter == null ) {
mAppFilter = new AppFilterImpl( getContext() );
}
final Map< Integer, List< AppInfo > > pagedApps = new HashMap<>();
final PackageManager packageManager = getContext().getPackageManager();
List< PackageInfo > packages = packageManager.getInstalledPackages( 0 );
int counter = 0;
for ( int i = 0; i < packages.size(); ++i ) {
PackageInfo packageInfo = packages.get( i );
//获取非系统应用
if ( ( packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM ) == 0 ) {
String appName = packageInfo.applicationInfo.loadLabel( packageManager ).toString();
String packageName = packageInfo.packageName;
String versionName = packageInfo.versionName;
int versionCode = packageInfo.versionCode;
Drawable appIcon = packageInfo.applicationInfo.loadIcon( packageManager );
AppInfo appInfo = new AppInfo( appName, packageName, versionName, versionCode, appIcon );
appInfos.add( appInfo );
if ( mAppFilter.filter( packageInfo ) ) {
continue;
}
int page = counter++ / AppsConst.TOTAL_SIZE_EACH_PAGE;
if ( !pagedApps.containsKey( page ) ) {
pagedApps.put( page, new ArrayList<>() );
}
String appName = packageInfo.applicationInfo.loadLabel( packageManager ).toString();
String packageName = packageInfo.packageName;
String versionName = packageInfo.versionName;
int versionCode = packageInfo.versionCode;
Drawable appIcon = packageInfo.applicationInfo.loadIcon( packageManager );
AppInfo appInfo = new AppInfo( appName, packageName, versionName, versionCode, appIcon );
pagedApps.get( page ).add( appInfo );
}
return appInfos;
return pagedApps;
}
public void launch( AppInfo appInfo ) {
if ( appInfo == null ) {
return;
}
Intent intent = getContext().getPackageManager().getLaunchIntentForPackage( appInfo.getPackageName() );
if ( intent == null ) {
Logger.e( TAG, "can't launch app: %s", appInfo.toString() );
return;
try {
Intent intent = getContext().getPackageManager().getLaunchIntentForPackage( appInfo.getPackageName() );
intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
getContext().startActivity( intent );
} catch ( Exception e ) {
TipToast.shortTip( R.string.module_apps_str_no_app );
}
intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
getContext().startActivity( intent );
}
}

View File

@@ -4,6 +4,7 @@ import com.mogo.commons.mvp.IView;
import com.mogo.module.apps.model.AppInfo;
import java.util.List;
import java.util.Map;
/**
* @author congtaowang
@@ -18,5 +19,5 @@ public interface AppsView extends IView {
*
* @param appInfos
*/
void renderApps( List< AppInfo > appInfos );
void renderApps( Map< Integer, List< AppInfo > > appInfos );
}