- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试构建一个带有摄像头的应用程序,当连接从 3G/4G 或其他方式更改为 Wi-Fi 时,该应用程序会执行某些操作。为了检测何时发生这种情况,我使用了一个扩展 BroadCastReceiver 的类:
public class WifiReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
boolean syncPopup = sharedPref.getBoolean("syncPopup", true);
if (syncPopup) {
DigginSQLiteHelper db = new DigginSQLiteHelper(context);
if (db.getAllToBeSyncedPhotos().size() > 0) {
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = null;
if (manager != null) {
networkInfo = manager.getActiveNetworkInfo();
}
SharedPreferences sharedPref2 = context.getSharedPreferences(context.getString(R.string.connType), Context.MODE_PRIVATE);
int connType = sharedPref2.getInt(context.getString(R.string.connType), 0);
if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI && networkInfo.isConnectedOrConnecting() && connType != ConnectivityManager.TYPE_WIFI) {
showNotification(context);
}
SharedPreferences.Editor editor = sharedPref2.edit();
editor.putInt(context.getString(R.string.connType), networkInfo.getType());
editor.commit();
}
} else {
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo;
if (manager != null) {
networkInfo = manager.getActiveNetworkInfo();
SharedPreferences.Editor editor= context.getSharedPreferences(context.getString(R.string.connType), Context.MODE_PRIVATE).edit();
editor.putInt(context.getString(R.string.connType), networkInfo.getType());
editor.commit();
}
}
}
private void showNotification(Context context) {
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
new Intent(context, MainActivity.class), 0);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.icon_camera)
.setContentTitle("My notification")
.setContentText("Connected to Wifi, ready to sync!");
mBuilder.setContentIntent(contentIntent);
mBuilder.setDefaults(Notification.DEFAULT_SOUND);
mBuilder.setAutoCancel(true);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, mBuilder.build());
}
}
但是每当我的相机的 Activity 打开和关闭时,WifiReceiver 都会将其检测为更改(这不是我想要的,我只希望当用户通过 WiFi 连接时发生这种情况)。我只是不知道要检查什么或做什么,以便在打开/关闭 CameraActivity 时不会调用 showNotification(Context context)
。
这是相机 Activity :
package com.example.sition.diggin;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import com.example.sition.diggin.compass.BearingToNorthProvider;
import com.example.sition.diggin.misc.CameraView;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
@SuppressWarnings("deprecation")
public class CameraActivity extends AppCompatActivity implements BearingToNorthProvider.ChangeEventListener {
//region fields
private Camera mCamera;
private CameraView mCameraView;
private float mDist = 0f;
private String flashMode;
private ImageButton flashButton;
private Intent intent;
private BearingToNorthProvider mBearingProvider;
private boolean pictureTaken = false;
private byte[] currentData;
private double bearing;
private double currentBearing = 0d;
private String cardinalDirection = "?";
private double rotation = 0d;
private final int REQUEST_CODE_ASK_PERMISSIONS = 2;
//endregion
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
mCamera = getCameraInstance();
mCameraView = new CameraView(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mCameraView);
ImageButton captureButton = (ImageButton) findViewById(R.id.btnCapture);
captureButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Camera.Parameters params = mCamera.getParameters();
params.setFlashMode(flashMode);
mCamera.setParameters(params);
mCamera.takePicture(null, null, mPicture);
}
});
SharedPreferences sharedPref = this.getSharedPreferences(getString(R.string.flashMode), Context.MODE_PRIVATE);
flashMode = sharedPref.getString(getString(R.string.flashMode), Camera.Parameters.FLASH_MODE_OFF);
flashButton = (ImageButton) findViewById(R.id.btnFlash);
setFlashButton();
mBearingProvider = new BearingToNorthProvider(this,this);
mBearingProvider.setChangeEventListener(this);
mBearingProvider.start();
}
@Override
protected void onPause() {
super.onPause();
mBearingProvider.stop();
}
/**
* Helper method to access the camera returns null if it cannot get the
* camera or does not exist
*
* @return the instance of the camera
*/
private Camera getCameraInstance() {
Camera camera = null;
try {
camera = Camera.open();
} catch (Exception e) {
Log.e("CamException", e.toString());
}
return camera;
}
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
currentData = data;
mBearingProvider.updateBearing();
bearing = mBearingProvider.getBearing();
cardinalDirection = bearingToString(bearing);
Log.e("Direction", cardinalDirection + "," + bearing);
findViewById(R.id.btnFlash).setVisibility(View.INVISIBLE);
findViewById(R.id.btnCapture).setVisibility(View.INVISIBLE);
findViewById(R.id.ivCompass).setVisibility(View.INVISIBLE);
findViewById(R.id.ivFocusPoint).setVisibility(View.INVISIBLE);
findViewById(R.id.ivCompassPointer).setVisibility(View.INVISIBLE);
findViewById(R.id.pictureOverlay).setVisibility(View.VISIBLE);
}
};
//region Picture Intents
/**
* Method that puts the necessary data in the intent and then sends it back to the ProjectOverview
* @param v the view that activated this method
*/
public void confirmPicture(View v) {
String path = createFile(currentData);
intent = new Intent();
intent.putExtra("path", path);
String description = String.valueOf(((EditText) findViewById(R.id.tvPictureDesc)).getText());
intent.putExtra("direction", cardinalDirection);
intent.putExtra("description", description);
//close this Activity...
setResult(Activity.RESULT_OK, intent);
finish();
}
/**
* Method that puts no data in the intent and then sends it back to the ProjectOverview
* @param v the view that activated this method
*/
public void deletePicture(View v) {
setResult(Activity.RESULT_CANCELED);
finish();
}
/**
* Method that restarts the camera giving the user a change to retake the picture
* @param v the view that activated this method
*/
public void retryPicture(View v) {
findViewById(R.id.btnFlash).setVisibility(View.VISIBLE);
findViewById(R.id.btnCapture).setVisibility(View.VISIBLE);
findViewById(R.id.ivCompass).setVisibility(View.VISIBLE);
findViewById(R.id.ivFocusPoint).setVisibility(View.VISIBLE);
findViewById(R.id.ivCompassPointer).setVisibility(View.VISIBLE);
findViewById(R.id.pictureOverlay).setVisibility(View.INVISIBLE);
pictureTaken = false;
mCamera.startPreview();
}
//endregion
//region File Methods
/**
* Method that creates a file from the given byte array and saves the file in the Pictures Directory
* @param data is the array of bytes that represent the picture taken by the camera
* @return the path of created file
*/
private String createFile(byte[] data){
checkFilePermissions();
File picFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + File.separator + "tempPic.jpg" + File.separator);
String path = picFile.getPath();
try {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(picFile));
bos.write(data);
bos.flush();
bos.close();
return path;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
/**
* Checks the permission for reading to and writing from the external storage
*/
private void checkFilePermissions() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
int hasWriteExternalStoragePermission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (hasWriteExternalStoragePermission != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_CODE_ASK_PERMISSIONS);
}
}
}
//endregion
//region Zoom Methods
@Override
public boolean onTouchEvent(MotionEvent event) {
// Get the pointer ID
Camera.Parameters params = mCamera.getParameters();
int action = event.getAction();
if (event.getPointerCount() > 1) {
// handle multi-touch events
if (action == MotionEvent.ACTION_POINTER_DOWN) {
mDist = getFingerSpacing(event);
} else if (action == MotionEvent.ACTION_MOVE && params.isZoomSupported()) {
mCamera.cancelAutoFocus();
handleZoom(event, params);
}
} else {
// handle single touch events
if (action == MotionEvent.ACTION_UP) {
handleFocus(event, params);
}
}
return true;
}
/**
* Method that handles the zoom of the camera
* @param event the event that activated this method
* @param params the parameters of the camera
*/
private void handleZoom(MotionEvent event, Camera.Parameters params) {
int maxZoom = params.getMaxZoom();
int zoom = params.getZoom();
float newDist = getFingerSpacing(event);
if (newDist > mDist) {
//zoom in
if (zoom < maxZoom)
zoom++;
} else if (newDist < mDist) {
//zoom out
if (zoom > 0)
zoom--;
}
mDist = newDist;
params.setZoom(zoom);
mCamera.setParameters(params);
}
/**
* Method that handles the focus of the camera when zooming
* @param event the event that activated this method
* @param params the parameters of the camera
*/
private void handleFocus(MotionEvent event, Camera.Parameters params) {
int pointerId = event.getPointerId(0);
int pointerIndex = event.findPointerIndex(pointerId);
// Get the pointer's current position
List<String> supportedFocusModes = params.getSupportedFocusModes();
if (supportedFocusModes != null && supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean b, Camera camera) {
// currently set to auto-focus on single touch
}
});
}
}
/** Determine the space between the first two fingers */
private float getFingerSpacing(MotionEvent event) {
double x = event.getX(0) - event.getX(1);
double y = event.getY(0) - event.getY(1);
return (float) Math.sqrt(x * x + y * y);
}
//endregion
//region Flash Methods
/**
* Method that changes the flash mode the camera currently uses (on/off/auto)
* @param v the view that activated this method
*/
public void changeFlashMode(View v) {
switch (flashMode) {
case Camera.Parameters.FLASH_MODE_ON :
flashMode = Camera.Parameters.FLASH_MODE_AUTO;
break;
case Camera.Parameters.FLASH_MODE_AUTO :
flashMode = Camera.Parameters.FLASH_MODE_OFF;
break;
case Camera.Parameters.FLASH_MODE_OFF :
flashMode = Camera.Parameters.FLASH_MODE_ON;
break;
}
SharedPreferences sharedPref = getSharedPreferences(getString(R.string.flashMode), Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString(getString(R.string.flashMode), flashMode);
editor.commit();
setFlashButton();
}
/**
* Method that changes the image of the button based on flash mode
*/
private void setFlashButton() {
switch (flashMode) {
case Camera.Parameters.FLASH_MODE_ON :
flashButton.setImageDrawable(getResources().getDrawable(R.drawable.camera_flash_on));
break;
case Camera.Parameters.FLASH_MODE_AUTO :
flashButton.setImageDrawable(getResources().getDrawable(R.drawable.camera_flash_auto));
break;
case Camera.Parameters.FLASH_MODE_OFF :
flashButton.setImageDrawable(getResources().getDrawable(R.drawable.camera_flash_off));
break;
}
}
//endregion
//region Bearing Methods
/**
* Method that gives a cardinal direction based on the current bearing to the true north
* @param bearing is the bearing to the true north
* @return cardinal direction that belongs to the bearing
*/
private String bearingToString(Double bearing) {
String strHeading = "?";
if (isBetween(bearing,-180.0,-157.5)) { strHeading = "South"; }
else if (isBetween(bearing,-157.5,-112.5)) { strHeading = "SouthWest"; }
else if (isBetween(bearing,-112.5,-67.5)) { strHeading = "West"; }
else if (isBetween(bearing,-67.5,-22.5)) { strHeading = "NorthWest"; }
else if (isBetween(bearing,-22.5,22.5)) { strHeading = "North"; }
else if (isBetween(bearing,22.5,67.5)) { strHeading = "NorthEast"; }
else if (isBetween(bearing,67.5,112.5)) { strHeading = "East"; }
else if (isBetween(bearing,112.5,157.5)) { strHeading = "SouthEast"; }
else if (isBetween(bearing,157.5,180.0)) { strHeading = "South"; }
return strHeading;
}
/**
* Method that checks if a certain number is in a certain range of numbers
* @param x is the number to check
* @param lower is the number that defines the lower boundary of the number range
* @param upper is the number that defines the upper boundary of the number range
* @return true if the number is between the other numbers, false otherwise
*/
private boolean isBetween(double x, double lower, double upper) {
return lower <= x && x <= upper;
}
/*
Method that triggers when the bearing changes, it sets the current bearing and sends an updated context to the provider
*/
@Override
public void onBearingChanged(double bearing) {
this.bearing = bearing;
mBearingProvider.setContext(this);
ImageView image = (ImageView) findViewById(R.id.ivCompass);
if (image.getVisibility() == View.VISIBLE) {
// create a rotation animation (reverse turn degree degrees)
if (bearing < 0) {
bearing += 360;
}
RotateAnimation ra = new RotateAnimation((float) currentBearing, (float) -bearing, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
// how long the animation will take place
ra.setDuration(210);
// set the animation after the end of the reservation status
ra.setFillAfter(true);
// Start the animation
image.startAnimation(ra);
rotation += currentBearing + bearing;
currentBearing = -bearing;
} else if (!pictureTaken){
ImageView image2 = (ImageView) findViewById(R.id.ivCompass2);
image2.setRotation((float) -rotation);
image.clearAnimation();
pictureTaken = true;
}
mBearingProvider.setContext(this);
}
//endregion
}
编辑:
更糟糕的是,WifiReceiver 似乎也在应用程序的其他位置调用 onReceive(似乎是随机的)。
编辑2:
我不知道这是否有帮助,但这里是 list 中有关 WifiReceiver 的一段代码:
<receiver android:name=".misc.WifiReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
最佳答案
在寻找答案很长一段时间后,我偶然发现了 this post 。我发现我在 Intent 过滤器中使用了错误的操作,所以现在我正在使用:
<receiver android:name=".misc.WifiReceiver">
<intent-filter>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED"/>
<action android:name="android.net.wifi.STATE_CHANGE"/>
</intent-filter>
</receiver>
我还没有机会在我希望它工作的确切情况下测试它,但目前看来它工作得很好。
关于java - 打开相机时调用 CONNECTIVITY_CHANGE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36307014/
SQLite、Content provider 和 Shared Preference 之间的所有已知区别。 但我想知道什么时候需要根据情况使用 SQLite 或 Content Provider 或
警告:我正在使用一个我无法完全控制的后端,所以我正在努力解决 Backbone 中的一些注意事项,这些注意事项可能在其他地方更好地解决......不幸的是,我别无选择,只能在这里处理它们! 所以,我的
我一整天都在挣扎。我的预输入搜索表达式与远程 json 数据完美配合。但是当我尝试使用相同的 json 数据作为预取数据时,建议为空。点击第一个标志后,我收到预定义消息“无法找到任何内容...”,结果
我正在制作一个模拟 NHL 选秀彩票的程序,其中屏幕右侧应该有一个 JTextField,并且在左侧绘制弹跳的选秀球。我创建了一个名为 Ball 的类,它实现了 Runnable,并在我的主 Draf
这个问题已经有答案了: How can I calculate a time span in Java and format the output? (18 个回答) 已关闭 9 年前。 这是我的代码
我有一个 ASP.NET Web API 应用程序在我的本地 IIS 实例上运行。 Web 应用程序配置有 CORS。我调用的 Web API 方法类似于: [POST("/API/{foo}/{ba
我将用户输入的时间和日期作为: DatePicker dp = (DatePicker) findViewById(R.id.datePicker); TimePicker tp = (TimePic
放宽“邻居”的标准是否足够,或者是否有其他标准行动可以采取? 最佳答案 如果所有相邻解决方案都是 Tabu,则听起来您的 Tabu 列表的大小太长或您的释放策略太严格。一个好的 Tabu 列表长度是
我正在阅读来自 cppreference 的代码示例: #include #include #include #include template void print_queue(T& q)
我快疯了,我试图理解工具提示的行为,但没有成功。 1. 第一个问题是当我尝试通过插件(按钮 1)在点击事件中使用它时 -> 如果您转到 Fiddle,您会在“内容”内看到该函数' 每次点击都会调用该属
我在功能组件中有以下代码: const [ folder, setFolder ] = useState([]); const folderData = useContext(FolderContex
我在使用预签名网址和 AFNetworking 3.0 从 S3 获取图像时遇到问题。我可以使用 NSMutableURLRequest 和 NSURLSession 获取图像,但是当我使用 AFHT
我正在使用 Oracle ojdbc 12 和 Java 8 处理 Oracle UCP 管理器的问题。当 UCP 池启动失败时,我希望关闭它创建的连接。 当池初始化期间遇到 ORA-02391:超过
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve
引用这个plunker: https://plnkr.co/edit/GWsbdDWVvBYNMqyxzlLY?p=preview 我在 styles.css 文件和 src/app.ts 文件中指定
为什么我的条形这么细?我尝试将宽度设置为 1,它们变得非常厚。我不知道还能尝试什么。默认厚度为 0.8,这是应该的样子吗? import matplotlib.pyplot as plt import
当我编写时,查询按预期执行: SELECT id, day2.count - day1.count AS diff FROM day1 NATURAL JOIN day2; 但我真正想要的是右连接。当
我有以下时间数据: 0 08/01/16 13:07:46,335437 1 18/02/16 08:40:40,565575 2 14/01/16 22:2
一些背景知识 -我的 NodeJS 服务器在端口 3001 上运行,我的 React 应用程序在端口 3000 上运行。我在 React 应用程序 package.json 中设置了一个代理来代理对端
我面临着一个愚蠢的问题。我试图在我的 Angular 应用程序中延迟加载我的图像,我已经尝试过这个2: 但是他们都设置了 src attr 而不是 data-src,我在这里遗漏了什么吗?保留 d
我是一名优秀的程序员,十分优秀!