From 3f9cc91f713654b667956ba0cc2d9d23669aab3a Mon Sep 17 00:00:00 2001 From: Peng Li Date: Wed, 9 May 2018 12:20:48 +0800 Subject: [PATCH 1/1] fix bug when long runing in background --- app/src/main/AndroidManifest.xml | 7 ++ app/src/main/java/ai/suanzi/rtmpclient/Ffmpeg.java | 1 + .../java/ai/suanzi/rtmpclient/MainActivity.java | 73 ++++++------ .../main/java/ai/suanzi/rtmpclient/MyService.java | 125 +++++++++++++++++++++ .../main/java/ai/suanzi/rtmpclient/UsbCamera.java | 4 + app/src/main/jni/ai_suanzi_rtmpclient_Ffmpeg.cpp | 27 ++--- app/src/main/jni/ai_suanzi_rtmpclient_Ffmpeg.h | 8 ++ 7 files changed, 200 insertions(+), 45 deletions(-) create mode 100644 app/src/main/java/ai/suanzi/rtmpclient/MyService.java create mode 100644 app/src/main/java/ai/suanzi/rtmpclient/UsbCamera.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 19ba5b3..1468979 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,6 +9,13 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> + + + + + diff --git a/app/src/main/java/ai/suanzi/rtmpclient/Ffmpeg.java b/app/src/main/java/ai/suanzi/rtmpclient/Ffmpeg.java index e4eb05c..7d9bb80 100644 --- a/app/src/main/java/ai/suanzi/rtmpclient/Ffmpeg.java +++ b/app/src/main/java/ai/suanzi/rtmpclient/Ffmpeg.java @@ -28,4 +28,5 @@ public class Ffmpeg { public native int play(Object surface, String fname); public native int push(Object surface); public native int preview(Object surface); + public native String getPerfectDevice(); } diff --git a/app/src/main/java/ai/suanzi/rtmpclient/MainActivity.java b/app/src/main/java/ai/suanzi/rtmpclient/MainActivity.java index cd42637..f7bb3a3 100644 --- a/app/src/main/java/ai/suanzi/rtmpclient/MainActivity.java +++ b/app/src/main/java/ai/suanzi/rtmpclient/MainActivity.java @@ -1,5 +1,6 @@ package ai.suanzi.rtmpclient; +import android.app.Activity; import android.graphics.ImageFormat; import android.graphics.SurfaceTexture; import android.support.v7.app.AppCompatActivity; @@ -20,6 +21,7 @@ import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import android.content.Intent; +import java.io.OutputStream; @@ -31,6 +33,9 @@ public class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal private StreamTask mStreamTask; private SurfaceHolder mHolder; ExecutorService mExecutor = Executors.newSingleThreadExecutor(); + //Intent it = new Intent(getApplicationContext(), MyService.class); + Intent intent = new Intent(); + @Override protected void onCreate(Bundle savedInstanceState) { @@ -40,7 +45,7 @@ public class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal final Button btn = findViewById(R.id.button); btn.setText("Start"); - btn.setOnClickListener(new View.OnClickListener() { + /*btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.e(TAG, "Button " + btn.getText() + " onClick"); @@ -65,7 +70,7 @@ public class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal } btn.setText(btn.getText().equals("Start") ? "Stop" : "Start"); } - }); + });*/ /*this.mCamera = getCameraInstance(); if(checkCameraHardware(this)) Log.e(TAG, "has cameras: " + Camera.getNumberOfCameras()); @@ -74,56 +79,35 @@ public class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal mHolder = surfaceView.getHolder(); mHolder.addCallback(this); - // - //mCamera.setPreviewCallback(this); + intent.setPackage(this.getPackageName()); + intent.setAction("ai.suanzi.rtmpclient.service"); - /*try{ - mCamera.setPreviewTexture(st); - }catch (IOException e){ - e.printStackTrace(); - }*/ final Button btn2 = findViewById(R.id.button); + + btn2.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View view){ Log.e(TAG, "onclick2"); //ffmpeg.play(mHolder.getSurface(),"/storage/sdcard0/output.flv"); - ffmpeg.push(mHolder.getSurface()); + //ffmpeg.push(mHolder.getSurface()); //ffmpeg.preview(mHolder.getSurface()); - + // intent.putExtra("cmd",0);//0,开启前台服务,1,关闭前台服务 + startService(intent); } }); - Log.e(TAG, "onclick2"); - /* - try { - Log.e(TAG, "Run command"); - Process sh = Runtime.getRuntime().exec(new String[]{"su", "-c", "chmod 666 /dev/video0"}); - sh.waitFor(); - }catch (Exception e){ - e.printStackTrace(); - }*/ - - - - - btn2.post(new Runnable(){ @Override public void run() { btn2.performClick(); + } }); - - Intent i = new Intent(); - i.setAction(Intent.ACTION_MAIN); - i.addCategory(Intent.CATEGORY_HOME); - this.startActivity(i); - - + switchToBackground(); } //SurfaceTexture st = new SurfaceTexture(0); @@ -318,4 +302,29 @@ public class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal return c; } + private void changeCameraPermission(){ + Log.e(TAG, "change /dev/video0 permission"); + try{ + /*Process sh = Runtime.getRuntime().exec("su", null,null); + OutputStream os = sh.getOutputStream(); + os.write(("chmod 666 /dev/video0").getBytes("ASCII")); + os.flush(); + os.close(); + sh.waitFor();*/ + + Process sh = Runtime.getRuntime().exec(new String[]{"su", "-c", "system/bin/sh"}); + sh = Runtime.getRuntime().exec(new String[]{"chmod", "666", "/dev/video0"}); + sh.waitFor(); + } catch (Exception e){ + e.printStackTrace(); + } + } + + private void switchToBackground(){ + Intent i = new Intent(); + i.setAction(Intent.ACTION_MAIN); + i.addCategory(Intent.CATEGORY_HOME); + this.startActivity(i); + } + } diff --git a/app/src/main/java/ai/suanzi/rtmpclient/MyService.java b/app/src/main/java/ai/suanzi/rtmpclient/MyService.java new file mode 100644 index 0000000..c5ec172 --- /dev/null +++ b/app/src/main/java/ai/suanzi/rtmpclient/MyService.java @@ -0,0 +1,125 @@ +package ai.suanzi.rtmpclient; + +import android.app.Service; +import android.content.Intent; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IBinder; +import android.os.Looper; +import android.util.Log; +import android.widget.Toast; +import android.support.v4.app.NotificationCompat; +import android.graphics.BitmapFactory; +import android.app.Notification; +import android.os.Message; + +public class MyService extends Service { + private static final String TAG = "MyService"; + private Ffmpeg ffmpeg = new Ffmpeg(); + private Boolean isRunning = false; + + private Runnable runnable = new Runnable() { + @Override + public void run() { + Log.e(TAG, "Run ffmpeg"); + isRunning = true; + ffmpeg.push(null); + } + }; + + + /** + * id不可设置为0,否则不能设置为前台service + */ + private static final int NOTIFICATION_DOWNLOAD_PROGRESS_ID = 0x0001; + + //private boolean isRemove=false;//是否需要移除 + + /** + * Notification + */ + public void createNotification(){ + Log.e(TAG, "create notification"); + //使用兼容版本 + NotificationCompat.Builder builder=new NotificationCompat.Builder(this); + //设置状态栏的通知图标 + builder.setSmallIcon(R.mipmap.ic_launcher); + //设置通知栏横条的图标 + builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher_background)); + //禁止用户点击删除按钮删除 + builder.setAutoCancel(false); + //禁止滑动删除 + builder.setOngoing(true); + //右上角的时间显示 + builder.setShowWhen(true); + //设置通知栏的标题内容 + builder.setContentTitle("Rtmp Foreground Service!!!"); + //创建通知 + Notification notification = builder.build(); + //设置为前台服务 + startForeground(NOTIFICATION_DOWNLOAD_PROGRESS_ID,notification); + } + + + + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public void onCreate() { + super.onCreate(); + Log.e(TAG, "onCreate"); + } + + @Override + public void onDestroy() { + stopForeground(true); + Toast.makeText(this, "MyService Stopped", Toast.LENGTH_LONG).show(); + Log.e(TAG, "onDestroy"); + super.onDestroy(); + + } + + @Override + public void onStart(Intent intent, int startid){ + super.onStart(intent, startid); + Log.e(TAG, "onStart"); + + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Log.e(TAG, "onStartCommand"); + if (!isRunning) { + createNotification(); + Toast.makeText(this, "Ffmpeg started", Toast.LENGTH_LONG).show(); + new Thread(runnable).start(); + } + +// int i=intent.getExtras().getInt("cmd"); +// if(i==0){ +// if(!isRemove) { +// +// createNotification(); +// } +// isRemove=true; +// }else { +// //移除前台服务 +// if (isRemove) { +// stopForeground(true); +// } +// isRemove=false; +// } + //super.onStartCommand(intent, flags, startId); + return START_STICKY; + } + + @Override + public void onLowMemory(){ + super.onLowMemory(); + Log.e(TAG, "onLowMemory"); + } + +} diff --git a/app/src/main/java/ai/suanzi/rtmpclient/UsbCamera.java b/app/src/main/java/ai/suanzi/rtmpclient/UsbCamera.java new file mode 100644 index 0000000..0ca1023 --- /dev/null +++ b/app/src/main/java/ai/suanzi/rtmpclient/UsbCamera.java @@ -0,0 +1,4 @@ +package ai.suanzi.rtmpclient; + +public class UsbCamera { +} diff --git a/app/src/main/jni/ai_suanzi_rtmpclient_Ffmpeg.cpp b/app/src/main/jni/ai_suanzi_rtmpclient_Ffmpeg.cpp index 760a062..59d4b6c 100644 --- a/app/src/main/jni/ai_suanzi_rtmpclient_Ffmpeg.cpp +++ b/app/src/main/jni/ai_suanzi_rtmpclient_Ffmpeg.cpp @@ -477,8 +477,8 @@ JNIEXPORT jint JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_push (JNIEnv *env, jobje AVFormatContext *pFormatCtx = avformat_alloc_context(); AVInputFormat *ifmt = av_find_input_format("video4linux2"); - if(avformat_open_input(&pFormatCtx, "/dev/video0", ifmt, NULL) != 0) { - LOGE("could not open file11"); + if((ret = avformat_open_input(&pFormatCtx, "/dev/video0", ifmt, NULL)) != 0) { + LOGE("could not open file11, ret=%d, error=%s,", ret, av_err2str(ret)); return -1; } @@ -621,21 +621,17 @@ JNIEXPORT jint JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_push (JNIEnv *env, jobje int64_t pts_time = av_rescale_q(enc_pkt.dts, time_base, time_base_q); - } - - ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt); //av_frame_free(&pFrameYUV); //av_packet_unref(packet); - //av_free_packet(&enc_pkt); + av_free_packet(&enc_pkt); + //av_packet_unref(&enc_pkt); + + + } + - /* - int y_size = pCodecCtx->width * pCodecCtx->height; - fwrite(pFrameYUV->data[0], 1, y_size, fp); // Y - fwrite(pFrameYUV->data[1], 1, y_size / 4, fp); // U - fwrite(pFrameYUV->data[2], 1, y_size / 4, fp); // V - */ } } av_packet_unref(packet); @@ -643,6 +639,7 @@ JNIEXPORT jint JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_push (JNIEnv *env, jobje sws_freeContext(img_convert_ctx); av_free(pFrameYUV); + av_free(pFrame); avcodec_close(pCodecCtx); avformat_close_input(&pFormatCtx); return 0; @@ -800,4 +797,8 @@ JNIEXPORT jint JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_preview (JNIEnv *env, jo //env->ReleaseStringUTFChars(fname, file_name); return 0; -} \ No newline at end of file +} + +JNIEXPORT jstring JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_getPerfectDevice (JNIEnv *env, jobject obj) { + +} diff --git a/app/src/main/jni/ai_suanzi_rtmpclient_Ffmpeg.h b/app/src/main/jni/ai_suanzi_rtmpclient_Ffmpeg.h index 9752077..2bdd6a7 100644 --- a/app/src/main/jni/ai_suanzi_rtmpclient_Ffmpeg.h +++ b/app/src/main/jni/ai_suanzi_rtmpclient_Ffmpeg.h @@ -71,6 +71,14 @@ JNIEXPORT jint JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_push JNIEXPORT jint JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_preview (JNIEnv *, jobject, jobject); +/* + * Class: ai_suanzi_rtmpclient_Ffmpeg + * Method: getPerfectDevice + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_ai_suanzi_rtmpclient_Ffmpeg_getPerfectDevice + (JNIEnv *, jobject); + #ifdef __cplusplus } #endif -- 2.11.0