How to capture and pass Mat object to a new activity? - java

I am planning on implementing ocr, the idea is for the user to capture an image and the app will write it as text to a file on the phone. I have managed to display the feed from the camera to the javacameraview using CvCameraViewListener2.
I now want to capture the frame as an Mat object and pass it to a new activity. The solution's I saw all involve saving the photo, or displaying the processed image or live processing. I just need to pass the Mat to another class for processing then I can release it. I'm having trouble find a methodology for doing this though it seems as though it should be fairly straightforward.
The question is essentially how to get the Mat object from the cameraview?
Any help or direction would be greatly appreciated.
Thank you stackoverflow
The relevant code is here
import android.Manifest;
import android.content.Intent;
Import android.content.pm.ActivityInfo; importandroid.content.pm.PackageManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
Import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_CAMERA_PERMISSION_RESULT = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getResources().getConfiguration().orientation != 90) {
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
}
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.cameraInit);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//marshmallow permissions
takePhoto();
}
});
}
private void callCamera(){
Intent startCameraIntent = new Intent(getApplicationContext(), OpenCVCamera.class);
startActivity(startCameraIntent);
}
public void takePhoto() {
if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
if(ContextCompat.checkSelfPermission(this,
Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED){
callCamera();
} else {
if(shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)){
Toast.makeText(this, "This app requires camera access", Toast.LENGTH_SHORT).show();
}
requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION_RESULT);
}
} else {
callCamera();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if(requestCode == REQUEST_CAMERA_PERMISSION_RESULT){
if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
callCamera();
} else {
Toast.makeText(this, "Permission Denied.", Toast.LENGTH_SHORT).show();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
import android.content.pm.ActivityInfo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceView;
import android.view.WindowManager;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Core;
import org.opencv.core.Mat;
public class OpenCVCamera extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener2{
// need to correct view size (i think this can be done in the xml
// else refer to cmaera video app
// also orientation needs to be corrected
private static final String TAG = "OpenCVCamera";
private CameraBridgeViewBase cameraBridgeViewBase;
private BaseLoaderCallback baseLoaderCallback = new BaseLoaderCallback(this) {
#Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
cameraBridgeViewBase.enableView();
break;
default:
super.onManagerConnected(status);
break;
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_open_cvcamera);
cameraBridgeViewBase = (CameraBridgeViewBase) findViewById(R.id.camera_view);
cameraBridgeViewBase.setVisibility(SurfaceView.VISIBLE);
cameraBridgeViewBase.setCvCameraViewListener(this);
}
#Override
public void onResume(){
super.onResume();
if (!OpenCVLoader.initDebug()) {
Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_1_0, this, baseLoaderCallback);
} else {
Log.d(TAG, "OpenCV library found inside package. Using it!");
baseLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
}
#Override
public void onCameraViewStarted(int width, int height) {
}
#Override
public void onCameraViewStopped() {
}
#Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
//original just returns inputFrame.rgba()
Core.rotate(inputFrame.rgba(), inputFrame.rgba(), Core.ROTATE_90_CLOCKWISE); //ROTATE_180 or ROTATE_90_COUNTERCLOCKWISE
return inputFrame.rgba();
}
}

Related

onCreate being called twice causing app to exit prematurely

I went through the other SO posts but didn't find anything relevant to my problem.
I am trying to create an app that will get the user's step count from the last reboot. Here is my main Activity:
package com.assignment.bwowassignment;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import java.util.Arrays;
public class MainActivity extends AppCompatActivity implements MainActivityContract.View {
MainActivityPresenter presenter;
#RequiresApi(api = Build.VERSION_CODES.Q)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
Log.d("mihir", "hello");
presenter = new MainActivityPresenter(this);
presenter.requestActivityPermission(this);
}
#Override
public void onGetStepsSuccess(float[] values) {
Log.d("mihir", Arrays.toString(values));
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == presenter.ACTIVITY_REQUEST_CODE)
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
presenter.registerListener(this);
else {
Log.d("mihir", "kill me");
finish();
}
}
#Override
protected void onPause() {
super.onPause();
presenter.sensorManager.unregisterListener(presenter);
}
}
MainActivityPresenter.java
package com.assignment.bwowassignment;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Build;
import android.util.Log;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.util.logging.Logger;
public class MainActivityPresenter implements MainActivityContract.Presenter, SensorEventListener {
MainActivityContract.View view;
SensorManager sensorManager;
Sensor sensor;
public MainActivityPresenter(MainActivityContract.View view) {
this.view = view;
sensorManager = (SensorManager) ((Context) view).getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
}
#Override
public void registerListener(Context context) {
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
}
#RequiresApi(api = Build.VERSION_CODES.Q)
#Override
public void requestActivityPermission(Context context) {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACTIVITY_RECOGNITION) == PackageManager.PERMISSION_GRANTED)
registerListener(context);
else if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, Manifest.permission.ACTIVITY_RECOGNITION))
new AlertDialog.Builder(context)
.setTitle("Permission required")
.setMessage("This permission is required to fetch the sensor data from your phone, denying it will cause the app to exit")
.setPositiveButton("Give permission", (dialog, which) -> ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.ACTIVITY_RECOGNITION}, ACTIVITY_REQUEST_CODE))
.setNegativeButton("Deny", (dialog, which) -> ((Activity) context).finish())
.show();
else
ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.ACTIVITY_RECOGNITION}, ACTIVITY_REQUEST_CODE);
}
#Override
public void onSensorChanged(SensorEvent event) {
view.onGetStepsSuccess(event.values);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
MainActivityContract.java
package com.assignment.bwowassignment;
import android.content.Context;
public interface MainActivityContract {
interface View {
void onGetStepsSuccess(float[] values);
}
interface Presenter {
int ACTIVITY_REQUEST_CODE = 1;
void registerListener(Context context);
void requestActivityPermission(Context context);
}
}
As you can see there are two Logs with my name in the tag, what is happening here is the "hello" log is getting logged twice. I am guessing it's the first onCreate which is responsible for my app finishing before starting since I get this warning in the logcat:
W/Activity: Can request only one set of permissions at a time
I am only requesting one permission but due to the onCreate being called twice the first permission gets automatically denied which causes the app to finish() before it already started! I have been scratching my head over this since yesterday, any help is appreciated!
I figured it out!
The culprit was this line:
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
So apparently, this causes a configuration change, causing the onCreate method to be called twice, to get over this, call it BEFORE the call to super in onCreate like this:
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Running speed monitoring app assistance

I am trying to write an app which constantly monitors the speed at which I run and tells me to speed up if I am running slow and vice verse. My code has no errors, but my TextView text doesn't change as it's supposed to as per my code. Please take a look at my mainActivity.java code:
package com.example.kaushik.speed_measurement;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.speech.tts.TextToSpeech;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
import java.util.Locale;
public class MainActivity extends AppCompatActivity implements LocationListener {
TextToSpeech toSpeech;
int status;
String text;
String text1;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LocationManager lm = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
this.onLocationChanged(null);
toSpeech=new TextToSpeech(MainActivity.this, new TextToSpeech.OnInitListener(){
#Override
public void onInit(int i) {
if ( status ==TextToSpeech.SUCCESS) {
toSpeech.setLanguage(Locale.UK);
}
else{
Toast.makeText(getApplicationContext(), "Feature not supported",
Toast.LENGTH_SHORT).show();
}
}
});
}
#Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
#Override
public void onLocationChanged(Location location) {
TextView txt = (TextView) this.findViewById(R.id.speed);
if (location==null){
txt.setText("-,- m/s");
}
else{
float nCurrentSpeed=location.getSpeed();
txt.setText(nCurrentSpeed + "m/s");
if (nCurrentSpeed<5) {
TextView txt1 = (TextView) this.findViewById(R.id.message);
txt.setText("Speed up!");
text = ("Speed up");
toSpeech.speak(text, TextToSpeech.QUEUE_FLUSH,null);
}
else{
TextView txt1 = (TextView) this.findViewById(R.id.message);
txt1.setText("Slow down");
text1 = ("Slow down");
toSpeech.speak(text1, TextToSpeech.QUEUE_FLUSH,null);
}
}
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
}

QR scanning, result - "com.google.android.gms.vision.barcode.Barcode#ecd6456"

I have problem, dont know what to do, Goal is to make QR scanner, you enter value then press OK it should store the values in object podaci and to use same values in other activitiy.
But what happens it scans QR code but it doesnt show real value it shows something like this : "com.google.android.gms.vision.barcode.Barcode#ecd6456" and there is no value stored in object podaci in MainActivity.
here is my QR class :
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.SparseArray;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.example.irhad.mytestapplication.data.Podaci;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.vision.CameraSource;
import com.google.android.gms.vision.Detector;
import com.google.android.gms.vision.barcode.Barcode;
import com.google.android.gms.vision.barcode.BarcodeDetector;
import java.io.IOException;
public class QRActivity extends AppCompatActivity{
SurfaceView camera_preview;
Intent main;
EditText txtUnosUplacenog;
TextView txtQRIspis;
Button btnOK;
private Podaci podaci;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.qr_activity);
camera_preview = findViewById(R.id.camera_preview);
txtUnosUplacenog = findViewById(R.id.txtUnosUplacenog);
btnOK = findViewById(R.id.btnOK);
txtQRIspis = findViewById(R.id.txtQRIspis);
podaci = new Podaci();
createCameraSource();
}
private void createCameraSource() {
BarcodeDetector barcodeDetector = new BarcodeDetector.Builder(this).build();
final CameraSource cameraSource = new CameraSource.Builder(this, barcodeDetector)
.setAutoFocusEnabled(true)
.setRequestedPreviewSize(620, 480)
.build();
camera_preview.getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
try {
if (ActivityCompat.checkSelfPermission(QRActivity.this,
Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
return;
}
cameraSource.start(camera_preview.getHolder());
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
cameraSource.stop();
}
});//camera_preview
barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
#Override
public void release() {}
#Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
final SparseArray<Barcode> barcodes = detections.getDetectedItems();
if(barcodes.size() > 0){
podaci.setQrvalue(barcodes.valueAt(0).toString());
podaci.setUplata(Double.parseDouble(txtUnosUplacenog.getText().toString()));
txtQRIspis.setText(podaci.getQrvalue());
}
}
});//barcodeDetector
}//CreateCameraSource
public void btnOK(View view){
if(podaci.getUplata() != 0 && podaci.getQrvalue() != "")
izadji(podaci);
}
public void izadji(Podaci podatak){
main = new Intent(this, MainActivity.class);
main.putExtra("barcode", podatak.getQrvalue() );
main.putExtra("vrijednost", podatak.getUplata() );
startActivity(main);
finish();
}
public void izadji(View view){
main = new Intent(this, MainActivity.class);
startActivity(main);
finish();
}
}
And here is my MainActivity class :
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.BatteryManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.example.irhad.mytestapplication.data.Podaci;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.vision.barcode.Barcode;
public class MainActivity extends AppCompatActivity {
Button btnSkenirajQR;
Button btnOpcije;
Button btnExit;
TextView txtIspis;
boolean baterija_ispisano = false;
BroadcastReceiver batteryInfo = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
if(level <= 10 && !baterija_ispisano){
Toast.makeText(getApplicationContext(),
"Molim vas napunite bateriju (<10%)",Toast.LENGTH_LONG);
baterija_ispisano = true;
}else if(level >= 11 && baterija_ispisano){
baterija_ispisano = false;
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnSkenirajQR = findViewById(R.id.btnSkener);
btnOpcije = findViewById(R.id.btnOpcije);
btnExit = findViewById(R.id.btnExit);
txtIspis = findViewById(R.id.txtIspis);
}
public void open_Skener(View view){
Intent qrskeniranje = new Intent(this, QRActivity.class);
startActivityForResult(qrskeniranje,0);
finish();
}
public void open_Opcije(View view){
Intent opcije = new Intent(this, OpcijeActivity.class);
startActivity(opcije);
finish();
}
public void izadji(View view){
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(data != null){
String qr = data.getParcelableExtra("barcode");
String value = data.getParcelableExtra("vrijednost");
txtIspis.setText("Barcode vrijednost : " + qr);
} else {
txtIspis.setText("Nije ocitalo");
}
}
}
Ps :And it is changing value while im holding in front of QR code.
#gr54943, #ac45c04 etc...

How to properly ask for permissions on Runtime?

Hi im making an application using Android Studios the requires 3 permissions in total
CALL_PHONE, READ_CONTACTS, RECORD_AUDIO.
im kinda very new to development and thats why my coding is a bit sloppy(no kidding), when I run the app it doesnt asks for the permission and doesnt work but if i manually go to setting and grant the permissions it works fine
Im using fragments and writing the code in the fragment class is that wrong or should i write this code in my mainActivity.java
Im attaching both please look at my code and how can I improve it
If I have to work from the scratch im ok with it.
DialerActivity.java:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class DialerActivity extends FragmentActivity {
private static final String FRAGMENT_TAG_DIALER = "fragment:dialer";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dialer);
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = (DialerFragment) fm.findFragmentByTag(FRAGMENT_TAG_DIALER);
if(fragment == null){
fragment = new DialerFragment();
fm.beginTransaction()
.add(R.id.fragment_container,fragment, FRAGMENT_TAG_DIALER)
.commit();
}
}
}
DialerFragmnet.java:
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;;
import android.support.v4.content.ContextCompat;
public class DialerFragment extends Fragment {
private EditText mPhoneField;
private Button mDialButton;
//Requesting Permissions on Runtime.
final private int REQUEST_CODE_ASK_PERMISSIONS=0;
private void InitiateCall(){
int hasCallPermission = ContextCompat.checkSelfPermission(getActivity(),Manifest.permission.READ_PHONE_STATE);
if (hasCallPermission != PackageManager.PERMISSION_GRANTED){
requestPermissions(new String[]{Manifest.permission.READ_PHONE_STATE},
REQUEST_CODE_ASK_PERMISSIONS);
return;
}
InitiateCall();
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults ){
switch (requestCode){
case REQUEST_CODE_ASK_PERMISSIONS:
if (grantResults[0]==PackageManager.PERMISSION_GRANTED){
//YAY! PERMISSION GRANTED
InitiateCall();
}else{
//GD! PERMISSION DENIED
Toast.makeText(getActivity(), R.string.permission_denied, Toast.LENGTH_SHORT).show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState){
View v=inflater.inflate(R.layout.fragment_dialer,container,false);
mPhoneField=(EditText) v.findViewById(R.id.input_pno);
mDialButton=(Button) v.findViewById(R.id.dial_button);
mDialButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
try{
if (mPhoneField != null && (mPhoneField.getText().length()==10||mPhoneField.getText().length()==11)){
startActivity(new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + mPhoneField.getText())));
}
else if(mPhoneField != null && mPhoneField.getText().length()==0){
Toast.makeText(getActivity(),R.string.no_number_toast,Toast.LENGTH_SHORT).show();
}
else if(mPhoneField !=null && mPhoneField.getText().length()<10){
Toast.makeText(getActivity(),R.string.wrong_number_toast,Toast.LENGTH_SHORT).show();
}
} catch (Exception e){
Log.e("DialerAppActivity","error: " + e.getMessage(),e);//Runtime error will be logged
}
}
});
return v;
}
}
You actually never call your method that ask the permission.
Your method : InitiateCall should not call itself, because it'll create an infiniteLoop. So you should modify it to be this way:
private void InitiateCall(){
int hasCallPermission = ContextCompat.checkSelfPermission(getActivity(),Manifest.permission.READ_PHONE_STATE);
if (hasCallPermission != PackageManager.PERMISSION_GRANTED){
requestPermissions(new String[]{Manifest.permission.READ_PHONE_STATE},
REQUEST_CODE_ASK_PERMISSIONS);
return;
}
}
and you can call InitiateCall at the end of the onCreateView.

Insert class for scanning ble devices into a Service, to make it work in background in Android

I have a class, and I want that this class works in background. I thought I'd put it in a service, but I do not know how to do it. This is my class called DeviceScanActivity.java:
package com.example.giacomob.myapplication;
/**
* Created by Giacomo B on 20/09/2015.
*/
import android.app.Activity;
import android.app.ListActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
class MyService extends Service{
}
public class DeviceScanActivity extends ListActivity {
MyService service = new MyService();
private LeDeviceListAdapter mLeDeviceListAdapter;
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
private static final int REQUEST_ENABLE_BT = 1;
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 2100000000;
#Override
public void onCreate(Bundle savedInstanceState) {
System.out.println("BLEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE");
super.onCreate(savedInstanceState);
getActionBar().setTitle(R.string.title_devices);
mHandler = new Handler();
// Use this check to determine whether BLE is supported on the device. Then you can
// selectively disable BLE-related features.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
}
// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
// BluetoothAdapter through BluetoothManager.
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// Checks if Bluetooth is supported on the device.
if (mBluetoothAdapter == null) {
Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
finish();
return;
}
scanLeDevice(true);
}
/*
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
if (!mScanning) {
menu.findItem(R.id.menu_stop).setVisible(false);
menu.findItem(R.id.menu_scan).setVisible(true);
menu.findItem(R.id.menu_refresh).setActionView(null);
} else {
menu.findItem(R.id.menu_stop).setVisible(true);
menu.findItem(R.id.menu_scan).setVisible(false);
menu.findItem(R.id.menu_refresh).setActionView(
R.layout.actionbar_indeterminate_progress);
}
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_scan:
mLeDeviceListAdapter.clear();
scanLeDevice(true);
break;
case R.id.menu_stop:
scanLeDevice(false);
break;
}
return true;
}
*/
#Override
protected void onResume() {
super.onResume();
// Ensures Bluetooth is enabled on the device. If Bluetooth is not currently enabled,
// fire an intent to display a dialog asking the user to grant permission to enable it.
if (!mBluetoothAdapter.isEnabled()) {
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
// Initializes list view adapter.
mLeDeviceListAdapter = new LeDeviceListAdapter();
setListAdapter(mLeDeviceListAdapter);
scanLeDevice(true);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// User chose not to enable Bluetooth.
if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
finish();
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
/*
#Override
protected void onPause() {
super.onPause();
scanLeDevice(false);
mLeDeviceListAdapter.clear();
}
*/
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
invalidateOptionsMenu();
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
invalidateOptionsMenu();
}
// Adapter for holding devices found through scanning.
private class LeDeviceListAdapter extends BaseAdapter {
private ArrayList<BluetoothDevice> mLeDevices;
private LayoutInflater mInflator;
public LeDeviceListAdapter() {
super();
mLeDevices = new ArrayList<BluetoothDevice>();
mInflator = DeviceScanActivity.this.getLayoutInflater();
}
public void addDevice(BluetoothDevice device) {
if (!mLeDevices.contains(device)) {
mLeDevices.add(device);
}
}
public BluetoothDevice getDevice(int position) {
return mLeDevices.get(position);
}
public void clear() {
mLeDevices.clear();
}
#Override
public int getCount() {
return mLeDevices.size();
}
#Override
public Object getItem(int i) {
return mLeDevices.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder;
// General ListView optimization code.
if (view == null) {
view = mInflator.inflate(R.layout.listitem_device, null);
viewHolder = new ViewHolder();
viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
BluetoothDevice device = mLeDevices.get(i);
final String deviceName = device.getName();
if (deviceName != null && deviceName.length() > 0)
viewHolder.deviceName.setText(deviceName);
else
viewHolder.deviceName.setText(R.string.unknown_device);
viewHolder.deviceAddress.setText(device.getAddress());
return view;
}
}
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mLeDeviceListAdapter.addDevice(device);
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
}
};
static class ViewHolder {
TextView deviceName;
TextView deviceAddress;
}
}
and I would to insert this class in a Service like this:
package com.example.giacomob.myapplication;
import android.app.Activity;
import android.app.IntentService;
import android.app.ListActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
/**
* Created by Giacomo B on 20/09/2015.
*/
public class LogService extends IntentService
{
public LogService()
{
super("LogService");
}
#Override
protected void onHandleIntent(Intent i)
{
int n=0;
while(true)
{
Log.i("PROVA SERVICE", "Evento n." + n++);
Toast.makeText(this, "Ho aperto il LogService", Toast.LENGTH_SHORT).show();
// Intent second = new Intent(getApplicationContext(), DeviceScanActivity.class);
// startActivity(second);
try {
Thread.sleep(10000);
}
catch (InterruptedException e)
{ }
}
}
How I can do it? Please, help me. Thanks
To run your scanning in the background, you'll want to put all your scanning code in your IntentService. The onHandleIntent method in your service has a similar logical function to your activity's onCreate method, so you can put your initialization code there.
Your activity will launch your service. To schedule regular scans, use either JobScheduler (preferred) or AlarmManager to send intents to launch your service at specified intervals. Be sure to pass your application context rather than your activity context when launching intents so that scanning may occur when your activity has been destroyed.
P.S. Please do not use an infinite loop and a sleep call. This will cause unnecessary blocking on your service thread and waste resources.

Categories