我正在尝试使用相机构建应用程序,该应用程序在连接性从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());
}
}
但是无论何时打开和关闭“我的相机的活动”,WifiReceiver都会将其检测为更改(这不是我想要的,我只希望在用户通过WiFi连接时发生这种情况)。我只是不知道要检查什么或要做什么,因此在打开/关闭CameraActivity时不会调用
showNotification(Context context)
。这是CameraActity:
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:
我不知道这是否有帮助,但这是清单中有关WifiReceiver的一段代码:
<receiver android:name=".misc.WifiReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
最佳答案
在寻找答案一段时间后,我偶然发现了
this post。而且我发现我在意图过滤器中使用了错误的操作,所以现在我在使用:
<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>
我还没有机会在我希望它能正常工作的确切情况下对其进行测试,但是目前看来它工作得很好。