实现短视频、使用本地广播完成UI操作

serial
BlueMatthew 1 year ago
parent 27dfdb7153
commit 4f073d9646

@ -9,6 +9,7 @@
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission
@ -82,7 +83,8 @@
tools:targetApi="28">
<activity
android:name=".video.VideoActivity"
android:exported="false" />
android:exported="false"
android:screenOrientation="landscape" />
<activity
android:name=".ChannelActivity"
android:exported="false"

@ -264,6 +264,7 @@ void CPhoneDevice::SetRecognizationCfg(const IDevice::CFG_RECOGNIZATION* pRecogn
if (m_pRecognizationCfg == NULL && pRecognizationCfg != NULL && (pRecognizationCfg->enabled != 0))
{
// TODO
XYLOG(XYLOG_SEVERITY_DEBUG, "Start init ncnn");
ncnn_init();
std::string paramFile = m_appPath + (APP_PATH_RECOG_PARAM);
std::string binFile = m_appPath + (APP_PATH_RECOG_BIN);

@ -42,6 +42,7 @@ import android.os.SystemClock;
import androidx.core.app.NotificationCompat;
import androidx.core.content.FileProvider;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionManager;
@ -57,6 +58,7 @@ import com.dev.devapi.api.SysApi;
import com.xypower.common.FileDownloader;
import com.xypower.common.InetAddressUtils;
import com.xypower.common.MicroPhotoContext;
import com.xypower.mpapp.video.VideoActivity;
import java.io.File;
import java.io.FileOutputStream;
@ -130,6 +132,7 @@ public class MicroPhotoService extends Service {
protected long mNativeHandle = 0;
private AlarmReceiver mAlarmReceiver = null;
private AlarmReceiver mLocalMsgReceiver = null;
private ScreenActionReceiver mScreenaAtionReceiver = null;
private NetworkChangedReceiver mNetworkChangedReceiver = null;
@ -165,11 +168,11 @@ public class MicroPhotoService extends Service {
mAlarmReceiver = new AlarmReceiver(this);
IntentFilter intentFilter = new IntentFilter(ACTION_HEARTBEAT);
intentFilter.addAction(ACTION_TAKE_PHOTO);
intentFilter.addAction(ACTION_TAKE_PHOTO_MANUALLY);
intentFilter.addAction(ACTION_HEARTBEAT_MANUALLY);
intentFilter.addAction(ACTION_MSG_BROADCAST);
intentFilter.addAction(ACTION_VIDEO_FINISHED);
intentFilter.addAction(ACTION_STOP);
// intentFilter.addAction(ACTION_TAKE_PHOTO_MANUALLY);
// intentFilter.addAction(ACTION_HEARTBEAT_MANUALLY);
// intentFilter.addAction(ACTION_MSG_BROADCAST);
// intentFilter.addAction(ACTION_VIDEO_FINISHED);
// intentFilter.addAction(ACTION_STOP);
// intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
getApplicationContext().registerReceiver(mAlarmReceiver, intentFilter, Context.RECEIVER_EXPORTED | Context.RECEIVER_VISIBLE_TO_INSTANT_APPS);
@ -178,6 +181,20 @@ public class MicroPhotoService extends Service {
// registerRe
}
{
mLocalMsgReceiver = new AlarmReceiver(this);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_HEARTBEAT);
intentFilter.addAction(ACTION_TAKE_PHOTO);
intentFilter.addAction(ACTION_TAKE_PHOTO_MANUALLY);
intentFilter.addAction(ACTION_HEARTBEAT_MANUALLY);
intentFilter.addAction(ACTION_MSG_BROADCAST);
intentFilter.addAction(ACTION_VIDEO_FINISHED);
intentFilter.addAction(ACTION_STOP);
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver (mLocalMsgReceiver, intentFilter);
}
{
mNetworkChangedReceiver = new NetworkChangedReceiver(this);
IntentFilter filter = new IntentFilter();
@ -226,6 +243,8 @@ public class MicroPhotoService extends Service {
getApplicationContext().unregisterReceiver(mScreenaAtionReceiver);
getApplicationContext().unregisterReceiver(mNetworkChangedReceiver);
LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(mLocalMsgReceiver);
for(Map.Entry<String, PowerManager.WakeLock> entry : mWakeLocks.entrySet()) {
try {
PowerManager.WakeLock wl = entry.getValue();
@ -387,6 +406,8 @@ public class MicroPhotoService extends Service {
}
}
}
// Will be called fron native
private void registerHeartbeatTimer(int duration) {
int orgHeartbeatDuration = mHeartbeatDuration;
mHeartbeatDuration = duration;
@ -412,36 +433,42 @@ public class MicroPhotoService extends Service {
private static void registerPhotoTimer(Context context, long scheduleTime, long takingTime, long timeout, List<Long> schedules) {
// 创建延迟意图
Intent alarmIntent = new Intent();
alarmIntent.setAction(ACTION_TAKE_PHOTO);
Intent intent = new Intent();
intent.setAction(ACTION_TAKE_PHOTO);
int cnt = schedules.size();
alarmIntent.putExtra(EXTRA_PARAM_SCHEDULES, cnt);
intent.putExtra(EXTRA_PARAM_SCHEDULES, cnt);
StringBuilder channelStr = new StringBuilder();
long val = 0;
for (int idx = 0; idx < cnt; idx++) {
val = schedules.get(idx).longValue();
alarmIntent.putExtra(EXTRA_PARAM_SCHEDULE + idx, schedules.get(idx).longValue());
intent.putExtra(EXTRA_PARAM_SCHEDULE + idx, schedules.get(idx).longValue());
channelStr.append("(" + ((val & 0XFF0000) >> 16) + "-" + Long.toString (((val & 0XFF00) >> 8), 16).toUpperCase() + ") ");
}
alarmIntent.putExtra(EXTRA_PARAM_TIME, scheduleTime);
alarmIntent.putExtra(EXTRA_PARAM_TAKING_TIME, takingTime);
intent.putExtra(EXTRA_PARAM_TIME, scheduleTime);
intent.putExtra(EXTRA_PARAM_TAKING_TIME, takingTime);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if (timeout == 0) {
// LocalBroadcast
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context);
localBroadcastManager.sendBroadcast(intent);
} else {
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
try {
alarmManager.cancel(pendingIntent);
} catch (Exception ex) {
ex.printStackTrace();
}
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
try {
alarmManager.cancel(pendingIntent);
} catch (Exception ex) {
ex.printStackTrace();
}
long currentTimeMillis = System.currentTimeMillis();
Date date = new Date(currentTimeMillis + timeout);
String dateStr = (String) DateFormat.format("MM-dd kk:mm:ss", date);
Log.d(TAG, "PhotoTimer Reg: " + dateStr + " currentTimeMillis=" + currentTimeMillis + " timeout=" + timeout + " CH-PR=" + channelStr.toString());
long currentTimeMillis = System.currentTimeMillis();
Date date = new Date(currentTimeMillis + timeout);
String dateStr = (String) DateFormat.format("MM-dd kk:mm:ss", date);
Log.d(TAG, "PhotoTimer Reg: " + dateStr + " currentTimeMillis=" + currentTimeMillis + " timeout=" + timeout + " CH-PR=" + channelStr.toString());
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, pendingIntent);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, pendingIntent);
}
}
private void registerPhotoTimer(long scheduleTime, long timeout, List<Long> schedules) {
@ -451,10 +478,8 @@ public class MicroPhotoService extends Service {
public void startRecording(int cameraId, long videoId, int duration, int width, int height, int quality) {
Context context = getApplicationContext();
Intent intent = context.getPackageManager().getLaunchIntentForPackage("com.xypower.mvapp");
if (intent == null) {
return;
}
Intent intent = new Intent(this, VideoActivity.class);
intent.putExtra("cameraId", cameraId);
intent.putExtra("videoId", videoId);
intent.putExtra("duration", duration);
@ -462,8 +487,8 @@ public class MicroPhotoService extends Service {
intent.putExtra("height", height);
intent.putExtra("quality", quality);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
protected boolean updateCaptureSchedule(long startTime) {
@ -502,33 +527,15 @@ public class MicroPhotoService extends Service {
schedules.add(Long.valueOf(val));
registerPhotoTimer(context, 0, ts, 100, schedules);
registerPhotoTimer(context, 0, ts, 0, schedules);
}
public static void sendHeartbeat(Context context) {
Intent alarmIntent = new Intent();
// if(Build.VERSION.SDK_INT >= 26) {
// alarmIntent.addFlags(0x01000000);
//}
// String className = AlarmReceiver.class.getName();
// alarmIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
// context.startService(alarmIntent);
// alarmIntent.setComponent(new ComponentName(context.getPackageName(), className));
// alarmIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// alarmIntent.setPackage(context.getPackageName());
alarmIntent.setAction(ACTION_HEARTBEAT_MANUALLY);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);
// context.sendBroadcast(alarmIntent);
// context.sendBroadcast(alarmIntent);
// LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context);
// localBroadcastManager.sendBroadcast(alarmIntent);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 100, pendingIntent);
Intent intent = new Intent();
intent.setAction(ACTION_HEARTBEAT_MANUALLY);
// PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context);
localBroadcastManager.sendBroadcast(intent);
}
@Override

@ -1,7 +1,9 @@
package com.xypower.mpapp.video;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import com.xypower.mpapp.R;
@ -14,8 +16,30 @@ public class VideoActivity extends AppCompatActivity {
setContentView(R.layout.activity_video);
if (null == savedInstanceState) {
Bundle bundle = new Bundle();
Intent intent = getIntent();
int duration = intent.getIntExtra("duration", 0);
if (intent.hasExtra("cameraId")) {
bundle.putInt("cameraId", intent.getIntExtra("cameraId", 0));
}
if (intent.hasExtra("videoId")) {
bundle.putLong("videoId", intent.getLongExtra("videoId", 0));
}
bundle.putInt("duration", duration);
String act = intent.getStringExtra("action");
if (act != null) {
bundle.putString("action", act);
}
bundle.putInt("width", intent.getIntExtra("width", 0));
bundle.putInt("height", intent.getIntExtra("height", 0));
Fragment fragment = VideoFragment.newInstance();
fragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, VideoFragment.newInstance())
.replace(R.id.container, fragment)
.commit();
}
}

@ -3,8 +3,10 @@ package com.xypower.mpapp.video;
import android.Manifest;
import android.app.Activity;
import android.app.Dialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Matrix;
@ -28,7 +30,9 @@ import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.Fragment;
import androidx.legacy.app.FragmentCompat;
import androidx.legacy.app.FragmentCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
@ -42,6 +46,7 @@ import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;
import com.xypower.mpapp.MicroPhotoService;
import com.xypower.mpapp.R;
import java.io.File;
@ -58,7 +63,10 @@ import java.util.concurrent.TimeUnit;
* Use the {@link VideoFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class VideoFragment extends Fragment implements View.OnClickListener, FragmentCompat.OnRequestPermissionsResultCallback {
public class VideoFragment extends Fragment implements View.OnClickListener, MediaRecorder.OnInfoListener, FragmentCompat.OnRequestPermissionsResultCallback {
public static final String ACTION_FINISH = "com.xypower.mvapp.ACT_FINISH";
public static final String ACTION_MP_VIDEO_FINISHED = "com.xypower.mpapp.ACT_V_FINISHED";
private static final int SENSOR_ORIENTATION_DEFAULT_DEGREES = 90;
private static final int SENSOR_ORIENTATION_INVERSE_DEGREES = 270;
@ -88,6 +96,10 @@ public class VideoFragment extends Fragment implements View.OnClickListener, Fra
INVERSE_ORIENTATIONS.append(Surface.ROTATION_270, 0);
}
private String mCameraId;
private long mVideoId = 0;
private int mDuration = 0;
/**
* An {@link AutoFitTextureView} for camera preview.
*/
@ -169,6 +181,8 @@ public class VideoFragment extends Fragment implements View.OnClickListener, Fra
*/
private Handler mBackgroundHandler;
private Handler mMainHandler;
/**
* A {@link Semaphore} to prevent the app from exiting before closing the camera.
*/
@ -212,6 +226,49 @@ public class VideoFragment extends Fragment implements View.OnClickListener, Fra
private String mNextVideoAbsolutePath;
private CaptureRequest.Builder mPreviewBuilder;
public void onInfo(MediaRecorder mr, int what, int extra) {
if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
Log.v(TAG, "Recording Maximum Duration Reached");
final Runnable quitRunnable = new Runnable() {
@Override
public void run() {
getActivity().finish();
}
};
if (mIsRecordingVideo) {
stopRecordingVideo();
Log.i(TAG, "Stop recording");
mMainHandler.post(quitRunnable);
}
}
}
private void broadcastVideoFile(boolean result, String path) {
if (mDuration <= 0) {
return;
}
Context context = getContext();
String receiverName = MicroPhotoService.AlarmReceiver.class.getName();
String packageName = context.getPackageName();
Intent intent = new Intent(ACTION_MP_VIDEO_FINISHED);
// intent.setPackage(packageName);
intent.putExtra("result", result);
intent.putExtra("path", path);
intent.putExtra("videoId", mVideoId);
// intent.setComponent(new ComponentName(packageName, receiverName));
Log.i(TAG, "Notify recording videoId=" + Long.toString(mVideoId) + " " + path);
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(getContext().getApplicationContext());
localBroadcastManager.sendBroadcast(intent);
context.sendBroadcast(intent);
}
public static Fragment newInstance() {
return new VideoFragment();
}
@ -277,12 +334,37 @@ public class VideoFragment extends Fragment implements View.OnClickListener, Fra
mButtonVideo = (Button) view.findViewById(R.id.video);
mButtonVideo.setOnClickListener(this);
view.findViewById(R.id.info).setOnClickListener(this);
mMainHandler = new Handler();
Bundle argument = getArguments();
if (argument != null) {
mCameraId = Integer.toString(argument.getInt("CameraId", 0));
mVideoId = argument.getLong("videoId", 0);
mDuration = argument.getInt("duration", 0);
}
Log.i(TAG, "Recv recording request CameraId=" + mCameraId + " videoId=" + Long.toString(mVideoId));
}
@Override
public void onResume() {
super.onResume();
startBackgroundThread();
Runnable runnable = new Runnable() {
@Override
public void run() {
if (!mIsRecordingVideo) {
Log.i(TAG, "Start recording duration=" + Integer.toString(mDuration));
startRecordingVideo();
}
}
};
if (mDuration > 0) {
mMainHandler.postDelayed(runnable, 1000);
}
if (mTextureView.isAvailable()) {
openCamera(mTextureView.getWidth(), mTextureView.getHeight());
} else {
@ -414,9 +496,10 @@ public class VideoFragment extends Fragment implements View.OnClickListener, Fra
}
configureTransform(width, height);
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setOnInfoListener(this);
manager.openCamera(cameraId, mStateCallback, null);
} catch (CameraAccessException e) {
Toast.makeText(activity, "Cannot access the camera.", Toast.LENGTH_SHORT).show();
// Toast.makeText(activity, "Cannot access the camera.", Toast.LENGTH_SHORT).show();
activity.finish();
} catch (NullPointerException e) {
// Currently an NPE is thrown when the Camera2API is used but not supported on the
@ -477,7 +560,8 @@ public class VideoFragment extends Fragment implements View.OnClickListener, Fra
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
Activity activity = getActivity();
if (null != activity) {
Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show();
broadcastVideoFile(false, "");
// Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show();
}
}
}, mBackgroundHandler);
@ -543,7 +627,12 @@ public class VideoFragment extends Fragment implements View.OnClickListener, Fra
if (null == activity) {
return;
}
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
try {
// mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
} catch (Exception ex) {
}
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
if (mNextVideoAbsolutePath == null || mNextVideoAbsolutePath.isEmpty()) {
@ -555,6 +644,9 @@ public class VideoFragment extends Fragment implements View.OnClickListener, Fra
mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
if (mDuration > 0) {
mMediaRecorder.setMaxDuration(mDuration * 1000);
}
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
switch (mSensorOrientation) {
case SENSOR_ORIENTATION_DEFAULT_DEGREES:
@ -568,9 +660,18 @@ public class VideoFragment extends Fragment implements View.OnClickListener, Fra
}
private String getVideoFilePath(Context context) {
final File dir = context.getExternalFilesDir(null);
return (dir == null ? "" : (dir.getAbsolutePath() + "/"))
+ System.currentTimeMillis() + ".mp4";
// final File dir = context.getExternalFilesDir(null);
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
if (!path.endsWith(File.separator)) {
path += File.separator;
}
path += context.getPackageName() + File.separator;
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
path += System.currentTimeMillis() + ".mp4";
return path;
}
private void startRecordingVideo() {
@ -621,7 +722,8 @@ public class VideoFragment extends Fragment implements View.OnClickListener, Fra
public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
Activity activity = getActivity();
if (null != activity) {
Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show();
broadcastVideoFile(false, "");
// Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show();
}
}
}, mBackgroundHandler);
@ -648,9 +750,10 @@ public class VideoFragment extends Fragment implements View.OnClickListener, Fra
Activity activity = getActivity();
if (null != activity) {
Toast.makeText(activity, "Video saved: " + mNextVideoAbsolutePath,
Toast.LENGTH_SHORT).show();
Log.d(TAG, "Video saved: " + mNextVideoAbsolutePath);
// Toast.makeText(activity, "Video saved: " + mNextVideoAbsolutePath, Toast.LENGTH_SHORT).show();
// Log.d(TAG, "Video saved: " + mNextVideoAbsolutePath);
broadcastVideoFile(true, mNextVideoAbsolutePath);
}
mNextVideoAbsolutePath = null;
startPreview();

Loading…
Cancel
Save