1.Android高仿网易云音乐-启动界面实现和动态权限处理

0.效果


效果图依次为启动界面,第一次显示用户协议对话框,动态获取权限。

系列文章目录导航

目录

1.实现分析

启动基本上没有什么难点,但在真实项目逻辑还是比较多;就是布局,然后显示用户协议对话框,动态处理权限,判断是否显示引导界面,是否显示广告界面等。

2.界面布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".component.splash.activity.SplashActivity">

    <!--banner-->
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="120dp"
        android:src="@drawable/splash_banner" />

    <!--logo-->
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/copyright"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="20dp"
        android:src="@drawable/splash_logo" />

    <!--版权-->
    <TextView
        android:id="@+id/copyright"
        android:textColor="@color/black80"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="30dp"
        android:text="@string/copyright" />
</RelativeLayout>

3.是否显示用户协议对话框

if (DefaultPreferenceUtil.getInstance(getHostActivity()).isAcceptTermsServiceAgreement()) {
    //已经同意了用户协议

    checkPermission();
} else {
    showTermsServiceAgreementDialog();
}

4.自定义协议对话框

继承自DialogFragment自定义对话框。

/**
 * 服务条款和隐私协议对话框
 */
public class TermServiceDialogFragment extends BaseViewModelDialogFragment<FragmentDialogTermServiceBinding> {

    private static final String TAG = "TermServiceDialogFragment";

    private View.OnClickListener onAgreementClickListener;

    public static TermServiceDialogFragment newInstance() {

        Bundle args = new Bundle();

        TermServiceDialogFragment fragment = new TermServiceDialogFragment();
        fragment.setArguments(args);
        return fragment;
    }

    /**
     * 显示对话框
     *
     * @param fragmentManager
     * @param onAgreementClickListener 同意按钮点击回调
     */
    public static void show(FragmentManager fragmentManager, View.OnClickListener onAgreementClickListener) {
        //创建fragment
        TermServiceDialogFragment fragment = newInstance();

        fragment.onAgreementClickListener = onAgreementClickListener;

        //显示
        //TAG只是用来查找Fragment的
        //我们这里不需要查找
        //所以值可以随便写
        fragment.show(fragmentManager, "TermServiceDialogFragment");
    }

    @Override
    protected void initViews() {
        super.initViews();
        //点击弹窗外边不能关闭
        setCancelable(false);

        SuperTextUtil.setLinkColor(binding.content, getActivity().getColor(R.color.link));
    }

    @Override
    protected void initDatum() {
        super.initDatum();

        Spanned content = Html.fromHtml(getString(R.string.term_service_privacy_content));

        //lambda写法,监听器里面只有一个方法才能这样写
        SpannableStringBuilder result = SuperTextUtil.setHtmlLinkClick(content, data -> Log.d(TAG, "onLinkClick: " + data));

        binding.content.setText(result);
    }

    @Override
    protected void initListeners() {
        super.initListeners();
        binding.primary.setOnClickListener(view -> {
            dismiss();
            onAgreementClickListener.onClick(view);
        });

        binding.disagree.setOnClickListener(view -> {
            dismiss();
            SuperProcessUtil.killApp();
        });
    }
}

5.动态处理权限

现在做Android必须要动态处理权限,这里使用第三方框架,推荐再用到的时候才动态请求权限,写法和现在一样。

5.1添加动态权限框架

动态处理权限可以直接使用系统API,添加第三方框架目的是使用更加方便。

//动态处理权限
//https://github.com/permissions-dispatcher/PermissionsDispatcher
implementation "com.github.permissions-dispatcher:permissionsdispatcher:4.8.0"
annotationProcessor "com.github.permissions-dispatcher:permissionsdispatcher-processor:4.8.0"

5.2实现

private void checkPermission() {
    //让动态框架检查是否授权了

    //如果不使用框架就使用系统提供的API检查
    //它内部也是使用系统API检查
    //只是使用框架就更简单了
    SplashActivityPermissionsDispatcher.onPermissionGrantedWithPermissionCheck(this);
}

/**
 * 权限授权了就会调用该方法
 * 请求相机权限目的是扫描二维码,拍照
 */
@NeedsPermission({
        Manifest.permission.CAMERA,
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION
})
void onPermissionGranted() {
    //如果有权限就进入下一步
    prepareNext();
}

/**
 * 显示权限授权对话框
 * 目的是提示用户
 */
@OnShowRationale({
        Manifest.permission.CAMERA,
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION
})
void showRequestPermission(PermissionRequest request) {
    new AlertDialog.Builder(getHostActivity())
            .setMessage(R.string.permission_hint)
            .setPositiveButton(R.string.allow, (dialog, which) -> request.proceed())
            .setNegativeButton(R.string.deny, (dialog, which) -> request.cancel()).show();
}

/**
 * 拒绝了权限调用
 */
@OnPermissionDenied({
        Manifest.permission.CAMERA,
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION
})
void showDenied() {
    //退出应用
    finish();
}

/**
 * 再次获取权限的提示
 */
@OnNeverAskAgain({
        Manifest.permission.CAMERA,
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.ACCESS_COARSE_LOCATION,
        Manifest.permission.ACCESS_FINE_LOCATION
})
void showNeverAsk() {
    //继续请求权限
    checkPermission();
}


/**
 * 授权后回调
 *
 * @param requestCode
 * @param permissions
 * @param grantResults
 */
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    //将授权结果传递到框架
    SplashActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
}

6.界面跳转

private void postNext() {
    binding.copyright.postDelayed(new Runnable() {
        @Override
        public void run() {
            next();
        }
    }, Config.SPLASH_DEFAULT_DELAY_TIME);

}

private void next() {
    //获取意图的目的是,因为启动该界面的时候,可能携带一些数据
    //需要在主界面处理
    Intent intent = new Intent();

    Intent oldIntent = getIntent();
    IntentUtil.cloneIntent(oldIntent, intent);

	//if (sp.isLogin()) {
		//intent.setClass(getHostActivity(), AdActivity.class);
	//} else {
    	intent.setClass(getHostActivity(), MainActivity.class);
	//}

    startActivity(intent);

    //关闭当前界面
    finish();

    //禁用启动动画
    overridePendingTransition(0, 0);
}

7.总结

到这里启动界面相关逻辑就实现完成了,总体来说还是比较简单的。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱学啊教育官方

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值