stream pushing ok without access permission of /dev/video0
[rtmpclient.git] / app / src / main / java / ai / suanzi / rtmpclient / MainActivity.java
1 package ai.suanzi.rtmpclient;
2
3 import android.app.Activity;
4 import android.app.PendingIntent;
5 import android.content.BroadcastReceiver;
6 import android.content.IntentFilter;
7 import android.graphics.ImageFormat;
8 import android.graphics.SurfaceTexture;
9 import android.hardware.usb.UsbDevice;
10 import android.hardware.usb.UsbManager;
11 import android.os.Environment;
12 import android.support.design.widget.TextInputEditText;
13 import android.support.v7.app.AppCompatActivity;
14 import android.os.Bundle;
15 import android.text.TextUtils;
16 import android.util.Log;
17 import android.view.SurfaceHolder;
18 import android.hardware.Camera;
19 import android.view.SurfaceView;
20 import android.view.View;
21 import android.widget.Button;
22 import android.widget.Toast;
23 import android.content.Context;
24 import android.content.pm.PackageManager;
25 import android.os.AsyncTask;
26
27 import java.io.File;
28 import java.util.HashMap;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.io.IOException;
32 import java.util.concurrent.Executor;
33 import java.util.concurrent.ExecutorService;
34 import java.util.concurrent.Executors;
35 import android.content.Intent;
36 import java.io.OutputStream;
37 import android.hardware.usb.UsbManager;
38 import android.hardware.usb.UsbDeviceConnection;
39
40 import de.mindpipe.android.logging.log4j.LogConfigurator;
41 import org.apache.log4j.Level;
42 import org.apache.log4j.Logger;
43 import android.net.wifi.WifiManager;
44 import android.net.wifi.WifiInfo;
45
46 //"rtmp://gpussh.suanzi.ai:1935/myapp/suanzi_ac83f34ead90_cameraid";
47
48 public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback, Camera.PreviewCallback{
49
50     private static final String TAG = "PENG";
51     private Ffmpeg ffmpeg;
52     private Camera mCamera ;
53     private StreamTask mStreamTask;
54     private SurfaceHolder mHolder;
55     private SurfaceView mSufaceView;
56     private UVCCamera uvcCamera;
57     ExecutorService mExecutor = Executors.newSingleThreadExecutor();
58     //Intent it = new Intent(getApplicationContext(), MyService.class);
59     Intent intent = new Intent();
60
61     private UsbManager usbManager;
62     private UsbDevice usbCamera;
63
64     private Logger gLogger;
65
66     private Button mBtnStart;
67     private TextInputEditText mTextServer;
68     private TextInputEditText mTextUser;
69     private TextInputEditText mTextCamera;
70     private String mMacAddr = "";
71
72     private void configLog(){
73         try {
74             final LogConfigurator logConfigurator = new LogConfigurator();
75             String fname = getExternalFilesDir(null) + File.separator + "log.txt";
76             logConfigurator.setFileName(fname);
77             Log.e(TAG, "Log file is located at: " + fname);
78             logConfigurator.setRootLevel(Level.DEBUG);
79             logConfigurator.setLevel("org.apache", Level.ERROR);
80             logConfigurator.setMaxFileSize(1024 * 1024 * 10);
81             logConfigurator.configure();
82             gLogger = Logger.getLogger(getClass());
83         } catch (Exception e){
84             e.printStackTrace();
85         }
86     }
87
88     private void init(){
89         configLog();
90         gLogger.debug("#######################################");
91         UserInfo.setConfigPath(getExternalFilesDir(null) + File.separator + "config");
92         this.mMacAddr = getMacAddr();
93
94         ffmpeg = Ffmpeg.getInstance();
95         uvcCamera = new UVCCamera();
96
97         mBtnStart = findViewById(R.id.button);
98         mTextServer = findViewById(R.id.textServer);
99         mTextUser = findViewById(R.id.textUser);
100         mTextCamera = findViewById(R.id.textCamera);
101         loadConfig();
102
103         // init service
104         intent.setPackage(this.getPackageName());
105         intent.setAction("ai.suanzi.rtmpclient.service");
106
107         // init surface view
108         mSufaceView = findViewById(R.id.surfaceView);
109         mHolder = mSufaceView.getHolder();
110         mHolder.addCallback(this);
111
112         // camera
113         mCamera = getCameraInstance();
114         configCamera(mCamera);
115     }
116
117
118     @Override
119     protected void onCreate(Bundle savedInstanceState) {
120         super.onCreate(savedInstanceState);
121         setContentView(R.layout.activity_main);
122         init();
123
124         mBtnStart.setOnClickListener(new View.OnClickListener(){
125             @Override
126             public void onClick(View view){
127                 String url = mTextServer.getText().toString() + "/" + mTextUser.getText().toString() + "_" + mMacAddr + "_" + mTextCamera.getText().toString();
128                 gLogger.error("----------> onClick, Url is: " + url);
129                 intent.putExtra("url", url);
130                 startService(intent);
131                 saveConfig();
132                 //changePermission();
133             }
134         });
135
136         /*btn2.post(new Runnable(){
137             @Override
138             public void run() {
139                 btn2.performClick();
140
141             }
142         });
143
144         switchToBackground();*/
145
146         /*
147         usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
148         HashMap<String, UsbDevice> deviceList = usbManager.getDeviceList();
149         Log.e(TAG, "device list size : " + deviceList.size());
150         Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
151         PendingIntent mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
152
153         IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED);
154         registerReceiver(mUsbReceiver, filter);
155         filter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_ATTACHED);
156         registerReceiver(mUsbReceiver, filter);
157         filter = new IntentFilter(ACTION_USB_PERMISSION);
158         registerReceiver(mUsbReceiver, filter);
159
160         while(deviceIterator.hasNext()){
161             UsbDevice device = deviceIterator.next();
162             Log.e(TAG, device.toString());
163             Log.e(TAG, device.getDeviceName() + " manufacture name: " + device.getManufacturerName() + " " + device.getSerialNumber() + " " + device.getDeviceId());
164
165             if (device.getVendorId() == 6257){
166                 usbManager.requestPermission(device, mPermissionIntent);
167                 Log.e(TAG,"XXXXXXXXXXXXXXXXXXXXXXXXXXX");
168                 Log.e(TAG, device.getVendorId() + "\n" + device.getProductId() + "\n" + device.getProductName() + "\n" +
169                         device.getManufacturerName() + "\n" + device.getDeviceId() + "\n" + device.getSerialNumber() + "\n" +
170                         device.getDeviceName());
171
172                 final String name = device.getDeviceName();
173                 final String[] v =  name.split("/");
174                 int busnum = 0;
175                 int devnum = 0;
176                 if (v != null) {
177                     busnum = Integer.parseInt(v[v.length-2]);
178                     devnum = Integer.parseInt(v[v.length-1]);
179                 }
180                 //mBusNum = busnum;
181                 //mDevNum = devnum;
182                 uData.vid = device.getVendorId();
183                 uData.pid = device.getProductId();
184                 uData.busNum = busnum;
185                 uData.devNum = devnum;
186
187                 String result = null;
188                 final String[] vv =  name.split("/");
189                 if ((vv != null) && (vv.length > 2)) {
190                     final StringBuilder sb = new StringBuilder(vv[0]);
191                     for (int i = 1; i < vv.length - 2; i++)
192                         sb.append("/").append(vv[i]);
193                     result = sb.toString();
194                 }
195                 uData.usbFsName = result;
196
197
198                 uData.print();
199
200                 usbCamera = device;
201             }
202
203             //Log.e(TAG, device.)
204             //device.getInterface()
205         }*/
206     }
207
208     /*private UsbData uData = new UsbData();
209
210     private class UsbData {
211         public int vid;
212         public int pid;
213         public int fd;
214         public int busNum;
215         public int devNum;
216         public String usbFsName;
217         public void print(){
218             Log.e(TAG, "vid=" + vid + ". pid=" + pid + ". fd=" + fd + ". busnum=" + busNum + ". devNum=" + devNum + ". usbFsName=" + usbFsName);
219         }
220     }*/
221
222     //SurfaceTexture st = new SurfaceTexture(0);
223
224     /*private static final String ACTION_USB_PERMISSION =
225             "com.android.example.USB_PERMISSION";
226     private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
227
228         public void onReceive(Context context, Intent intent) {
229             String action = intent.getAction();
230             if (ACTION_USB_PERMISSION.equals(action)) {
231                 synchronized (this) {
232                     UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
233
234                     if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true)) {
235                         if(device != null){
236                             Log.e(TAG, "extra permission granted");
237                             //call method to set up device communication
238
239
240                             new Thread(new Runnable() {
241                                 @Override
242                                 public void run() {
243                                     Log.e("device","MyThread3");//bhw
244                                     UsbDeviceConnection connection = usbManager.openDevice(usbCamera);
245                                     int fd = connection.getFileDescriptor();//获取文件描述符
246                                     uData.fd = fd;
247                                     //ffmpeg.test(fd);
248                                     int ret = uvcCamera.open(uData.vid, uData.pid, uData.fd, uData.busNum, uData.devNum, uData.usbFsName);
249                                     Log.e(TAG, "uvcCamera open return code:" + ret);
250
251                                     Log.e("device","MyThread3  "+fd);
252                                 }
253                             }).start();
254
255                         }
256                     }
257                     else {
258                         Log.e(TAG, "permission denied for device. " + device);
259                     }
260                 }
261             } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)){
262                 UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
263                 if (device != null){
264                     Log.e(TAG, "==== device out");
265                 }
266             } else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
267                 Log.e(TAG, "==== device in =====");
268             }
269         }
270     };*/
271
272
273
274
275     @Override
276     protected void onPause(){
277         super.onPause();
278         gLogger.debug("OnPause");
279     }
280
281     @Override
282     protected void onResume() {
283         super.onResume();
284         gLogger.debug("OnResume");
285     }
286
287     @Override
288     protected void onStop() {
289         super.onStop();
290         gLogger.debug("onStop");
291     }
292
293     @Override
294     protected void onStart(){
295         super.onStart();
296         gLogger.debug("onStart");
297     }
298
299     @Override
300     protected void onDestroy(){
301         super.onDestroy();
302         gLogger.debug("onDestroy");
303     }
304
305     @Override
306     protected void onRestart(){
307         super.onStart();
308         gLogger.debug("onRestart");
309     }
310
311
312     // class StreamTask AsyncTask
313     private class StreamTask extends AsyncTask<Void, Void, Void>{
314         private byte[] data;
315
316         StreamTask(byte[] data){
317             this.data = data;
318         }
319
320         @Override
321         protected Void doInBackground(Void... params) {
322
323             if (this.data != null){
324                 Log.e(TAG, "fps: " + mCamera.getParameters().getPreviewFrameRate());
325                 ffmpeg.process(this.data);
326             }
327             return null;
328         }
329     }
330
331
332
333
334     // SurfaceHolder.Callback implementation
335     @Override
336     public void surfaceCreated(final SurfaceHolder holder){
337         gLogger.error("SurfacedCreated");
338     }
339
340     @Override
341     public void surfaceChanged(SurfaceHolder holder, int format, int widht, int height){
342         gLogger.error("surfaceChanged");
343         try {
344             mCamera.setPreviewDisplay(holder);
345             mCamera.startPreview();
346         } catch (Exception e){
347             gLogger.error("Error starting camera previewe: " + e.getMessage());
348             Toast.makeText(this, "Camera Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
349         }
350     }
351
352     @Override
353     public void surfaceDestroyed(SurfaceHolder holder){
354         Log.e(TAG, "surfaceDestroyed");
355     }
356
357     @Override
358     public void  onPreviewFrame(final byte[] data, Camera camera){
359         gLogger.error("onPreviewFrame");
360         if (null != mStreamTask){
361             switch (mStreamTask.getStatus()){
362                 case RUNNING:
363                     Log.e(TAG, "onPreviewFrame Running");
364                     return;
365                 case PENDING:
366                     Log.e(TAG,"OnPreviewFrame Pending");
367                     mStreamTask.cancel(false);
368                     break;
369             }
370         }
371         mStreamTask = new StreamTask(data);
372         mStreamTask.execute((Void)null);
373
374
375 //        ong endTime = System.currentTimeMillis();
376 //        mExecutor.execute(new Runnable() {
377 //            @Override
378 //            public void run() {
379 //                //long encodeTime = System.currentTimeMillis();
380 //                ffmpeg.process(data);
381                 //Log.e(TAG, "编码第:" + (encodeCount++) + "帧,耗时:" + (System.currentTimeMillis() - encodeTime));
382 //            }
383 //        });
384         //Log.e(TAG, "采集第:" + (++count) + "帧,距上一帧间隔时间:"
385 //                + (endTime - previewTime) + "  " + Thread.currentThread().getName());
386 //        previewTime = endTime;*/
387
388     }
389
390     // private
391     private boolean checkCameraHardware(Context context) {
392         return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
393     }
394
395     private static Camera getCameraInstance(){
396         Camera c = null;
397         try {
398             Log.e(TAG, "Open Camera");
399             c = Camera.open(1);
400         } catch (Exception e){
401             e.printStackTrace();
402         }
403         return c;
404     }
405
406     private void configCamera(Camera camera){
407         Camera.Parameters paras = camera.getParameters();
408         gLogger.error("Supported Picture Sizes:");
409         for (Camera.Size cc : paras.getSupportedPictureSizes()){
410             gLogger.error(cc.width + "x" + cc.height);
411         }
412         gLogger.error("Supported Preview fps range:");
413         for(int[] i : paras.getSupportedPreviewFpsRange()){
414             gLogger.error("[" + i[0] + "," + i[1] + "]");
415         }
416         gLogger.error("Set parameters");
417         camera.setParameters(paras);
418         camera.setDisplayOrientation(0);
419         gLogger.error("Preview Format: " + paras.getPreviewFormat() + ". Size: " + paras.getPreviewSize().width + "x" + paras.getPreviewSize().height);
420         gLogger.error("Picture Format: " + paras.getPictureFormat() + ". Size: " + paras.getPictureSize().width + "x" + paras.getPictureSize().height);
421
422         try {
423             camera.setPreviewDisplay(mHolder);
424         } catch (IOException e){
425             e.printStackTrace();
426         }
427         camera.setPreviewCallback(this);
428     }
429
430     private void switchToBackground(){
431         Intent i = new Intent();
432         i.setAction(Intent.ACTION_MAIN);
433         i.addCategory(Intent.CATEGORY_HOME);
434         this.startActivity(i);
435     }
436
437     private String getMacAddr() {
438         WifiManager manager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
439         WifiInfo info = manager.getConnectionInfo();
440         return info.getMacAddress().replace(":", ""); //02:00:00:00:00:00 - 020000000000
441     }
442
443     private void loadConfig() {
444         UserInfo info = UserInfo.getConfig();
445         mTextServer.setText(info.server.equals("") ? "rtmp://gpussh.suanzi.ai:1935/myapp" :  info.server);
446         mTextUser.setText(info.user.equals("") ? "suanzi" : info.user );
447         mTextCamera.setText(info.cameraId.equals("") ?  "001" : info.cameraId);
448         mMacAddr = info.macAddr.equals("") ?  this.mMacAddr : info.macAddr;
449         gLogger.debug("loadConfig " + info.toString());
450     }
451
452     private void saveConfig() {
453         UserInfo info = UserInfo.getConfig();
454         info.update(mTextServer.getText().toString(), mTextUser.getText().toString(), mMacAddr, mTextCamera.getText().toString());
455         if(info.saveConfig()) {
456             Toast.makeText(getApplicationContext(), "Config saved", Toast.LENGTH_LONG).show();
457         } else {
458             Toast.makeText(getApplicationContext(), "Error: config saved", Toast.LENGTH_LONG).show();
459         }
460         gLogger.error("saveConfig: " + info.toString());
461     }
462
463     private void changePermission(){
464         try {
465             Log.e(TAG, "change permission");
466             //Process sh = Runtime.getRuntime().exec(new String[]{"su", "-c", "chmod 666 /dev/video0"});
467
468             Process sh = Runtime.getRuntime().exec("/system/xbin/su", null,null);
469             //Process sh = Runtime.getRuntime().exec("su", null,null);
470
471             OutputStream  os = sh.getOutputStream();
472             os.write(("/system/bin/chmod 666 /dev/video0").getBytes("ASCII"));
473             //os.write(("/system/bin/echo 'wowo' >> /data/local/test").getBytes("ASCII"));
474             os.flush();
475             os.close();
476             sh.waitFor();
477
478
479         }catch (Exception e){
480             e.printStackTrace();
481         }
482     }
483 }