c语言怎么获取红米手机的点击位置

c语言怎么获取红米手机的点击位置,第1张

1、在C语言中调用Java类:需要使用JNI(JavaNativeInterface)机制,将C语言与Java语言连接起来,实现C语言调用Java类的功能。

2、获取Activity对象:在C语言中,需要通过JNI机制获取当前正在运行的Activity对象,以便后续进行UI *** 作。

3、获取触摸事件:可以通过Activity对象获取View对象,并注册触摸事件监听器。当用户触摸屏幕时,触摸事件监听器会接收到相应的事件,包括触摸位置、触摸时间等信息。

4、处理触摸事件:在处理触摸事件时,需要先判断事件类型,如果是点击事件,则可以通过事件对象获取点击位置的X坐标和Y坐标,从而获得红米手机的点击位置。

activity可以 *** 作service了,我们还需要service能 *** 作activity。

我觉得可以有3中方式:

1直接把activity传给service,service通过activity实例随便 *** 作activity

2使用接口回调方式,activity实现相应的接口,service通过接口进行回调,比较灵活

3使用广播

使用广播是比较常见的方式,我们就不具体讲解了,下面我们介绍前面2中方法,具体看代码,用service更新seekbar。

我们的activity代码:

[html] view plain copy

package comhckbindservice;

import androidappActivity;

import androidcontentComponentName;

import androidcontentIntent;

import androidcontentServiceConnection;

import androidosBundle;

import androidosIBinder;

import androidutilLog;

import androidviewView;

import androidwidgetSeekBar;

import androidwidgetToast;

import comhckbindserviceMyServiceMyBuild;

public class MainActivity extends Activity {

private MyService myService; //我们自己的service

private SeekBar pBar; //模拟service更新进度条

private ConnectionService connectionService;

@Override

protected void onCreate(Bundle savedInstanceState) {

superonCreate(savedInstanceState);

setContentView(Rlayoutmain);

pBar = (SeekBar) findViewById(Ridseekbar);

connectionService=new ConnectionService();

}

public void startService(View view) { //绑定service

bindService(new Intent(this,MyServiceclass), connectionService, 1);

}

/

@author Administrator

实现service接口,用于service绑定时候,回调

/

class ConnectionService implements ServiceConnection

{

@Override

public void onServiceConnected(ComponentName name, IBinder service) {

myService=((MyBuild)service)getMyService(); //获取Myservice对象

/

直接把当前对象传给service,这样service就可以随心所欲的调用本activity的各种可用方法

/

myServicesetMainActivity(MainActivitythis); //把当前对象传递给myservice

/

使用一个接口来实现回调,这样比上面方法更加灵活,推荐

/

// myServicesetOnProgressBarListener(new UpdateProgressListener() {

//

// @Override

// public void updateBar(int size) {

// updateBar(size);

// }

// });

}

@Override

public void onServiceDisconnected(ComponentName name) {

}

}

/

@param size

更新seekbar

/

public void updateBar(int size)

{

pBarsetProgress(size);

}

/

@param view

开始更新seekbar

/

public void startBar(View view) {

if (myService==null) {

ToastmakeText(this, "请先开始service", ToastLENGTH_LONG)show();

}

else {

myServicestartUpdateProgress();

}

}

/

@param view

停止更新seekbar

/

public void stopBar(View view) {

if (myService==null) {

ToastmakeText(this, "更新没有开始", ToastLENGTH_LONG)show();

}

else {

myServicestopUpdateProgress();

}

}

/

@param view

停止service

/

public void stopService(View view) {

myService=null;

unbindService(connectionService);

}

@Override

protected void onDestroy() {

superonDestroy();

try {

unbindService(connectionService);

} catch (Exception e) {

}

}

}

重要代码是onServiceConnected回调方法里面

myService=((MyBuild)service)getMyService(); //获取Myservice对象

获取service对象后,我们想怎么 *** 作它都行了,比如上面的,把activity实例直接通过它的方法传递过去,便于

service调用activity的各种方法。或者,设置传递一个回调接口对象过去,用户回调

service代码:

[html] view plain copy

package comhckbindservice;

import androidappService;

import androidcontentIntent;

import androidosBinder;

import androidosHandler;

import androidosIBinder;

import androidutilLog;

public class MyService extends Service{

private int size=0;

private UpdateProgress updateProgress;

private final long TIME=2000;

private boolean isUpdate=true;

private MainActivity activity;

private UpdateProgressListener listener;

@Override

public IBinder onBind(Intent intent) {

return new MyBuild();

}

@Override

public void onCreate() {

superonCreate();

updateProgress=new UpdateProgress();

}

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

return superonStartCommand(intent, flags, startId);

}

/

@author Administrator

线程用来改变seekbar进度的大小

/

class UpdateProgress implements Runnable

{

@Override

public void run() {

if (isUpdate) {

size+=10;

if (size>100) {

size=0;

}

handlersendEmptyMessage(0);

}

}

}

/

调用更新相应方法,更新进度条

/

Handler handler=new Handler()

{

public void handleMessage(androidosMessage msg) {

/

直接调用activity对象里面的方法

/

if (activity!=null) {

activityupdateBar(size);

}

/

使用接口回调

/

// if (listener!=null) {

// listenerupdateBar(size);

// }

handlerpostDelayed(updateProgress, TIME);

};

};

/

停止更新

/

public void stopUpdateProgress()

{

isUpdate=false;

}

/

开启更新

/

public void startUpdateProgress()

{

if (!isUpdate) {

handlerpost(updateProgress);

}

isUpdate=true;

}

public void onDestroy() {

isUpdate=false;

};

/

@param activity

初始化MainActivity对象

/

public void setMainActivity(MainActivity activity)

{

thisactivity=activity;

}

/

@param listener

初始化UpdateProgressListener对象

/

public void setOnProgressBarListener(UpdateProgressListener listener)

{

thislistener=listener;

}

/

@author Administrator

使用类部类,返回当前service的实例,用于activity,调用service的各种方法

/

class MyBuild extends Binder

{

public MyService getMyService()

{

return MyServicethis;

}

}

}

service里面最重要的就是,最下面我们的MyBuild类部类了,通过它的getMyService方法,获取service的实例

该类的实例实在onBind时候,我们返回给activity的。

接口:

[html] view plain copy

package comhckbindservice;

public interface UpdateProgressListener {

public void updateBar(int size);

}

一个简单接口,用于service回调activity

上面是使用 bindService来启动service的,那么如果我们使用startService启动service时候,上面的办法就不行了。

因为onBind不会执行,我们获取不到IBinder实例。这个时候,我们可以使用设计模式的观察者模式来处理。

在Android中,应用程序的版本号是在AndroidManifestxml文件中进行配置的,而PackageInfo类则封装了从该配置文件中获取的所有信息,描述了包内容的整体信息,因此,可以使用PackageInfo对象的versionName属性获取应用的版本号。要怎么获取PackageInfo对象呢?可以通过PackageManager对象来获取。PackageManager是一个检索当前已安装在设备上的相关应用程序包的各种信息的类。PackageManager对象中的getPackageInfo方法可以获取PackageInfo对象,该方法需要传递两个参数:应用包名和条件。通常情况下,应用程序的包名可以通过Activity或Context(Activity继承自Context)的getPackageName()方法获取,而添加可以有很多设置,通常设置为0。最后是PackageManager对象的获取,Context对象提供了getPackageManager()方法来获取该对象。

本文将对Activity的工作过程进行分析。

主要学习以下内容:

(1)系统内部是如何启动一个Activity的

(2)新Activity的对象是何时创建的

(3)Activity的各个生命周日是被系统何时回调的

Activity启动流程分两种,一种是启动正在运行的app的Activity,即启动子Activity。如无特殊声明默认和启动该activity的activity处于同一进程。如果有声明在一个新的进程中,则处于两个进程。另一种是打开新的app,即为Launcher启动新的Activity。后边启动Activity的流程是一样的,区别是前边判断进程是否存在的那部分。

Activity的启动流程整体如下:

一Activity启动阶段

(一)涉及到的概念

进程:Android系统为每个APP分配至少一个进程

IPC:跨进程通信,Android中采用Binder机制。

(二)涉及到的类

ActivityStack:Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。

ActivitySupervisor:管理 activity 任务栈

ActivityThread:ActivityThread 运行在UI线程(主线程),App的真正入口。

ApplicationThread:用来实现AMS和ActivityThread之间的交互。

ApplicationThreadProxy:ApplicationThread 在服务端的代理。AMS就是通过该代理与ActivityThread进行通信的。

IActivityManager:继承与IInterface接口,抽象出跨进程通信需要实现的功能

AMN:运行在server端(SystemServer进程)。实现了Binder类,具体功能由子类AMS实现。

AMS:AMN的子类,负责管理四大组件和进程,包括生命周期和状态切换。AMS因为要和ui交互,所以极其复杂,涉及window。

AMP:AMS的client端代理(app进程)。了解Binder知识可以比较容易理解server端的stub和client端的proxy。AMP和AMS通过Binder通信。

Instrumentation:仪表盘,负责调用Activity和Application生命周期。测试用到这个类比较多。

(三)涉及到的进程

(1)Launcher所在的进程

(2)AMS所在的SystemServer进程

(3)要启动的Activity所在的app进程

如果是启动根Activity,就涉及上述三个进程。

如果是启动子Activity,那么就只涉及AMS进程和app所在进程。

(四)具体流程

Launcher:Launcher通知AMS要启动activity。

startActivitySafely->startActivity->InstrumentationexecStartActivity()(AMPstartActivity)->AMSstartActivity

AMS:PMS的resoveIntent验证要启动activity是否匹配。如果匹配,通过ApplicationThread发消息给Launcher所在的主线程,暂停当前Activity(即Launcher)。

暂停完,在该activity还不可见时,通知AMS,根据要启动的Activity配置ActivityStack。然后判断要启动的Activity进程是否存在

存在:发送消息LAUNCH_ACTIVITY给需要启动的Activity主线程,执行handleLaunchActivity

不存在:通过socket向zygote请求创建进程。进程启动后,ActivityThreadattach

判断Application是否存在,若不存在,通过LoadApkmakeApplication创建一个。在主线程中通过threadattach方法来关联ApplicationThread。

在通过ActivityStackSupervisor来获取当前需要显示的ActivityStack。

继续通过ApplicationThread来发送消息给主线程的Handler来启动Activity (handleLaunchActivity)。

handleLauchActivity:调用了performLauchActivity,里边Instrumentation生成了新的activity对象,继续调用activity生命周期。

IPC过程:

双方都是通过对方的代理对象来进行通信。

1app和AMS通信:app通过本进程的AMP和AMS进行Binder通信

2AMS和新app通信:通过ApplicationThreadProxy来通信,并不直接和ActivityThread通信

(五)参考函数流程

Activity启动流程(从Launcher开始):

第一阶段: Launcher通知AMS要启动新的Activity(在Launcher所在的进程执行)

第二阶段:AMS先校验一下Activity的正确性,如果正确的话,会暂存一下Activity的信息。然后,AMS会通知Launcher程序pause Activity(在AMS所在进程执行)

第三阶段:pause Launcher的Activity,并通知AMS已经paused(在Launcher所在进程执行)

第四阶段:检查activity所在进程是否存在,如果存在,就直接通知这个进程,在该进程中启动Activity;不存在的话,会调用Processstart创建一个新进程(执行在AMS进程)

第五阶段: 创建ActivityThread实例,执行一些初始化 *** 作,并绑定Application。如果Application不存在,会调用LoadedApkmakeApplication创建一个新的Application对象。之后进入Loop循环。(执行在新创建的app进程)

第六阶段:处理新的应用进程发出的创建进程完成的通信请求,并通知新应用程序进程启动目标Activity组件(执行在AMS进程)

第七阶段: 加载MainActivity类,调用onCreate声明周期方法(执行在新启动的app进程)

从另一个角度下图来概括:

下面简要介绍一下启动的过程:

        Step 1 无论是通过Launcher来启动Activity,还是通过Activity内部调用startActivity接口来启动新的Activity,都通过Binder进程间通信进入到ActivityManagerService进程中,并且调用ActivityManagerServicestartActivity接口; 

        Step 2 ActivityManagerService调用ActivityStackstartActivityMayWait来做准备要启动的Activity的相关信息;

        Step 3 ActivityStack通知ApplicationThread要进行Activity启动调度了,这里的ApplicationThread代表的是调用ActivityManagerServicestartActivity接口的进程,对于通过点击应用程序图标的情景来说,这个进程就是Launcher了,而对于通过在Activity内部调用startActivity的情景来说,这个进程就是这个Activity所在的进程了;

        Step 4 ApplicationThread不执行真正的启动 *** 作,它通过调用ActivityManagerServiceactivityPaused接口进入到ActivityManagerService进程中,看看是否需要创建新的进程来启动Activity;

        Step 5 对于通过点击应用程序图标来启动Activity的情景来说,ActivityManagerService在这一步中,会调用startProcessLocked来创建一个新的进程,而对于通过在Activity内部调用startActivity来启动新的Activity来说,这一步是不需要执行的,因为新的Activity就在原来的Activity所在的进程中进行启动;

        Step 6 ActivityManagerServic调用ApplicationThreadscheduleLaunchActivity接口,通知相应的进程执行启动Activity的 *** 作;

        Step 7 ApplicationThread把这个启动Activity的 *** 作转发给ActivityThread,ActivityThread通过ClassLoader导入相应的Activity类,然后把它启动起来。

 在“手机页面之间的跳转”一文中我介绍了如何运用setContentView()方法切换布局文件Layout的方式进行手机页面间的跳转, 这种适合更改背景,文字颜色,文字内容,但是始终是一个Activity,如果要把主控权移交给另外一个Activity,切换布局文件Layout的方式就办不到了。

如何把主控权移交给另外一个Activity呢?原理:通过Intent对象和startActivity()方法配合来实现。在主程序里使用startActivity()方法调用另外一个Activity,但是最主要的不是这个startActivity()方法,而是Intent对象,Intent在英文中是“意图”的意思,在主Activity当中,告诉程序自己是什么,并想要前往哪里,这就是Intent对象要做的事情了。在主Activity(ActivityOne)里放置一个按钮,当单击这个按钮的时候,告诉主Activity(ActivityOne)前往ActivityTwo,并在ActivityTwo里放置一个回到主Activity(ActivityOne)的一个按钮。

实现步骤

一:布局文件编写

11:第一个布局文件mainxml

<xml version="10" encoding="utf-8">

<LinearLayout xmlns:android=">

您说具体点,什么情况下获取当前窗口的对象。

如果是在一个activity里获取dialogd出来没有就是if(dialog!=null&&dialogisshowing){//就是当前窗口是dialog界面 dialogthis就是当前窗口对象}

eles{//是当前activity 为窗口对象, activitythis}

具体的配置环境和手机环境就不再赘述了。

电脑端:

Android studio

Android sdk

XposedBridgeApi jar包

手机端:

root

安装了xposed installer

已安装并激活xposed框架

其实就是一路next,创建工程完成后等待gradle加载完毕。

导入完成后,修改下app/buildgradle中的依赖声明。将XposedBridgeApi的依赖由implementation改成provided。改完后记得sync一下gradle。

xposedmodule: 表示这是一个xposed模块

xposeddescription: 描述该模块的用途,可以引用stringxml中的字符串

xposedminversion:要求支持的Xposed Framework最低版本

创建一个或者几个类,并实现IXposedHookLoadPackage,IXposedHookZygoteInit或者其他IXposedMod的子接口。

XposedBridgelog会将日志输出到logcat,并写入日志文件

也可以用 androidutilLog输出到logcat

这里举个例子,实现一下xposed的模块自检,检查自己的模块是否启动。就是在程序启动时,判断模块是否激活了。如果激活了就d个toast提示模块已开启,如果因为某种未知原因导致激活失败,那么久d个toast提示模块未开启。

实现也很简单,就是在MainActivity实现一个boolean方法,然后用xposed hook自己。能hook成功,自然代表模块成功启动了,反之亦然。

hook isModuleActive函数

这样就ok了

我们需要新建一个assets文件夹,并创建文件xposed_init,在里面填上xposed模块的入口

这里我们声明自己的类“comjohnhaotestdemoTestDemo”

到这里,这个简单的模块就算开发完了。

将这个工程,编译,打包,安装到已经支持Xposed的手机中。

需要注意的是,要关闭instant run功能!!!

下面看下实际效果(为什么gif不能自己动呢,还得点击查看):

勾选激活模块,重启设备

我们再来启动试试(gif怎么弄才能自动循环播放呢)

是不是ok了呢?

关于xposed简单的介绍就到这儿了

以上就是关于c语言怎么获取红米手机的点击位置全部的内容,包括:c语言怎么获取红米手机的点击位置、service怎么得到绑定的activity实例、如何获取app 的包名和activity 名等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/9564061.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-29
下一篇 2023-04-29

发表评论

登录后才能评论

评论列表(0条)

保存