文章采集api(抖音爬虫教程,AndServer+Service打造Android服务器实现so文件调用)

优采云 发布时间: 2021-10-04 14:14

  文章采集api(抖音爬虫教程,AndServer+Service打造Android服务器实现so文件调用)

  抖音爬虫教程,AndServer+Service搭建Android服务器实现so文件调用so文件调用

  随着Android手机安全的飞速发展,无论是为了执行效率还是程序安全,关键代码下沉到native层已经成为一项基本操作。

  native层的开发参考JNI/NDK开发。通过JNI,Java层和native层(主要是C/C++)可以相互调用。本机层编译生成so动态链接库,so文件具有可移植性广、执行效率高、保密性强等优点。

  那么问题来了,如何调用so文件是极其重要的。当然你也可以直接分析so文件的伪代码,用强大的编程技巧直接模拟按键操作,不过我觉得对于普通人来说头发还是比较重要的。

  目前主流的调用so文件的操作应该是: 1.基于Unicorn的各种实现(还在学习中,暂不列出) 2. Android服务器搭建,在App中启动http服务完成调用so的需求(当然前提是经过so等验证)

  至于为什么选择AndServer,嗯,不是为什么,只是因为我发现了它为什么要和Service结合,我在学习Android开发的时候就了解了Service的生命周期,个人理解还是用Service来做比较好创建 Http 服务。

  当然也有Application的简单使用,因为在正式环境下,so文件的大部分逻辑都有上下文的一些包名,签名验证等,如果自定义Application,就可以得到传递参数的上下文。

  短视频直播数据采集接口SDK,请点击查看接口文档libyemu.so介绍

  这是我编译的so文件,根据输入参数进行简单的字符串拼接(以下是native层编译前的c代码)

  extern "C"

JNIEXPORT jstring JNICALL

Java_com_fw_myapplication_ndktest_NdkTest_stringFromUTF(JNIEnv *env, jobject instance, jstring str_) {

jclass String_clazz = env->FindClass("java/lang/String");

jmethodID concat_methodID = env->GetMethodID(String_clazz, "concat", "(Ljava/lang/String;)Ljava/lang/String;");

jstring str = env->NewStringUTF(" from so --[NightTeam夜幕]");

jobject str1 = env->CallObjectMethod(str_, concat_methodID, str);

const char *chars = env->GetStringUTFChars((jstring)str1, 0);

return env->NewStringUTF(chars);

}

  这部分代码还需要贴出来。简单的静态配准使用了反射的思想。反之,反射是至关重要的。接下来是java代码,它定义了native函数。

  package com.fw.myapplication.ndktest;

public class NdkTest {

public static native String stringFromUTF(String str);

static {

System.loadLibrary("yemu");

}

}

  如果你在这里有点困惑,你可能需要补上Android开发的基础。

  Android项目测试so

  先说一下我的环境,因为这个环境影响太大了 1、AndroidStudio 3.4 2、手机Android 6架构 armeabi-v7a 打开AndroidStudio新建项目

  

  在模块的build中加入这句话,然后同步

  

  将编译好的so文件复制到libs文件夹(对应刚才的jniLibs.srcDirs)

  

  复制so对应的java代码,注意包名和类名的一致性

  

  打开activity_main.xml文件,给TextView添加一个id

  

  打开 MainActiviy.java 开始编码

  

  这两行的意思是,先从layout中找到id对应的TextView,然后为其设置Text(调用原生函数的返回值)。让我们测试一下我们的通话情况。

  

  可以看到我们的so文件调用成功了(这里我们的so无效,测试一下app是否可以正常调用)

  AndServer代码编写

  AndServer官方文档:/AndServer/ 打开官方文档,看看别人的介绍,新建一个java文件

  

  如图,写了经典的MVC C,定义了一个nightteam_sign接口,请求方法为get,请求参数为sign,调用native函数,然后返回json,但是这里我想用Application获取上下文对象并去掉包名,然后自定义Applictaion

  package com.nightteam.httpso;

import android.app.Application;

public class MyApp extends Application {

private static MyApp myApp;

public static MyApp getInstance() {

return myApp;

}

@Override

public void onCreate() {

super.onCreate();

myApp = this;

}

}

  然后在清单文件中指定要启动的应用程序

  

  然后修改MyController.java的代码

  

  接下来复制官方文档服务器的代码导入一些包,修改部分代码如下

  

  AndServer.serverBuilder 的新版本已经需要传递上下文。这里也修改了网络地址和端口号,从构造参数中获取。至此,AndServer 的东西基本完成了。其实我们会搭建一个界面来调整so。业务逻辑比较多,所以代码最简单好用

  服务代码编写

  这里我们用按钮的点击事件启动Service,所以在activity_main.xml中添加一个按钮并指定点击事件

  

  

  接下来编写自定义Service代码

  package com.nightteam.httpso.Service;

import android.app.Service;

import android.content.Intent;

import android.os.IBinder;

import android.util.Log;

import com.nightteam.httpso.ServerManager;

import java.net.InetAddress;

import java.net.UnknownHostException;

public class MyService extends Service {

private static final String TAG = "NigthTeam";

@Override

public void onCreate() {

super.onCreate();

Log.d(TAG, "onCreate: MyService");

new Thread() {

@Override

public void run() {

super.run();

InetAddress inetAddress = null;

try {

inetAddress = InetAddress.getByName("0.0.0.0");

Log.d(TAG, "onCreate: " + inetAddress.getHostAddress());

ServerManager serverManager = new ServerManager(getApplicationContext(), inetAddress, 8005);

serverManager.startServer();

} catch (UnknownHostException e) {

e.printStackTrace();

}

}

}.start();

}

@Override

public IBinder onBind(Intent intent) {

return null;

}

}

  我打印了几条日志,在子线程中启动了AndServer服务(什么时候使用UI线程和子线程是Android的基础,这里不再赘述)。注意,这里从 0.0.0.0 获取inetAddress,别搞错了,localhost和0.0.0.的区别0,请移至搜索引擎,然后将context、inetAddress、port传递给ServerManager的构造函数用于新建对象,然后启动服务最后注意查看manifest文件中Service的声明

  

  打开Service,获取本地ip

  回到我们MainActivity.java的操作(按钮点击事件)编写启动Service的代码

  public void operate(View view) {

switch (view.getId()){

case R.id.id_bt_index:

//启动服务:创建-->启动-->销毁

//如果服务已经创建了,后续重复启动,操作的都是同一个服务,不会再重新创建了,除非你先销毁它

Intent it1 = new Intent(this, MyService.class);

Log.d(TAG, "operate: button");

startService(it1);

((Button) view).setText("服务已开启");

break;

}

}

  至此,我们的服务基本设置好了,但是为了方便,我想在App上显示我们本地的IP,这样我们就不用再设置和检查了。我在网上找到了一个获取IP地址的工具。,源码如下:

  package com.nightteam.httpso;

import java.net.InetAddress;

import java.net.NetworkInterface;

import java.net.SocketException;

import java.util.Enumeration;

import java.util.regex.Pattern;

public class NetUtils {

private static final Pattern IPV4_PATTERN = Pattern.compile("^(" +

"([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" +

"([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");

private static boolean isIPv4Address(String input) {

return IPV4_PATTERN.matcher(input).matches();

}

//获取本机IP地址

public static InetAddress getLocalIPAddress() {

Enumeration enumeration = null;

try {

enumeration = NetworkInterface.getNetworkInterfaces();

} catch (SocketException e) {

e.printStackTrace();

}

if (enumeration != null) {

while (enumeration.hasMoreElements()) {

NetworkInterface nif = enumeration.nextElement();

Enumeration inetAddresses = nif.getInetAddresses();

if (inetAddresses != null)

while (inetAddresses.hasMoreElements()) {

InetAddress inetAddress = inetAddresses.nextElement();

if (!inetAddress.isLoopbackAddress() && isIPv4Address(inetAddress.getHostAddress())) {

return inetAddress;

}

}

}

}

return null;

}

}

  将工具类复制到我们的 Android 项目中,并在 MainActivity.java 中继续编码

  

  获取本地地址和Android SDK版本(Android 8之后启动Service的方式不同)

  申请权限,启动App

  最后一步是为应用申请网络权限

  

  然后连接我们的手机,运行项目,测试一下,点击启动服务

  

  查看AndroidStudio日志

  

  好像一切正​​常,在浏览器访问下试试(ip是App中显示的ip地址)

  

  如图,我们访问到了我们想要的内容。回去再说Service,打开我们手机的设置,找到应用管理-运行服务(不同的手机,不同的方法)

  

  可以看到我们的程序运行了一个服务,这个服务就是我们编码的MyService

  接下来,杀死App进程并再次检查正在运行的服务

  

  这里我在权限管理中设置了自动运行,可以保持服务运行。(这个地方还是根据系统大小不同) 到此为止,可以使用App启动http服务并调整so。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线