精华内容
下载资源
问答
  • 不是点了某一个按钮之后发生的闪退,而是app一打开就闪退。 三个可能原因: 1.在onCreate函数以外的地方使用“findViewById” 正确的方式是如下图这样: 要先在onCreate函数中初始化布局才能实例化按钮控件。 2.有...

    不是点了某一个按钮之后发生的闪退,而是app一打开就闪退。
    三个可能原因:

    1.在onCreate函数以外的地方使用“findViewById”

    正确的方式是如下图这样:
    在这里插入图片描述
    要先在onCreate函数中初始化布局才能实例化按钮控件。

    2.有不止一个Android Studio窗口在运行

    关闭其他不需要的窗口。这个是在StackOverFlow看到的原因,但是事实证明我并不是因为这个…

    3.布局文件出问题,文件头或控件都有可能,一个一个排查

    首先把控件全删光,运行试试还闪退吗,如果是的话就是文件头的问题。
    如果没有问题则一个一个删除控件试。但是最后发现我的问题十分奇怪。
    原因如下图,textSize以及layout_width以及layout_weight都不可以使用@string/…这样的形式,改成数字+dp就好了…
    在这里插入图片描述

    展开全文
  • Android安卓证书生成和签名查看

    千次阅读 2019-08-19 15:29:55
    Android 使用证书作为标识应用程序作者的一种方式使用签名来区分不同的APP 签名分为调试模式下的证书和公布模式下的证书 调试模式下的证书只能用作真机调试,不安全 公布模式下的证书才能发布到应用商店供其他...

    概述

    Android 使用证书作为标识应用程序作者的一种方式,使用签名来区分不同的APP

    签名分为调试模式下的证书和公布模式下的证书

    调试模式下的证书只能用作真机调试,不安全

    公布模式下的证书才能发布到应用商店供其他使用者下载

    这里生成的是调试模式下的证书

    步骤

    1. 证书生成需要JDK,未安装要自行安装

    2.打开命令行(cmd),开始按钮右键--运行

    3.进入 JDK下的bin目录,默认是 C:\Program Files\Java\jdk1.8.0_181\bin

    cd C:\Program Files\Java\jdk1.8.0_181\bin

    4.生成证书 ,-keystore 后是生成证书的路径和名称,我放在桌面,名字为 debug.keystore

    keytool -genkey -v -keystore C:\Users\admin\Desktop\debug.keystore -alias 
    androiddebugkey -keyalg RSA -validity 10000

    点击后会有密码,名称等的输入,最后还有密码确认

    此时在桌面已经生成相应证书

    5.查看签名

    keytool -list -v -keystore  C:\Users\admin\Desktop\debug.keystore

    输入上面自己设置的密码

    展开全文
  • 其他页面跳转到带有微信二维码识别的页面(不是直接打开该页面) ios版本的微信(实测版本6.5.19) 结果: 二维码长按无法识别,刷新页面后恢复正常,安卓下正常。 解决方案: 1. 进入该页面的方式使用...

    spa(单页应用,vue)中,使用history模式时,微信长按识别二维码在ios下失效的问题。

     

    触发条件:

    spa单页应用;

    路由模式 history

    从其他页面跳转到带有微信二维码识别的页面(不是直接打开该页面)

    ios版本的微信(实测版本6.5.19)

     

    结果:

    二维码长按无法识别,刷新页面后恢复正常,安卓下正常。

     

    解决方案:

    1. 进入该页面的方式不使用路由跳转,而改为 <a href="xxx">目标二维码页面</a>的方式;

    2. 在beforeCreated中重载该页面(例如增加&_r=1);

    3. 改为hash模式恢复正常。

     

    猜想:

    微信的长按识别功能,也需要URL认证,但是ios版本的微信,应该是尚未实现根据popstate状态对微信的接口进行监听注册,导致长按识别的接口在该情况下无法识别单页应用修改的路由,从而调用接口失败,而刷新后接口会重新注册当前的URL(而不是通过pushstate改变的URL),因此导致该bug,后续有望修复。毕竟friendly URL 还是有些用处的,特别是分享等场景。

    转载于:https://www.cnblogs.com/aleafo/p/7814258.html

    展开全文
  • 业务场景以微信视频通话为例,在视频通话时,我们打开其他应用或点击Home键退出时或点击缩放图标,悬浮窗会显示在其他应用之上,给人的假象是通话页面变小了,点击悬浮窗回到通过页面,悬浮窗消失。退出通...

    前言

    我们大多数在两种情况下可以看到悬浮窗,一个是视频通话时的悬浮窗,另一个是360卫士的悬浮球,实现此功能的方式比较多,这里以视频通话悬浮窗中的需求为例。编码实现使用Kotlin。Java版本留言邮箱即可。

    业务场景

    以微信视频通话为例,在视频通话时,我们打开其他应用或点击Home键退出时或点击缩放图标,悬浮窗会显示在其他应用之上,给人的假象是通话页面变小了,点击悬浮窗回到通过页面,悬浮窗消失。退出通话页面悬浮窗消失。

    业务场景技术分析

    在编码之前,我们必须将流程整理好,这样更有利于编码的实现。实现一个功能如果需要10分钟,思考的时间是7分钟,编码占用的时间只是三分钟。

    1.悬浮窗可以显示在其他应用或launchers之上,这个肯定需要悬浮窗权限,而悬浮窗权限属于特殊权限,所以只能通过引导用户去打开无法像危险权限那样直接申请。可以做到后台显示则说明悬浮窗是一个Service。

    2.通话页面隐藏时悬浮窗显示,通话页面显示时悬浮窗隐藏,可以看出悬浮窗和Activity的生命周期相关联,所以悬浮窗的Service和通话页面的Activity是通过bind去绑定的。

    3.既然Service和Activity是通过bind去绑定的,说明当悬浮窗显示的时候,通话Activity虽然不可见但仍在运行。

    结合上述技术问题分析,我们倒叙一一通过编码实现

    悬浮窗实现方案

    实现效果

    准备工作

    首先我们新建一个项目,项目中有两个Activity,我们在第二个Activity编写通话模拟页面。在第二个页面的原因我们后面会讲到。

    如何将acitivity置于后台

    其实很简单,我们调用一个方法即可

    moveTaskToBack(true);

    这个方法的含义就是将当前的任务战置于后台,so,为什么我要在第二个Activity中实现的原因之一,因为默认的Activity的启动模式是标准模式,而上面方法会将任务栈置于后台而不是一个单独的Activity,所以我们为了显示悬浮窗时不影响操作软件的其他功能,我们要将通话页面的Activity设置为singleInstance,这样当调用上面方法的时候只是将通话页面所在的Activity栈置于后台,如果你还不了解启动模式可以移步至上一篇文章:Activity的启动模式。

    我们现在在右上方的点击事件中添加上述代码,可以看到通话页面的Activity的已经在后台运行了。

    判断是否有悬浮窗权限

    点击左上角图标时,我们要先判断当前app是否有悬浮窗权限,首先我们在配置文件中添加,悬浮窗的权限。

    (很多文章标题都是悬浮窗如何绕过权限,什么设置类型为TOAST或者PHONE,我想说不可能的事,TOAST类型的虽然部分机型可以显示但是就是一个普通的TOSAT会自动消失)

    那么我们如何判断是否有悬浮窗权限呢,这一块不同厂商处理方案可能不一样,这里我们用一种通用的处理方案,测试表明除了(vivo部分)无效,其他多数机型都ok。并且vivo部分机型微信通话也不会弹出提示(这我就放心了~)

    fun zoom(v: View) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

    if (!Settings.canDrawOverlays(this)) {

    Toast.makeText(this, "当前无权限,请授权", Toast.LENGTH_SHORT)

    GlobalDialogSingle(this, "", "当前未获取悬浮窗权限", "去开启", DialogInterface.OnClickListener { dialog, which ->

    dialog.dismiss()

    startActivityForResult(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + packageName)), 0)

    }).show()

    } else {

    moveTaskToBack(true)

    val intent = Intent(this@Main2Activity, FloatWinfowServices::class.java)

    hasBind = bindService(intent, mVideoServiceConnection, Context.BIND_AUTO_CREATE)

    }

    }

    }

    我们通过Settings.canDrawOverlays(this)来判断当前应用是否有悬浮窗权限,如果没有,我们弹窗提示,通过

    startActivityForResult(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + packageName)), 0)

    跳转到开启悬浮窗权限页面。如果悬浮窗权限已开启,直接将当前任务栈置于后台,开启服务即可。

    其实回调方法,并没有直接告诉我们是否授权成功,所以我们需要在回调中再次判断

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {

    if (requestCode == 0) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

    if (!Settings.canDrawOverlays(this)) {

    Toast.makeText(this, "授权失败", Toast.LENGTH_SHORT).show()

    } else {

    Handler().postDelayed({

    val intent = Intent(this@Main2Activity, FloatWinfowServices::class.java)

    intent.putExtra("rangeTime", rangeTime)

    hasBind = bindService(intent, mVideoServiceConnection, Context.BIND_AUTO_CREATE)

    moveTaskToBack(true)

    }, 1000)

    }

    }

    }

    }

    这里我们可以看到回调中延迟了1秒,因为测试发现某些机型反应“过快”,收到回调的时候还以为没有授权成功,其实已经成功了。

    绑定Service我们需要一个ServiceConnection对象

    internal var mVideoServiceConnection: ServiceConnection = object : ServiceConnection {

    override fun onServiceConnected(name: ComponentName, service: IBinder) {

    // 获取服务的操作对象

    val binder = service as FloatWinfowServices.MyBinder

    binder.service

    }

    override fun onServiceDisconnected(name: ComponentName) {}

    }

    Main2Activity的完整代码如下所示:

    /**

    * @author Huanglinqing

    */

    class Main2Activity : AppCompatActivity() {

    private val chronometer: Chronometer? = null

    private var hasBind = false

    private val rangeTime: Long = 0

    override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState)

    setContentView(R.layout.activity_main2)

    }

    fun zoom(v: View) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

    if (!Settings.canDrawOverlays(this)) {

    Toast.makeText(this, "当前无权限,请授权", Toast.LENGTH_SHORT)

    GlobalDialogSingle(this, "", "当前未获取悬浮窗权限", "去开启", DialogInterface.OnClickListener { dialog, which ->

    dialog.dismiss()

    startActivityForResult(Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + packageName)), 0)

    }).show()

    } else {

    moveTaskToBack(true)

    val intent = Intent(this@Main2Activity, FloatWinfowServices::class.java)

    hasBind = bindService(intent, mVideoServiceConnection, Context.BIND_AUTO_CREATE)

    }

    }

    }

    internal var mVideoServiceConnection: ServiceConnection = object : ServiceConnection {

    override fun onServiceConnected(name: ComponentName, service: IBinder) {

    // 获取服务的操作对象

    val binder = service as FloatWinfowServices.MyBinder

    binder.service

    }

    override fun onServiceDisconnected(name: ComponentName) {}

    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {

    if (requestCode == 0) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

    if (!Settings.canDrawOverlays(this)) {

    Toast.makeText(this, "授权失败", Toast.LENGTH_SHORT).show()

    } else {

    Handler().postDelayed({

    val intent = Intent(this@Main2Activity, FloatWinfowServices::class.java)

    intent.putExtra("rangeTime", rangeTime)

    hasBind = bindService(intent, mVideoServiceConnection, Context.BIND_AUTO_CREATE)

    moveTaskToBack(true)

    }, 1000)

    }

    }

    }

    }

    override fun onRestart() {

    super.onRestart()

    Log.d("RemoteView", "重新显示了")

    //不显示悬浮框

    if (hasBind) {

    unbindService(mVideoServiceConnection)

    hasBind = false

    }

    }

    override fun onNewIntent(intent: Intent) {

    super.onNewIntent(intent)

    }

    override fun onDestroy() {

    super.onDestroy()

    }

    }

    新建悬浮窗Service

    新建悬浮窗Service FloatWinfowServices,因为我们使用的BindService,我们在onBind方法中初始化service中的布局

    override fun onBind(intent: Intent): IBinder? {

    initWindow()

    //悬浮框点击事件的处理

    initFloating()

    return MyBinder()

    }

    service中我们通过WindowManager来添加一个布局显示。

    /**

    * 初始化窗口

    */

    private fun initWindow() {

    winManager = application.getSystemService(Context.WINDOW_SERVICE) as WindowManager

    //设置好悬浮窗的参数

    wmParams = params

    // 悬浮窗默认显示以左上角为起始坐标

    wmParams!!.gravity = Gravity.LEFT or Gravity.TOP

    //悬浮窗的开始位置,因为设置的是从左上角开始,所以屏幕左上角是x=0;y=0

    wmParams!!.x = winManager!!.defaultDisplay.width

    wmParams!!.y = 210

    //得到容器,通过这个inflater来获得悬浮窗控件

    inflater = LayoutInflater.from(applicationContext)

    // 获取浮动窗口视图所在布局

    mFloatingLayout = inflater!!.inflate(R.layout.remoteview, null)

    // 添加悬浮窗的视图

    winManager!!.addView(mFloatingLayout, wmParams)

    }

    悬浮窗的参数主要设置悬浮窗的类型为

    WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY

    8.0 以下可设置为:

    wmParams!!.type = WindowManager.LayoutParams.TYPE_PHONE

    代码如下所示:

    private //设置window type 下面变量2002是在屏幕区域显示,2003则可以显示在状态栏之上

    //设置可以显示在状态栏上

    //设置悬浮窗口长宽数据

    val params: WindowManager.LayoutParams

    get() {

    wmParams = WindowManager.LayoutParams()

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

    wmParams!!.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY

    } else {

    wmParams!!.type = WindowManager.LayoutParams.TYPE_PHONE

    }

    wmParams!!.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or

    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR or

    WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH

    wmParams!!.width = WindowManager.LayoutParams.WRAP_CONTENT

    wmParams!!.height = WindowManager.LayoutParams.WRAP_CONTENT

    return wmParams

    }

    当点击悬浮窗的时候回到Activity2页面,并且悬浮窗消失,所以我们只需要给悬浮窗添加点击事件

    linearLayout!!.setOnClickListener { startActivity(Intent(this@FloatWinfowServices, Main2Activity::class.java)) }

    当Service走到onDestory的时候将view移除,对于Activity2页面来说 当onResume的时候 解绑Service,当onstop的时候 绑定Service。

    从效果图中我们可以看到悬浮窗可以拖拽的,所以还要设置触摸事件,当移动距离超过某个值的时候让onTouch消费事件,这样就不会触发点击事件了。这个算是view比较基础的知识,相信大家都明白了。

    //开始触控的坐标,移动时的坐标(相对于屏幕左上角的坐标)

    private var mTouchStartX: Int = 0

    private var mTouchStartY: Int = 0

    private var mTouchCurrentX: Int = 0

    private var mTouchCurrentY: Int = 0

    //开始时的坐标和结束时的坐标(相对于自身控件的坐标)

    private var mStartX: Int = 0

    private var mStartY: Int = 0

    private var mStopX: Int = 0

    private var mStopY: Int = 0

    //判断悬浮窗口是否移动,这里做个标记,防止移动后松手触发了点击事件

    private var isMove: Boolean = false

    private inner class FloatingListener : View.OnTouchListener {

    override fun onTouch(v: View, event: MotionEvent): Boolean {

    val action = event.action

    when (action) {

    MotionEvent.ACTION_DOWN -> {

    isMove = false

    mTouchStartX = event.rawX.toInt()

    mTouchStartY = event.rawY.toInt()

    mStartX = event.x.toInt()

    mStartY = event.y.toInt()

    }

    MotionEvent.ACTION_MOVE -> {

    mTouchCurrentX = event.rawX.toInt()

    mTouchCurrentY = event.rawY.toInt()

    wmParams!!.x += mTouchCurrentX - mTouchStartX

    wmParams!!.y += mTouchCurrentY - mTouchStartY

    winManager!!.updateViewLayout(mFloatingLayout, wmParams)

    mTouchStartX = mTouchCurrentX

    mTouchStartY = mTouchCurrentY

    }

    MotionEvent.ACTION_UP -> {

    mStopX = event.x.toInt()

    mStopY = event.y.toInt()

    if (Math.abs(mStartX - mStopX) >= 1 || Math.abs(mStartY - mStopY) >= 1) {

    isMove = true

    }

    }

    else -> {

    }

    }

    //如果是移动事件不触发OnClick事件,防止移动的时候一放手形成点击事件

    return isMove

    }

    }

    FloatWinfowServices所有代码如下所示:

    class FloatWinfowServices : Service() {

    private var winManager: WindowManager? = null

    private var wmParams: WindowManager.LayoutParams? = null

    private var inflater: LayoutInflater? = null

    //浮动布局

    private var mFloatingLayout: View? = null

    private var linearLayout: LinearLayout? = null

    private var chronometer: Chronometer? = null

    override fun onBind(intent: Intent): IBinder? {

    initWindow()

    //悬浮框点击事件的处理

    initFloating()

    return MyBinder()

    }

    inner class MyBinder : Binder() {

    val service: FloatWinfowServices

    get() = this@FloatWinfowServices

    }

    override fun onCreate() {

    super.onCreate()

    }

    /**

    * 悬浮窗点击事件

    */

    private fun initFloating() {

    linearLayout = mFloatingLayout!!.findViewById(R.id.line1)

    linearLayout!!.setOnClickListener { startActivity(Intent(this@FloatWinfowServices, Main2Activity::class.java)) }

    //悬浮框触摸事件,设置悬浮框可拖动

    linearLayout!!.setOnTouchListener(FloatingListener())

    }

    //开始触控的坐标,移动时的坐标(相对于屏幕左上角的坐标)

    private var mTouchStartX: Int = 0

    private var mTouchStartY: Int = 0

    private var mTouchCurrentX: Int = 0

    private var mTouchCurrentY: Int = 0

    //开始时的坐标和结束时的坐标(相对于自身控件的坐标)

    private var mStartX: Int = 0

    private var mStartY: Int = 0

    private var mStopX: Int = 0

    private var mStopY: Int = 0

    //判断悬浮窗口是否移动,这里做个标记,防止移动后松手触发了点击事件

    private var isMove: Boolean = false

    private inner class FloatingListener : View.OnTouchListener {

    override fun onTouch(v: View, event: MotionEvent): Boolean {

    val action = event.action

    when (action) {

    MotionEvent.ACTION_DOWN -> {

    isMove = false

    mTouchStartX = event.rawX.toInt()

    mTouchStartY = event.rawY.toInt()

    mStartX = event.x.toInt()

    mStartY = event.y.toInt()

    }

    MotionEvent.ACTION_MOVE -> {

    mTouchCurrentX = event.rawX.toInt()

    mTouchCurrentY = event.rawY.toInt()

    wmParams!!.x += mTouchCurrentX - mTouchStartX

    wmParams!!.y += mTouchCurrentY - mTouchStartY

    winManager!!.updateViewLayout(mFloatingLayout, wmParams)

    mTouchStartX = mTouchCurrentX

    mTouchStartY = mTouchCurrentY

    }

    MotionEvent.ACTION_UP -> {

    mStopX = event.x.toInt()

    mStopY = event.y.toInt()

    if (Math.abs(mStartX - mStopX) >= 1 || Math.abs(mStartY - mStopY) >= 1) {

    isMove = true

    }

    }

    else -> {

    }

    }

    //如果是移动事件不触发OnClick事件,防止移动的时候一放手形成点击事件

    return isMove

    }

    }

    /**

    * 初始化窗口

    */

    private fun initWindow() {

    winManager = application.getSystemService(Context.WINDOW_SERVICE) as WindowManager

    //设置好悬浮窗的参数

    wmParams = params

    // 悬浮窗默认显示以左上角为起始坐标

    wmParams!!.gravity = Gravity.LEFT or Gravity.TOP

    //悬浮窗的开始位置,因为设置的是从左上角开始,所以屏幕左上角是x=0;y=0

    wmParams!!.x = winManager!!.defaultDisplay.width

    wmParams!!.y = 210

    //得到容器,通过这个inflater来获得悬浮窗控件

    inflater = LayoutInflater.from(applicationContext)

    // 获取浮动窗口视图所在布局

    mFloatingLayout = inflater!!.inflate(R.layout.remoteview, null)

    chronometer = mFloatingLayout!!.findViewById(R.id.chronometer)

    chronometer!!.start()

    // 添加悬浮窗的视图

    winManager!!.addView(mFloatingLayout, wmParams)

    }

    private //设置window type 下面变量2002是在屏幕区域显示,2003则可以显示在状态栏之上

    //设置可以显示在状态栏上

    //设置悬浮窗口长宽数据

    val params: WindowManager.LayoutParams

    get() {

    wmParams = WindowManager.LayoutParams()

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

    wmParams!!.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY

    } else {

    wmParams!!.type = WindowManager.LayoutParams.TYPE_PHONE

    }

    wmParams!!.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or

    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR or

    WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH

    wmParams!!.width = WindowManager.LayoutParams.WRAP_CONTENT

    wmParams!!.height = WindowManager.LayoutParams.WRAP_CONTENT

    return wmParams

    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {

    return super.onStartCommand(intent, flags, startId)

    }

    override fun onDestroy() {

    super.onDestroy()

    winManager!!.removeView(mFloatingLayout)

    }

    }

    实际应用中需要考虑的一些其他问题

    在使用使用的过程中,我们肯定会遇到其他问题:

    1.用户使用过程中,可能会直接按Home键,这个时候如何提示呢?

    产生问题原因:因为用户按Home键之后,开发者无法重写Home键逻辑,此时应用不在前台运行,无法弹窗提醒,此时用户点击APP图标进入的是第一个栈,这个时候用户就没有进入通话页面的入口了。

    解决方案:

    第一种解决方案 我们可以仿照微信那样去做,就是在整个通话过程中开启一个前台通知,用户点击通知时进入通话页面。

    第二种解决方案 就是检测应用是否在前台,当通话页面在运行的时候,并且应用重新回到前台,我们广播到其他页面,提示权限引导即可。

    2.用户在通话页面(singleInstance模式),点击Home键

    应用在后台运行的时候,通话结束,Activity被finish,此时从任务程序中切回应用你会发现打开的竟然是通话页面!

    这个问题简单的说就是,如果你在通话页面呼叫某人,通话过程中按Home键,然后电话挂断,此时你从任务程序中切回应用,会再次呼叫这个人,也就是这种状态下重新回到了onCreate方法。

    问题产生原因:

    1.因为通话页面是singleInstance模式,此时有两个任务栈,按Home键后再从任务程序中切回,此时应用只保留了第二个任务栈,已经失去了和第一个任务栈的关系,finish之后无法在回到第一个任务栈。

    解决方案:

    1.(不推荐)通话页面不使用singleInstance模式,这种情况下,在通话过程中无法操作软件的其他功能,一般都不采取。

    2.(我目前的解决方案)设置一个标记位,标记当前是否在通话,在onCreate中如果通话已经结束了,跳转到一个过渡页面(标准模式),过渡页面中finish,就可以了,添加过渡页面的原因是我们不知道上一个页面是哪里,因为我们收到来电可能是任意页面,我们我们在过渡页面finsh之后,就再次回到了第一个任务栈。

    总结

    以上所述是小编给大家介绍的Android 实现悬浮窗功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

    如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

    展开全文
  • 这个不是说桌面应用程序开发比其他开发很简单。总之作为桌面应用程序开发者,我们已经有能力按照我们的想法创造出各种应用程序。包括我自己,因为我也是从做桌面程序开始的。一方面,我们已经使得桌面程序更容易的与...
  • 使用的手机是三星A9,其他安卓手机方式也相同,电脑是win 10 系统。 第一步首先打开手机的开发者模式,确保usb调试和通过usb验证应用程序保持打开状态,如图所示: 第二步,最好是电脑和安卓手机都连接了...
  • 1、苹果用户打开后要么自动调起App Store下载(前提是你的应用在苹果商店上架了);要么是去Safari下载。 2、安卓用户打开链接后要么直接下载,要么前往手机默认浏览器下载。 以上是最好的实现方式,该实现方式...
  • 由于Aria涉及到文件和网络的操作,因此需要你在manifest文件中添加以下权限,如果你希望在6.0以上的系统中使用Aria,那么你需要动态向安卓系统申请文件系统读写权限,如何使用安卓系统权限 <uses-permission ...
  • 如何进行手机导航设置

    千次阅读 2012-12-21 17:14:31
    安卓手机都基本配置了GPS模块,可以让大家便捷的使用地图导航功能。安卓手机的导航设置比较简单,...如果手机不带有谷歌地图的话,可以使用其他第三方的地图应用 本文固定链接: http://www.chenjiayu.cn/arch
  • 1.标准版 2014/07/07| 版本号:6.03.0707.2411 美化安装、卸载界面 ... 像手机用户使用应用一样,打开一个毫无心理成本的桌面应用,让老用户的 粘度更高。 4、暴风加号市场_加号市场下载标准版软件截图:
  • 去广告版文ES文件浏览器,ES文件浏览器是一个能管理安卓设备本地、局域网共享、远程FTP、蓝牙设备和云存储的系统工具类移动软件。全球主动下载超过2亿次,安卓文件...应用备份、安装、卸载和快捷方式 Root浏览、权限修改
  • 就是使用查看元素方式,获取到通知栏里面的内容 (3)返回应用使用往上滑动,会收起通知栏。 或者按返回键的方法。 (4)按键操作: driver.press_keycode(4) 其中返回的按钮code是4,所以输入code就会做相应操作...
  • Packet Capture手机端app抓包工具

    千次阅读 2020-10-18 17:40:14
    无意间看到一个叫Packet Capture,...拖到模拟其上,打开该app,安装证书,不安装会导致,其他应用对改中间app不可信,从而造成抓包失败。 配置信息 安装成功后,有两种抓包方式,左边绿色箭头表示抓取某个应用的包,
  • 实现原理: 当收到支付宝、微信、实时收款信息,客户端会实时通知服务器收款金额和方式,服务器收到有效期订单金额后处理订单状态,使用随机减免的方式区分订单(5分钟订单有效期内有相同金额的订单会随机减免0.01 -...
  • 尽我所知,除了文中特别加以标注和致谢的地方外,论文中不包含其他人已经发表或撰写过的研究成果,也不包含为获得东南大学或其它教育机构的学位或证书而使用过的材料。与我一同工作的同志对本研究所做的任何贡献均已...
  • 实现一键打开支付宝APP支付(支持安卓浏览器、IOS应用,不支持微信中打开)(支付宝已封禁) 实现移动端支付方案 支持H5、APP、小程序 轻松支持多账户收款 赶快使用手机扫码体验吧 注:v3.1源码(含详细文档)...
  • 其他语言开发Android应用工具 传感器模拟工具 Android串口开发工具 图片尺寸处理工具 图片压缩工具 资源清理工具 px和dp转换/计算工具 Java To iOS JSON/XML转换为POJO Class工具 Java DAO Generate工具 Chrome插件...
  • 您如果未经授权将VirtualApp用于内部使用、商业牟利或上传应用市场,我们将取证后报警(侵犯著作权罪)或起诉,这将对您所属公司造成刑事责任及法律诉讼,影响到您公司的商誉和投资。购买商业授权为您节省大量开发、...
  • 本资源是以压缩包的形式的, 里面是一个 “TXT”的文档, 文档中 有“百度云” 分享的链接, 这本书太大,上传不上来,所以以这样的方式上传。永久有效, 有问题的话,可以联系我,里面留有本人的QQ。 作者: Unity ...
  • 前缀名从而在同一个数据库中安装多种应用而不产生冲突。 三、 您的 MySQL 数据库账号应当拥有 CREATE、DROP、ALTER 等执行权限,同时文件空间需不低于 100M,数据库 空间不低于5M,通常您的虚拟空间都会满足这个...
  • 金盾2019破解版

    2016-12-22 11:15:13
    只需加密一次即可实现跨平台播放,支持手机和平板,支持Windows、安卓、苹果IOS、Mac; 支持各种视频的高速编码加密与高速解码播放,加密后的文件自带解码器和播放器;可以加 密各种视频音频格式文件(wmv,avi,mpg,...
  • 本地设备采集到的数据实时上传到云端,以便手机APP或者web等其他方式提取。 支持两种数据源,一种是串口和网络通过协议采集设备数据,一种是数据库采集。数据库采集模式可以作为通用的系统使用。 自带设备模拟工具,...
  • 【沙盒浏览】 App 内部文件浏览的功能,支持删除和预览, 并且能通过 AirDrop 或者其他分享方式上传到 PC 中,进行更加细致的操作; 【MockGPS】 App 能定位到全国各地,支持地图地位和手动输入经纬度; 【H5任意门...
  • 主版面(这里)是给普通用户用的,打开即用,无需命令行或编程基础 1. 为什么有这个表 作为开发者其实比较好奇其他人在做什么业余项目(不管目的是做到盈利/玩票/试试看) 所以特意建了这个库。欢迎各位开发者把自己的...
  • 【沙盒浏览】 App 内部文件浏览的功能,支持删除和预览, 并且能通过 AirDrop 或者其他分享方式上传到 PC 中,进行更加细致的操作; 【MockGPS】 App 能定位到全国各地,支持地图地位和手动输入经纬度; 【H5任意门...
  • 不知道是因为最近kaihui还是怎么的,打开android sdk官方网站特别的慢,想下载最新版本的platform几乎变成不可能完成的任务,不知道为什么Google不像Apache那样在各国设立镜像站。为了预防今后再出现这样的情况,...
  • 使用方法: 2.0.0以后,放弃了support库,请使用AndroidX implementation 'com.easyandroid:easytools:2.0.3' 然后,在自己的Application中调用Utils.init(this);进行初始化 添加混淆: -keep class ...
  • Windows系统可以使用命令在桌面创建一个快捷方式 weditor --shortcut 命令行直接输入 weditor 会自动打开浏览器,输入设备的ip或者序列号,点击Connect即可。 具体参考文章:浅谈自动化测试工具python-uiautomator2...
  • 本项目仅做学习交流使用,API数据内容所有权归原作公司所有,请勿用于其他用途。 可以先下载apk运行到手机上看看效果,下载链接地址: apk如下所示 组件化apk的下载地址 02.项目运行 运行环境要求 Android ...
  • 创建数组可以使用构造函数的方式也可以使用字面量的形式,另外可以使用concat从一个数组中复制一个副本出来。数组本身提供了很多方法让开发者使用来操作数组。 - length 数组的长度 - toString 可以返回一个以...

空空如也

空空如也

1 2
收藏数 30
精华内容 12
关键字:

安卓使用其他应用打开方式