|
本帖最后由 兔巴哥 于 2019-11-7 18:18 编辑
继之一、之二后,一直折腾怎么样将oscam打包成安卓的app,无奈功力不够,只能进行到编译出主程序一步,遂放弃.....近日发现了很有意义的博文,于是分享给大家。(内容有删减)
一、Compiling Oscam for Android
1、首先配置Linux系统
2、下载最新的Linux 64位(x86)Android NDK,可以在这里下载https://developer.android.com/ndk/downloads/index.html,在写这篇文章的时候,最新的稳定版本是r13b。
将NDK文件解压到Home,然后cd到build / tools文件夹中,以便于构建用于交叉编译的工具链。
- cd ~/android-ndk-r13b/build/tools
- export TOOLCHAIN=~/android-toolchain
- ./make_standalone_toolchain.py --arch arm --api 24 --install-dir $TOOLCHAIN
复制代码 这个命令在你的Home上创建一个android工具链。
3、在使用这个工具链交叉编译OScam之前,我们还需要先编译OpenSSL,否则在使用cccam协议时会出现无法连接的情况。
下载,解压缩和构建OpenSSL:
- cd ~
- wget http://www.openssl.org/source/openssl-1.0.1g.tar.gz
- tar -xf openssl-1.0.1g.tar.gz
- cd openssl-1.0.1g
- export CC=$TOOLCHAIN/bin/arm-linux-androideabi-gcc
- export RANLIB=$TOOLCHAIN/bin/arm-linux-androideabi-ranlib
- ./Configure --prefix=$TOOLCHAIN/sysroot/usr android
- make
- make install_sw
复制代码 检查Oscam svn并编译添加openssl。
- cd ~
- svn checkout http://www.streamboard.tv/svn/oscam/trunk oscam-svn
- cd oscam-svn
- ./config.sh --enable WEBIF WITH_SSL
复制代码 4、交叉编译Android上运行的Oscam。
- make static EXTRA_FLAGS="-pie" LIB_RT= LIB_PTHREAD= CROSS=$TOOLCHAIN/bin/arm-linux-androideabi-
复制代码 如果一切正常,应该在oscam-svn的Distribution文件夹中生成一个在Android环境中运行的程序文件,比如oscam-1.20-unstable_svn11347-arm-linux-androideabi-ssl。
当然,这不是一个APK,刚刚做的只是编译出来了本机C代码。这个在安卓设备运行比较麻烦,而且也不容易实现。
APK是一个包含字节码(编译的java代码)和资源的包,它将在android java虚拟机(可以是Dalvik或ART,取决于您的Android版本)内运行。
那么如何在安卓设备上安装并运行该程序呢?
我们基本上需要构建一个包含我们的本地二进制文件作为资源的Android应用程序(APK),将其提取到可执行的位置(不在SDCard上运行),使其可执行并运行。
二、Building an Oscam APK for Android在上一节中如果已经编译出Oscam二进制文件,那么这一步生成APK的过程无论是Linux系统还是Windows系统都是可以完成的。
1、使用Android Studio创建一个新的项目。
2、在“res”文件夹下创建一个“raw”文件夹。
3、把oscam二进制文件改名为“oscam”并放在raw文件夹下。
4、添加一些小部件到用户界面,并做一些代码。
5、布局的XML代码应该是这样的:
- <?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:id="@+id/activity_main"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="@dimen/activity_vertical_margin"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- tools:context="com.tekreaders.myoscamapk.MainActivity">
-
- <Button
- android:id="@+id/startButton"
- android:layout_alignParentTop="true"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Start Oscam"
- android:onClick="startOscam"
- />
- <Button
- android:id="@+id/stopButton"
- android:layout_toRightOf="@+id/startButton"
- android:layout_alignParentTop="true"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Stop Oscam"
- android:onClick="stopOscam"
- />
-
- <TextView
- android:id="@+id/outputView"
- android:layout_alignParentBottom="true"
- android:layout_alignParentRight="true"
- android:layout_alignParentLeft="true"
- android:layout_below="@+id/startButton"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:maxLines="200"
- android:scrollbars="vertical"
- android:text="Oscam log will be displayed here..."
- />
- </RelativeLayout>
复制代码 6、整个MainActivity的代码:
- public class MainActivity extends AppCompatActivity {
- TextView outputView;
- Button startButton;
- Button stopButton;
-
- private String confDir = Environment.getExternalStorageDirectory().getPath() + "/oscam";
- private String tmpDir = Environment.getExternalStorageDirectory().getPath() + "/oscam/tmp";
- private String oscamFilename = "";
- private Process oscamProcess;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- outputView = (TextView)findViewById(R.id.outputView);
- startButton = (Button)findViewById(R.id.startButton);
- stopButton = (Button)findViewById(R.id.stopButton);
- outputView.setMovementMethod(new ScrollingMovementMethod());
- requestPermissions();
- }
-
- //request the runtime permissions, this required since Marshmallow
- public void requestPermissions() {
- if (Build.VERSION.SDK_INT >= 23) {
- ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
- }
- }
-
- //output logs and enable/disable buttons according to the running state
- public void setStatus(final boolean running, final String message){
- runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if (message!=null) {
- outputView.setText(outputView.getText()+"\n"+message);
- if (outputView.getVisibility() == View.VISIBLE) {
- final int scrollAmount = outputView.getLayout().getLineTop(outputView.getLineCount()) - outputView.getHeight();
- if (scrollAmount > 0)
- outputView.scrollTo(0, scrollAmount);
- else
- outputView.scrollTo(0, 0);
- }
- }
- startButton.setEnabled(!running);
- stopButton.setEnabled(running);
- }
- });
- }
-
- public void startOscam(View view){
- if (oscamProcess == null) {
- //run this process on a new thread to avoid UI blocking
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- setStatus(true, "Initializing...");
- //check the config and tmp folders
- File cdir = new File(confDir);
- File tdir = new File(tmpDir);
- boolean confDirExists = cdir.exists();
- boolean tmpDirExists = tdir.exists();
- if (!confDirExists)
- confDirExists = cdir.mkdir();
- if (!tmpDirExists)
- tmpDirExists = tdir.mkdir();
- if (confDirExists && tmpDirExists) {
- //check the stat file to sanitize the default errors
- File stat = new File(tmpDir + "/stat");
- if (!stat.exists()) {
- FileWriter statfile = new FileWriter(stat);
- statfile.write("");
- statfile.close();
- }
- //extract the resource in the raw folder into the App private space and overwrite if it already exists
- String appFileDirectory = getFilesDir().getParent();
- oscamFilename = appFileDirectory + "/oscam";
- InputStream ins = getResources().openRawResource(R.raw.oscam);
- final byte[] buffer = new byte[ins.available()];
- ins.read(buffer);
- ins.close();
- File destination = new File(oscamFilename);
- if (destination.exists())
- destination.delete();
- FileOutputStream fos = new FileOutputStream(destination);
- fos.write(buffer);
- fos.close();
- if (destination.exists()) {
- //set executable rights on the file (chmod)
- boolean isExecutable = destination.setExecutable(true);
- if (isExecutable) {
- setStatus(true, "Launching oscam with confDir='" + confDir + "' and tmpDir='" + tmpDir + "'...");
- //start the Oscam process
- oscamProcess = new ProcessBuilder().command(oscamFilename, "--config-dir", confDir, "--temp-dir", tmpDir).redirectErrorStream(true).start();
- //start a thread to read Oscam logs and print them on our textview
- Thread readThread = new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(oscamProcess.getInputStream()));
- while (!Thread.currentThread().isInterrupted()) {
- if (bufferedReader.ready()) {
- String line = bufferedReader.readLine();
- setStatus(true, line);
- }
- }
- bufferedReader.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- });
- readThread.start();
- //wait for the process to terminate
- oscamProcess.waitFor();
- //when we get here, the process is already dead, we should cleanup
- readThread.interrupt();
- oscamProcess = null;
- setStatus(false, "Oscam stopped!");
- } else
- setStatus(false, "Oscam is not executable!");
- } else
- setStatus(false, "Oscam binary not found!");
- } else
- setStatus(false, "Unable to read/write configuration and tmp folder!");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }).start();
- }
- }
-
- public void stopOscam(View view){
- if (oscamProcess != null) {
- try {
- //get the Oscam process PID by using reflection
- long pid = -1;
- try {
- Field f = oscamProcess.getClass().getDeclaredField("pid");
- f.setAccessible(true);
- pid = f.getLong(oscamProcess);
- f.setAccessible(false);
- } catch (Exception e) {
- pid = -1;
- }
- //send a SIGTERM to the oscam process
- Runtime.getRuntime().exec("kill -15 " + pid);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }else
- setStatus(false, "Oscam stopped!");
- }
-
-
- }
复制代码 7、运行应用程序并单击开始按钮后,你应该看到这样的界面。
就是这样。 你刚做了一个可以启动和停止的Oscam APK。 请记住将您的配置文件放在/ sdcard / oscam /文件夹中,然后就可以开始了。
以上所有代码的示例项目也可以在GitHub上获得。
显然你可以对这个应用程序做更多的改进。 例如,这应该是一个服务,并在启动时运行,不会被系统杀死。
但是,这超出了本教程的范围,您应该查看Android文档以了解更多信息。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|