I am using a contact picker to get the number to an editText. The saved contact numbers can be of three types based on how the user saved a particular number.
+911234567899 (with +91 as prefix) [India CountryCode].
01234567899 (with 0 as prefix) [Common STD Code used to call mobile numbers].
1234567899 (without any prefix).
I need to get remove the prefixes (if any) and get the actual 10 digit number without spaces to my editText (some devices put spaces between the numbers for better readability).
Now the issue I am facing is, this works perfect only for the first time you pick each type of contact, Like, It will work for the 1st time you pick a prefixed number and non prefixed number. The next time you try it, it won't work as i need. But works again perfect if we restart the app.
This is the code:
ScreenMain.java
import android.Manifest;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.net.Uri;
import android.provider.ContactsContract;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class ScreenMain extends AppCompatActivity {
private static final int PERMISSION_ALL = 1;
ImageButton btnGetNumber;
EditText etMobileNumber;
private String sMobileNumber = "";
private Uri uriContact;
private String contactID; // contacts unique ID
private static ScreenMain inst;
public static ScreenMain instance() {
return inst;
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_screen_main);
btnGetData = (Button) findViewById(R.id.btndGetStatus);
etMobileNumber = (EditText) findViewById(R.id.etdMobileNumber);
String[] PERMISSIONS = { Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_CONTACTS,
};
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
etMobileNumber.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
}
});
btnGetNumber.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// using native contacts selection
// Intent.ACTION_PICK = Pick an item from the data, returning what was selected.
startActivityForResult(new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI), REQUEST_CODE_PICK_CONTACTS);
}
});
btnGetData.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
// sendSms("mONST");
ClassSMS.sendSms(getApplicationContext(),"mONST",etMobileNumber.getText().toString());
}
});
btnCall.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
// ClassMakeCall.makeCall(getApplicationContext(),etMobileNumber.getText().toString());
String ssMobNumber = etMobileNumber.getText().toString();
if (ssMobNumber.length() == 0) {
Toast.makeText(getApplicationContext(), " Please enter mobile number in the motorON unit", Toast.LENGTH_SHORT).show();
return;
}
if (ssMobNumber.length() != 10) {
Toast.makeText(getApplicationContext(), " Invalid mobile number", Toast.LENGTH_SHORT).show();
return;
}
try {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:+91" + ssMobNumber));
if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
Toast.makeText(getApplicationContext()," SMS Fail, Please goto Settings -> APPS -> motorON -> Permissions and enable SMS permission ", Toast.LENGTH_SHORT).show();
return;
}
startActivity(callIntent);
} catch (ActivityNotFoundException activityException) {
Toast.makeText(getApplicationContext()," unable to make call", Toast.LENGTH_SHORT).show();
}
}
});
ivSettings.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(getApplicationContext(), ScreenSettings.class));
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_PICK_CONTACTS && resultCode == RESULT_OK) {
// Log.d(TAG, "Response: " + data.toString());
uriContact = data.getData();
ClassGetPhoneNumber.retrieveContactNumber(getApplicationContext(),uriContact);
if(ClassGetPhoneNumber.sStatus.equals("OK"))
{
etMobileNumber.setText(ClassGetPhoneNumber.sResponse);
}
}
}
#Override
protected void onStart() {
super.onStart();
inst = this;
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
}
#Override
protected void onRestart(){
super.onRestart();
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
// Log.d(TAG, "atvt restart");
}
#Override
protected void onResume(){
super.onResume();
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
// Log.d(TAG, "atvt resume");
}
#Override
protected void onPause(){
super.onPause();
// Log.d(TAG, "atvt pause");
}
#Override
protected void onStop(){
super.onStop();
// Log.d(TAG, "atvt stop");
}
#Override
protected void onDestroy()
{
super.onDestroy();
// Log.d(TAG, "atvt destroy");
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults)
{
switch (requestCode)
{
case PERMISSION_ALL:
{
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
}
else
{
Toast.makeText(getApplicationContext()," App Needs SMS Permission to Work ", Toast.LENGTH_SHORT).show();
}
return;
}
}
}
}
ClassGetPhoneNumber.java
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.util.Log;
class ClassGetPhoneNumber
{
private static final String TAG = null ;
public static String sStatus="ERROR";
public static String sResponse;
public static String sContactNumber;
public static String sContactNumberFinal;
public static int With91 = 0, With0 = 0, TenDigit = 0, InvalidNumber = 0;
public static String contactID=""; // contacts unique ID
public static String contactNumber = null;
public static void retrieveContactNumber(Context context, Uri uriContact)
{
// getting contacts ID
Cursor cursorID = context.getContentResolver().query(uriContact,
new String[]{ContactsContract.Contacts._ID},
null, null, null);
if (cursorID.moveToFirst()) {
contactID = cursorID.getString(cursorID.getColumnIndex(ContactsContract.Contacts._ID));
}
cursorID.close();
// Using the contact ID now we will get contact phone number
Cursor cursorPhone = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER},
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ? AND " +
ContactsContract.CommonDataKinds.Phone.TYPE + " = " +
ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE,
new String[]{contactID},
null);
contactNumber = null;
if (cursorPhone.moveToFirst()) {
contactNumber = cursorPhone.getString(cursorPhone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
}
cursorPhone.close();
sResponse = null;
sContactNumber = null;
sContactNumberFinal = null;
sContactNumber = contactNumber.replaceAll("\\s","");
int iLength = sContactNumber.length();
if(iLength==13)
With91 = 1;
if(iLength==11)
With0 = 1;
if(iLength==10)
TenDigit = 1;
if(With91 == 1)
{
sContactNumberFinal = sContactNumber.substring(3);
Log.e(TAG,"In With91, sContactNumberFinal : "+sContactNumberFinal);
sResponse = sContactNumberFinal;
sStatus = "OK";
}
if (With0 == 1)
{
sContactNumberFinal = sContactNumber.substring(1);
Log.e(TAG,"In With0, sContactNumberFinal : "+sContactNumberFinal);
sResponse = sContactNumberFinal;
sStatus = "OK";
}
if (TenDigit == 1)
{
sContactNumberFinal = sContactNumber;
Log.e(TAG,"In TenDigit, sContactNumberFinal : "+sContactNumberFinal);
sResponse = sContactNumberFinal;
sStatus = "OK";
}
}
}
I agree with #DaveyDaveDave static fields are not the way to go, but if you insist here's your same code, with lots of fixes and simplified code.
Note that NORMALIZED_NUMBER is only supported from API 16 and above.
class ClassGetPhoneNumber {
...
public static void retrieveContactNumber(Context context, Uri uriContact) {
sResponse = null;
sContactNumber = null;
sContactNumberFinal = null;
// get contactID from contactUri
long contactID = ContentUris.parseId(contactUri);
// Using the contact ID now we will get contact phone number
// Don't add selection by Phone.TYPE as we might miss a lot of phones.
// We ask for the normalized number, this will only work for API 16 and above
Cursor cursorPhone = context.getContentResolver().query(CommonDataKinds.Phone.CONTENT_URI,
new String[]{CommonDataKinds.Phone.NORMALIZED_NUMBER, CommonDataKinds.Phone.NUMBER},
CommonDataKinds.Phone.CONTACT_ID + " = " + contactID,null,null);
contactNumber = null;
if (cursorPhone != null && cursorPhone.moveToFirst()) {
contactNumber = cursorPhone.getString(0); // this number will always be of e164 format: "+<country><local number>"
Log.d(TAG, "normalized number: " + contactNumber + ", original number: " + cursorPhone.getString(1) + ", contact-id: " + contactID);
} else {
// you need to quit here, otherwise you'll be using an old value of contactNumber in the rest of the code.
if (cursorPhone != null) {
cursorPhone.close();
}
return;
}
cursorPhone.close();
if (!TextUtils.isEmpty(contactNumber)) {
sContactNumber = contactNumber;
sContactNumberFinal = sContactNumber.substring(3);
sResponse = sContactNumberFinal;
sStatus = "OK";
} else {
// no phone was found
sStatus = "NOT FOUND";
}
}
}
It's hard to follow your code, because there's an awful lot going on, but I think the root cause will be that everything in your ClassGetPhoneNumber class is static, so the fields in that class are set on the first pass, and their values remain the next time you call the retrieveContactNumber method.
From looking at it, I suspect it's not as simple as it working the first time and not working subsequently, but rather that you get generally 'odd' behaviour, depending on the input.
The simplest solution would be to remove all the static keywords from the ClassGetPhoneNumber class, and to change the call from:
ClassGetPhoneNumber.retrieveContactNumber(getApplicationContext(),uriContact);
to:
new ClassGetPhoneNumber().retrieveContactNumber(getApplicationContext(),uriContact);
I think that will resolve the immediate problems you have.
I figured it out.
The issue was:
The value of the variables which I used to determine how the user has saved a
particular number (With91, With0, TenDigit), was not initialized to zero at the start of the
retrieveContactNumber() method.
Initializing them to zero at the start of the function cleared its previous
values and made it work as intended.
Thanks everyone for your time and support.
-Paul Varghese
Related
I am trying to access all the images that come from MediaStore, but I would like to separate the images coming from it into two different folders; External and Internal memory, where internal memory is the Android device primary storage and external would be something like an SD card. How can I achieve this ?
My code is below.
I have this activity:
package com.projects.timely.gallery;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.projects.timely.R;
#SuppressWarnings("ConstantConditions")
public class StorageViewer extends AppCompatActivity implements View.OnClickListener {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_storage_view);
setSupportActionBar(findViewById(R.id.toolbar));
getSupportActionBar().setTitle("Select Storage");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ViewGroup v_internalStorage = findViewById(R.id.internal_storage);
v_internalStorage.setOnClickListener(this);
ViewGroup v_externalStorage = findViewById(R.id.external_storage);
v_externalStorage.setOnClickListener(this);
boolean ext_str_mounted
= Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
v_externalStorage.setVisibility(ext_str_mounted ? View.VISIBLE : View.GONE);
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.internal_storage) {
startActivity(new Intent(this, ImageDirectory.class)
.putExtra(ImageDirectory.STORAGE_ACCESS_ROOT, ImageDirectory.INTERNAL));
} else {
startActivity(new Intent(this, ImageDirectory.class)
.putExtra(ImageDirectory.STORAGE_ACCESS_ROOT, ImageDirectory.EXTERNAL));
}
finish();
}
#Override
public boolean onSupportNavigateUp() {
super.onBackPressed();
return true;
}
}
That triggers this code. This code is executed within an activity. It is in a file called ImageDirectory.java
#Override
#SuppressLint("InlinedApi")
public void run() {
String root_extra = getIntent().getStringExtra(STORAGE_ACCESS_ROOT);
Uri storageUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
if (root_extra != null) {
storageUri = root_extra.equals(EXTERNAL) ? MediaStore.Images.Media.EXTERNAL_CONTENT_URI
: MediaStore.Images.Media.INTERNAL_CONTENT_URI;
}
String[] projection = {
MediaStore.Images.Media._ID,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
MediaStore.Images.Media.SIZE,
MediaStore.Images.Media.DISPLAY_NAME};
Cursor imgCursor = getApplicationContext()
.getContentResolver()
.query(storageUri, projection, null, null, null);
int bucketId = imgCursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
int imgSize = imgCursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE);
int name = imgCursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME);
int bucketName
= imgCursor.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
List<String> dirName = new ArrayList<>();
while (imgCursor.moveToNext()) {
long id = imgCursor.getLong(bucketId);
int size = imgCursor.getInt(imgSize);
String fileName = imgCursor.getString(name);
String folderName = imgCursor.getString(bucketName);
// Updated this part, replaced with storageUri
Uri contentUri
= ContentUris.withAppendedId(storageUri, id);
Image currentImage = new Image(contentUri, size, fileName, folderName);
int directoryIndex = linearSearch(dirName, folderName);
// if search result (directoryIndex) passes this test, then it means that there is
// no such directory in list of directory names
if (directoryIndex < 0) {
imageDirectoryList.add(new ArrayList<>());
dirName.add(folderName);
directoryIndex = linearSearch(dirName, folderName);
if (directoryIndex >= 0)
imageDirectoryList.get(directoryIndex).add(currentImage);
} else {
imageDirectoryList.get(directoryIndex).add(currentImage);
}
}
imgCursor.close();
runOnUiThread(() -> {
imageAdapter.notifyDataSetChanged();
doViewUpdate();
});
}
I was trying to run this code to take a photo and recognize tho photo owner, at first the user clicks the button Train and takes a picture than enter its name, after that he clicks on Recognize button and take a picture if the picture was saved the apps recognize its face if not it shows unknown person for example. The app runs good but when it crashes sometimes with this error:
FATAL EXCEPTION: main
Process: com.facedetection.app, PID: 7442
java.lang.RuntimeException: Unable to stop activity {com.facedetection.app/com.facedetection.app.TrainActivity}: CvException [org.opencv.core.CvException: cv::Exception: OpenCV(4.0.0-pre) E:\AssemCourses\opencv-master\modules\core\src\matrix.cpp:235: error: (-215:Assertion failed) s >= 0 in function 'setSize'
]
at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:4852)
at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:4915)
at android.app.ActivityThread.access$1600(ActivityThread.java:211)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1759)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6946)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
Caused by: CvException [org.opencv.core.CvException: cv::Exception: OpenCV(4.0.0-pre) E:\AssemCourses\opencv-master\modules\core\src\matrix.cpp:235: error: (-215:Assertion failed) s >= 0 in function 'setSize'
]
at org.opencv.face.FaceRecognizer.train_0(Native Method)
at org.opencv.face.FaceRecognizer.train(FaceRecognizer.java:133)
at com.facedetection.app.TrainActivity.trainfaces(TrainActivity.java:95)
at com.facedetection.app.TrainActivity.onStop(TrainActivity.java:351)
at android.app.Instrumentation.callActivityOnStop(Instrumentation.java:1305)
at android.app.Activity.performStop(Activity.java:6777)
at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:4847)
Here is the classe mentionned in the error logcat:
Class TrainActivity.java:
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.DialogInterface;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.text.InputType;
import android.util.Log;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.facebook.stetho.Stetho;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Rect;
import org.opencv.core.Size;
import org.opencv.face.Face;
import org.opencv.face.FaceRecognizer;
import org.opencv.face.LBPHFaceRecognizer;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import static org.opencv.objdetect.Objdetect.CASCADE_SCALE_IMAGE;
/**
* Created by Assem Abozaid on 6/2/2018.
*/
public class TrainActivity extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener2 {
private static String TAG = TrainActivity.class.getSimpleName();
private CameraBridgeViewBase openCVCamera;
private Mat rgba,gray;
private CascadeClassifier classifier;
private MatOfRect faces;
private static final int PERMS_REQUEST_CODE = 123;
private ArrayList<Mat> images;
private ArrayList<String> imagesLabels;
private Storage local;
private String[] uniqueLabels;
FaceRecognizer recognize;
private boolean trainfaces() {
if(images.isEmpty())
return false;
List<Mat> imagesMatrix = new ArrayList<>();
for (int i = 0; i < images.size(); i++)
imagesMatrix.add(images.get(i));
Set<String> uniqueLabelsSet = new HashSet<>(imagesLabels); // Get all unique labels
uniqueLabels = uniqueLabelsSet.toArray(new String[uniqueLabelsSet.size()]); // Convert to String array, so we can read the values from the indices
int[] classesNumbers = new int[uniqueLabels.length];
for (int i = 0; i < classesNumbers.length; i++)
classesNumbers[i] = i + 1; // Create incrementing list for each unique label starting at 1
int[] classes = new int[imagesLabels.size()];
for (int i = 0; i < imagesLabels.size(); i++) {
String label = imagesLabels.get(i);
for (int j = 0; j < uniqueLabels.length; j++) {
if (label.equals(uniqueLabels[j])) {
classes[i] = classesNumbers[j]; // Insert corresponding number
break;
}
}
}
Mat vectorClasses = new Mat(classes.length, 1, CvType.CV_32SC1); // CV_32S == int
vectorClasses.put(0, 0, classes); // Copy int array into a vector
recognize = LBPHFaceRecognizer.create(3,8,8,8,200);
recognize.train(imagesMatrix, vectorClasses);
if(SaveImage())
return true;
return false;
}
public void showLabelsDialog() {
Set<String> uniqueLabelsSet = new HashSet<>(imagesLabels); // Get all unique labels
if (!uniqueLabelsSet.isEmpty()) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Select label:");
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
images.remove(images.size()-1);
}
});
builder.setCancelable(false); // Prevent the user from closing the dialog
String[] uniqueLabels = uniqueLabelsSet.toArray(new String[uniqueLabelsSet.size()]); // Convert to String array for ArrayAdapter
Arrays.sort(uniqueLabels); // Sort labels alphabetically
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, uniqueLabels) {
#Override
public #NonNull
View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
TextView textView = (TextView) super.getView(position, convertView, parent);
if (getResources().getBoolean(R.bool.isTablet))
textView.setTextSize(20); // Make text slightly bigger on tablets compared to phones
else
textView.setTextSize(18); // Increase text size a little bit
return textView;
}
};
ListView mListView = new ListView(this);
mListView.setAdapter(arrayAdapter); // Set adapter, so the items actually show up
builder.setView(mListView); // Set the ListView
final AlertDialog dialog = builder.show(); // Show dialog and store in final variable, so it can be dismissed by the ListView
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
dialog.dismiss();
addLabel(arrayAdapter.getItem(position));
Log.i(TAG, "Labels Size "+imagesLabels.size()+"");
}
});
} else {
showEnterLabelDialog();
}
}
private void showEnterLabelDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Please enter your name:");
final EditText input = new EditText(this);
input.setInputType(InputType.TYPE_CLASS_TEXT);
builder.setView(input);
builder.setPositiveButton("Submit", null); // Set up positive button, but do not provide a listener, so we can check the string before dismissing the dialog
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
images.remove(images.size()-1);
}
});
builder.setCancelable(false); // User has to input a name
AlertDialog dialog = builder.create();
// Source: http://stackoverflow.com/a/7636468/2175837
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(final DialogInterface dialog) {
Button mButton = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String string = input.getText().toString().trim();
if (!string.isEmpty()) { // Make sure the input is valid
// If input is valid, dismiss the dialog and add the label to the array
dialog.dismiss();
addLabel(string);
}
}
});
}
});
// Show keyboard, so the user can start typing straight away
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
dialog.show();
}
private void addLabel(String string) {
String label = string.substring(0, 1).toUpperCase(Locale.US) + string.substring(1).trim().toLowerCase(Locale.US); // Make sure that the name is always uppercase and rest is lowercase
imagesLabels.add(label); // Add label to list of labels
Log.i(TAG, "Label: " + label);
}
public boolean SaveImage() {
File path = new File(Environment.getExternalStorageDirectory(), "TrainedData");
path.mkdirs();
String filename = "lbph_trained_data.xml";
File file = new File(path, filename);
recognize.save(file.toString());
if(file.exists())
return true;
return false;
}
public void cropedImages(Mat mat) {
Rect rect_Crop=null;
for(Rect face: faces.toArray()) {
rect_Crop = new Rect(face.x, face.y, face.width, face.height);
}
Mat croped = new Mat(mat, rect_Crop);
images.add(croped);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.train_main);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
Stetho.initializeWithDefaults(this);
if (hasPermissions()){
Toast.makeText(this, "Permission Granted", Toast.LENGTH_SHORT).show();
Log.i(TAG, "Permission Granted Before");
}
else {
requestPerms();
}
openCVCamera = (CameraBridgeViewBase)findViewById(R.id.java_camera_view);
openCVCamera.setCameraIndex(CameraBridgeViewBase.CAMERA_ID_FRONT);
openCVCamera.setVisibility(SurfaceView.VISIBLE);
openCVCamera.setCvCameraViewListener(this);
local = new Storage(this);
Button detect = (Button)findViewById(R.id.take_picture_button);
detect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(gray.total() == 0)
Toast.makeText(getApplicationContext(), "Can't Detect Faces", Toast.LENGTH_SHORT).show();
classifier.detectMultiScale(gray,faces,1.1,3,0|CASCADE_SCALE_IMAGE, new Size(30,30));
if(!faces.empty()) {
if(faces.toArray().length > 1)
Toast.makeText(getApplicationContext(), "Mutliple Faces Are not allowed", Toast.LENGTH_SHORT).show();
else {
if(gray.total() == 0) {
Log.i(TAG, "Empty gray image");
return;
}
cropedImages(gray);
showLabelsDialog();
Toast.makeText(getApplicationContext(), "Face Detected", Toast.LENGTH_SHORT).show();
}
}else
Toast.makeText(getApplicationContext(), "Unknown Face", Toast.LENGTH_SHORT).show();
}
});
}
#SuppressLint("WrongConstant")
private boolean hasPermissions(){
int res = 0;
//string array of permissions,
String[] permissions = new String[]{Manifest.permission.CAMERA};
for (String perms : permissions){
res = checkCallingOrSelfPermission(perms);
if (!(res == PackageManager.PERMISSION_GRANTED)){
return false;
}
}
return true;
}
private void requestPerms(){
String[] permissions = new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE};
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
requestPermissions(permissions,PERMS_REQUEST_CODE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
boolean allowed = true;
switch (requestCode){
case PERMS_REQUEST_CODE:
for (int res : grantResults){
// if user granted all permissions.
allowed = allowed && (res == PackageManager.PERMISSION_GRANTED);
}
break;
default:
// if user not granted permissions.
allowed = false;
break;
}
if (allowed){
//user granted all permissions we can perform our task.
Log.i(TAG, "Permission has been added");
}
else {
// we will give warning to user that they haven't granted permissions.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) || shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE) ||
shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)){
Toast.makeText(this, "Permission Denied.", Toast.LENGTH_SHORT).show();
}
}
}
}
private BaseLoaderCallback callbackLoader = new BaseLoaderCallback(this) {
#Override
public void onManagerConnected(int status) {
switch(status) {
case BaseLoaderCallback.SUCCESS:
faces = new MatOfRect();
openCVCamera.enableView();
images = local.getListMat("images");
imagesLabels = local.getListString("imagesLabels");
break;
default:
super.onManagerConnected(status);
break;
}
}
};
#Override
protected void onPause() {
super.onPause();
if(openCVCamera != null)
openCVCamera.disableView();
}
#Override
protected void onStop() {
super.onStop();
if (images != null && imagesLabels != null) {
local.putListMat("images", images);
local.putListString("imagesLabels", imagesLabels);
Log.i(TAG, "Images have been saved");
if(trainfaces()) {
images.clear();
imagesLabels.clear();
}
}
}
#Override
protected void onDestroy(){
super.onDestroy();
if(openCVCamera != null)
openCVCamera.disableView();
}
#Override
protected void onResume(){
super.onResume();
if(OpenCVLoader.initDebug()) {
Log.i(TAG, "System Library Loaded Successfully");
callbackLoader.onManagerConnected(BaseLoaderCallback.SUCCESS);
} else {
Log.i(TAG, "Unable To Load System Library");
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION, this, callbackLoader);
}
}
#Override
public void onCameraViewStarted(int width, int height) {
rgba = new Mat();
gray = new Mat();
classifier = FileUtils.loadXMLS(this, "lbpcascade_frontalface_improved.xml");
}
#Override
public void onCameraViewStopped() {
rgba.release();
gray.release();
}
#Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
Mat mGrayTmp = inputFrame.gray();
Mat mRgbaTmp = inputFrame.rgba();
int orientation = openCVCamera.getScreenOrientation();
if (openCVCamera.isEmulator()) // Treat emulators as a special case
Core.flip(mRgbaTmp, mRgbaTmp, 1); // Flip along y-axis
else {
switch (orientation) { // RGB image
case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
Core.flip(mRgbaTmp, mRgbaTmp, 0); // Flip along x-axis
break;
case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
Core.flip(mRgbaTmp, mRgbaTmp, 1); // Flip along y-axis
break;
}
switch (orientation) { // Grayscale image
case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
Core.transpose(mGrayTmp, mGrayTmp); // Rotate image
Core.flip(mGrayTmp, mGrayTmp, -1); // Flip along both axis
break;
case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
Core.transpose(mGrayTmp, mGrayTmp); // Rotate image
break;
case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
Core.flip(mGrayTmp, mGrayTmp, 1); // Flip along y-axis
break;
case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
Core.flip(mGrayTmp, mGrayTmp, 0); // Flip along x-axis
break;
}
}
gray = mGrayTmp;
rgba = mRgbaTmp;
Imgproc.resize(gray, gray, new Size(200,200.0f/ ((float)gray.width()/ (float)gray.height())));
return rgba;
}
}
The Lines of Errors mentionned in the logcat refers to those java code lines:
In TrainActivity.java:
recognize = LBPHFaceRecognizer.create(3,8,8,8,200);
recognize.train(imagesMatrix, vectorClasses);
And
if(trainfaces()) {
images.clear();
imagesLabels.clear();
}
Do you guys have any idea about this problem and how to fix it?
PS: I am a beginner with OpenCv.
You can solve it by reset preferences onCreate TrainActivity
// -------------------------------
// reset preferences
local = new Storage(this);
images = new ArrayList<>();
imagesLabels = new ArrayList<>();
local.putListMat("images", images);
local.putListString("imagesLabels", imagesLabels);
// -------------------------------
Why is my activity unable to upload pictures taken by camera while it easily uploads the picture picked from the gallery?
The picture uploaded through the gallery is available on the server but the file(picture) taken through the camera is not found on the server after the API hit.
Opening the directory on the server gives 'File not found' error for the file uploaded via camera.
Here is my code:
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.content.FileProvider;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.AppCompatCheckBox;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import static com.app.engage.Interfaces.Keys.userDetails.*;
import com.app.engage.Interfaces.ApiResponse;
import com.app.engage.Interfaces.NetworkConnectivityListener;
import com.app.engage.R;
import com.app.engage.Utilities.ConnectionDetector;
import com.app.engage.Utilities.GetServerData;
import com.app.engage.Utilities.ImageOnlyOptionsDialog;
import com.app.engage.Utilities.ProgressDialog;
import com.app.engage.Utilities.RoleSectDialog;
import com.app.engage.Utilities.RoundCorner;
import com.app.engage.Utilities.SharedPreference_Main;
import com.app.engage.Utilities.Utilities;
import com.bumptech.glide.Glide;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import com.app.engage.Interfaces.OnButtonClicked;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class SignupActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener, ApiResponse.Api_hit, View.OnClickListener {
private TextView toolbarText;
public static TextView selections;
private ProgressDialog progressDialog;
private String selected_role = null;
private String selectedRole = "", selectedOrgType = "";
public static String selectedNatPriArea = "";
private ArrayList<String> role_list, org_type, nat_pri_area;
private ApiResponse apiResponse;
private ImageView dp;
private Uri uriFilePath;
private int REQUEST_CODE_CAMERA = 1002;
private int REQUEST_PICK_IMAGE = 1003;
private AlertDialog.Builder builder;
private TextView upload_dp;
private AppCompatCheckBox stayLoggedIn;
private Spinner roleSpinner, organisationTypeSpinner;
private Button signUp;
private SharedPreference_Main sharedPreference_main;
private String mCurrentPhotoPath;
// private Utilities utilities;
private TextView select_nat_pri_area;
private ConnectionDetector receiver;
private EditText fullName, email, orgName, password, reEnterPassword;
private File file = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup);
getWindow().setBackgroundDrawableResource(R.drawable.blurred_background); //setting background here
android.support.v7.widget.Toolbar toolbar = findViewById(R.id.app_bar);
setSupportActionBar(toolbar);
ActionBar ab = getSupportActionBar();
role_list = new ArrayList<>(); //arraylist that will hold the roles coming from the server
org_type = new ArrayList<>();//arraylist that will hold the roles coming from the server
nat_pri_area = new ArrayList<>();
sharedPreference_main = new SharedPreference_Main(this);
ab.setDisplayHomeAsUpEnabled(true);
ab.setHomeAsUpIndicator(R.drawable.white_back_icon_for_toolbar);
toolbarText = findViewById(R.id.toolbarText);
select_nat_pri_area = findViewById(R.id.nat_pri_areaaa);
toolbarText.setText("Sign Up");
apiResponse = new ApiResponse(this);
roleSpinner = findViewById(R.id.select_role_spinner);
organisationTypeSpinner = findViewById(R.id.organisation_type_spinner);
fullName = findViewById(R.id.full_name_editText);
email = findViewById(R.id.email_editText_signUp);
password = findViewById(R.id.pass_edit_text);
reEnterPassword = findViewById(R.id.reEnterPword);
orgName = findViewById(R.id.org_edit_text);
selections = findViewById(R.id.selectionss);
signUp = findViewById(R.id.signUp_Button);
dp = findViewById(R.id.dp);
progressDialog = new ProgressDialog(this);
select_nat_pri_area.setOnClickListener(this);
upload_dp = findViewById(R.id.upload_dp);
dp.setOnClickListener(this);
selections.setOnClickListener(this);
upload_dp.setOnClickListener(this);
// utilities = new Utilities(this);
receiver = new ConnectionDetector(new NetworkConnectivityListener() {
#Override
public void onNetworkConnected() //if network connection is available
{
if (role_list.size() <= 0 || org_type.size() <= 0 || nat_pri_area.size() <= 0) {
getData();
}
}
#Override
public void onNetworkDisconnected() {
displayAlert();
}
}, this);
// sharedPreference_main = SharedPreference_Main.getInstance(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) //initialising the AlertDialogue builder
{
builder = new AlertDialog.Builder(this, android.R.style.Theme_Material_Dialog_Alert);
} else {
builder = new AlertDialog.Builder(this);
}
roleSpinner.setOnItemSelectedListener(this);
organisationTypeSpinner.setOnItemSelectedListener(org_type_selection);
dp.setOnClickListener(this);
upload_dp.setOnClickListener(this);
// natPriorityAreaSpinner.setAdapter(adapterSetter(priorityArea));
signUp.setOnClickListener(this);
}
private ArrayAdapter<String> adapterSetter(ArrayList<String> data) //to temporarily populate the spinners
{
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
this, R.layout.custom_spinner, data);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
return adapter;
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
#Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(receiver, filter);
receiver.isNetworkAvailable();
//checkConnection();
}
public void signup() {
if (!validate()) { //if the conditions in the validate function are not met return
onSignupFailed();
Toast.makeText(this, "Something went wrong sign-up failed", Toast.LENGTH_SHORT).show();
return;
} else {
Toast.makeText(this, "signing up", Toast.LENGTH_SHORT).show();
// signUp.setEnabled(false);
progressDialog.progressDialogStart("Please Wait...");
try {
apiResponse.hitVolleyMultipartApi(this, "signup", getparams(), prof_pic, file);
} catch (Exception e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
// TODO: Implement your own signup logic here.'
// save();
}
public void onSignupSuccess() //if signup is successful
{
signUp.setEnabled(true);
setResult(RESULT_OK, null);
//Toast.makeText(this, "snkflsndkfl", Toast.LENGTH_SHORT).show();
Intent i = new Intent(this, HomeActivity.class);
//i.putExtra("Back Functionality", true);
startActivity(i);
finish();
}
public void onSignupFailed() {
Toast.makeText(getBaseContext(), "Signup failed", Toast.LENGTH_LONG).show();
signUp.setEnabled(true);
}
public boolean validate() //to check the entered information
{
boolean valid = true;
String name = fullName.getText().toString();
String mail = email.getText().toString();
String pword = password.getText().toString();
String org_Name = orgName.getText().toString();
String reEnterPword = reEnterPassword.getText().toString();
if (name.isEmpty() || name.length() < 3) {
fullName.setError("at least 3 characters", null);
valid = false;
} else {
fullName.setError(null);
}
if (mail.isEmpty() || !android.util.Patterns.EMAIL_ADDRESS.matcher(mail).matches()) {
email.setError("enter a valid email address", null);
valid = false;
} else {
email.setError(null);
}
if (org_Name.isEmpty()) {
orgName.setError("Please enter the organisation's name", null);
valid = false;
} else {
orgName.setError(null);
}
if (pword.isEmpty() || password.length() < 4 || password.length() > 10) {
password.setError("between 4 and 10 alphanumeric characters", null);
valid = false;
} else {
password.setError(null);
}
if (reEnterPword.isEmpty() || reEnterPassword.length() < 4 || reEnterPassword.length() > 10 || !(reEnterPword.equals(pword))) {
reEnterPassword.setError("Password Do not match", null);
valid = false;
} else {
reEnterPassword.setError(null);
}
return valid;
}
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
switch (i) {
case 0:
selectedRole = "Facilitator";
break;
case 1:
selectedRole = "Provider Administrator";
break;
case 2:
selectedRole = "Provider Executive";
break;
case 3:
selectedRole = "School PLD Administrator";
break;
case 4:
selectedRole = "MOE National Priority";
break;
case 5:
selectedRole = "Senior Leadership";
break;
case 6:
selectedRole = "Teacher";
break;
}
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
AdapterView.OnItemSelectedListener org_type_selection = new AdapterView.OnItemSelectedListener() //for organisation type selection
{
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
switch (i) {
case 0:
selectedOrgType = "Education";
break;
case 1:
selectedOrgType = "IT";
break;
case 2:
selectedOrgType = "Medical";
break;
case 3:
selectedOrgType = "";
break;
case 4:
selectedOrgType = "";
break;
case 5:
selectedOrgType = "";
break;
case 6:
selectedOrgType = "";
break;
}
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
};
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
}
return super.onOptionsItemSelected(item);
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.dp:
case R.id.upload_dp:
ImageOnlyOptionsDialog imageOnlyOptionsDialog = new ImageOnlyOptionsDialog();
imageOnlyOptionsDialog.setonButtonClickListener(new OnButtonClicked() {
#Override
public void onButtonCLick(int buttonId) {
switch (buttonId) {
case R.id.btnCamera:
startCamera();
break;
case R.id.btnGallery:
pickFromGallery();
break;
default:
break;
}
}
});
imageOnlyOptionsDialog.show(getSupportFragmentManager(), ImageOnlyOptionsDialog.class.getSimpleName());
break;
case R.id.signUp_Button:
signup();
break;
case R.id.nat_pri_areaaa:
case R.id.selectionss:
Bundle data = new Bundle();
data.putStringArrayList("pri_areas", nat_pri_area);
RoleSectDialog roleSectDialog = new RoleSectDialog();
roleSectDialog.setArguments(data);
roleSectDialog.show(getSupportFragmentManager(), RoleSectDialog.class.getSimpleName());
roleSectDialog.setonButtonClickListener(new OnButtonClicked() {
#Override
public void onButtonCLick(int buttonId) {
switch (buttonId) {
case R.id.k:
break;
default:
break;
}
}
});
break;
default:
break;
}
}
public void startCamera() {
PackageManager packageManager = this.getPackageManager();
if (packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
File mainDirectory = new File(Environment.getExternalStorageDirectory(), "MyFolder/tmp");
if (!mainDirectory.exists())
mainDirectory.mkdirs();
Calendar calendar = Calendar.getInstance();
uriFilePath = Uri.fromFile(new File(mainDirectory, "IMG_" + calendar.getTimeInMillis() + ".jpeg"));
Intent intent1 = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent1.putExtra(MediaStore.EXTRA_OUTPUT, uriFilePath);
startActivityForResult(intent1, REQUEST_CODE_CAMERA);
}
}
public void pickFromGallery() //this is the intent creation for picking image from gallery
{
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(Intent.createChooser(intent, "Complete action using"), REQUEST_PICK_IMAGE);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) //this receives the intent's result
{
if (requestCode == REQUEST_CODE_CAMERA) {
if (resultCode == RESULT_OK) {
try {
ExifInterface exif = new ExifInterface(uriFilePath.getPath());
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
Matrix matrix = new Matrix();
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
matrix.postRotate(90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
matrix.postRotate(180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
matrix.postRotate(270);
break;
}
String filePath = getRealPathFromURI(uriFilePath);
file = new File(new URI("file://" + filePath.replace(" ", "%20")));//photo is file type that is global
Glide.with(this)
.load(file)
.placeholder(R.drawable.upload_image)
.into(dp);
// getImageDetails(photo);
} catch (Exception e) {
e.printStackTrace();
}
}
} else if (requestCode == REQUEST_PICK_IMAGE) {
if (resultCode == RESULT_OK) {
Uri selectedImageUri = data.getData();
String selectedImagePath = getRealPathFromURI(selectedImageUri);
Toast.makeText(this, selectedImagePath, Toast.LENGTH_SHORT).show();
try {
file = new File(new URI("file://" + selectedImagePath.replace(" ", "%20")));
Glide.with(this).load(file).placeholder(R.drawable.upload_image)
.into(dp);
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
}
public String getRealPathFromURI(Uri uri) {
if (uri == null) {
return null;
}
String[] projection = {MediaStore.Images.Media.DATA};
Cursor cursor = this.getContentResolver().query(uri, projection, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
int column_index = cursor.getColumnIndex(projection[0]);
return cursor.getString(column_index);
}
return uri.getPath();
}
public HashMap<String, String> getparams() { //parameters passed while hitting the API
HashMap<String, String> params = new HashMap<>();
params.put(rulee, "sign_up");
params.put(emaill, email.getText().toString());
params.put(word, password.getText().toString());
params.put(f_name, fullName.getText().toString());
params.put(n_p_a, selections.getText().toString());
params.put(or_name, orgName.getText().toString());
params.put(or_type, selectedOrgType);
Toast.makeText(this, selectedRole, Toast.LENGTH_SHORT).show();
params.put(rolId, selectedRole);
return params;
}
#Override
public void response(String responseObject, String method_call) //this gets the response when API is hit
{
progressDialog.dismissDialog();
try {
JSONObject response = new JSONObject(responseObject);
if (response.getString("flag").equalsIgnoreCase("success")) {
JSONObject object = response.getJSONObject("response");
sharedPreference_main.setUserName(object.getString(f_name));
sharedPreference_main.setUserEmail(object.getString(emaill));
sharedPreference_main.setUserOrganisation(object.getString(or_name));
sharedPreference_main.setUserRole(object.getString(rol));
sharedPreference_main.setOrgType(object.getString(or_type));
sharedPreference_main.setNPA(object.getString(n_p_a));
sharedPreference_main.setUserProfilePic(object.getString(prof_pic));
onSignupSuccess(); //if everything works out call the home activity
} else if (response.getString("flag").equalsIgnoreCase("0")) {
String resp = response.getString("response");
builder.setTitle("Error:"); //building up the dialog
builder.setMessage(resp);
displayAlert(resp);
} else if (response.getString("flag").equalsIgnoreCase("1")) {
// Toast.makeText(this, response.getString("flag"), Toast.LENGTH_SHORT).show();
JSONArray data = response.getJSONArray("message");
if (data.length() > 0) {
for (int i = 0; i < data.length(); i++) {
JSONObject inData = data.getJSONObject(i);
if (inData.has("role_name")) {
role_list.add(inData.getString("role_name"));
} else if (inData.has("organisation_type")) {
org_type.add(inData.getString("organisation_type"));
} else if (inData.has("prior_name")) {
nat_pri_area.add(inData.getString("prior_name"));
}
// N_P_A.add(inData.getString("prior_name"));
}
}
if (role_list.size() > 0) {
// String[] role = role_list.toArray(new String[role_list.size()]);
roleSpinner.setAdapter(adapterSetter(role_list));
}
if (org_type != null) {
// String organisationType[] =org_type.toArray(new String[org_type.size()]);
organisationTypeSpinner.setAdapter(adapterSetter(org_type));
}
// String[] priorityArea = org_type.toArray(new String[org_type.size()]);
//
}
// onSignupSuccess();
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void error(String error) {
progressDialog.dismissDialog();
Toast.makeText(this, error, Toast.LENGTH_SHORT).show();
}
private void displayAlert(final String code) {
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
fullName.setText("");
email.setText("");
password.setText("");
orgName.setText("");
}
}).show();
}
private void displayAlert() //overloaded function
{
builder.setTitle("No internet connection");
builder.setTitle("Please switch on the internet");
builder.setPositiveButton("Retry", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
// checkConnection();
if (receiver.isNetworkAvailable()) {
dialogInterface.c**strong text**ancel();
} else {
displayAlert();
}
}
}).setNegativeButton("Exit", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
// checkConnection();
dialogInterface.cancel();
}
}).show();
}
public void getData() {
GetServerData getServerData = new GetServerData(this);
getServerData.getRoles();
}
}
Note:
Language version - Java
Target SDK -23
Any help would be appreciated.
This was happening because the permissions were not being provided to the application while running it on the smartphone. Newer versions of Android require the apps to be granted permissions from within the smartphone.
Use this and upvote after your issue gets resolve.
private File profilePic;
private Uri photoFileUri;
/**
* Method below will work for Camera Intent.
*/
private void clickPicture() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
try {
photoFile = AppUtils.getInstance().createImageFile(); // Create the File where the photo should go
outputFileUri = FileProvider.getUriForFile(SignUpActivity.this, getApplicationContext().getPackageName() + ".provider", photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(takePictureIntent, CAMERA_IMAGE_REQUEST);
} catch (IOException io) {
io.printStackTrace(); // Error occurred while creating the File
}
//outputFileUri = Uri.fromFile(photoFile);//At this Uri the image captured will get saved.
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
switch (requestCode) {
case AppConstants.MediaConstants.REQUEST_CAPTURE_IMAGE:
profilePic = new File(AppUtils.getInstance().getRealPathFromURI(photoFileUri, mActivity));
break;
}
}
}
Use this method below directly in your classs
/**
* method to get real path from uri
*
* #param contentURI
* #param context
* #return
*/
public String getRealPathFromURI(Uri contentURI, Context context) {
String result;
Cursor cursor = context.getContentResolver().query(contentURI, null, null, null, null);
if (cursor == null) { // Source is Dropbox or other similar local file path
result = contentURI.getPath();
} else {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
result = cursor.getString(idx);
cursor.close();
}
return result;
}
create "provide_paths.xml" file in folder name "xml" in res directory and add code below in it
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="external_files"
path="." />
</paths>
I'm using the Google-API to get the count of unread E-Mails and some Events from the Google-Calender. I used the Quick-Start Sample Code from Google and it worked fine(asks for scope-permissions if not set and so on). So I formed it to a Service and a Auth-Activity for the user to change their Accounts. My problem is that the User don't get asked for Authorization anymore. The App still uses the right Account and if I select an Account which is authorized for my App it still work but if I select a new Account no Authorization-form is being shown.
Google AuthUtil Error:
09-19 13:13:54.114: D/DEBUG_TEST(7072): ERROR: UserRecoverableErrorNeedPermission
Here is my Activity that changes the Account. Every time a user selects an Google-Account the Static-Variable "gAccountDaten"(GoogleAccountCredential Object) got updated.
import android.accounts.AccountManager;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Toast;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.util.ExponentialBackOff;
import com.google.api.services.calendar.CalendarScopes;
import com.google.api.services.gmail.GmailScopes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.EasyPermissions;
public class GoogleAuthActivity extends Activity implements EasyPermissions.PermissionCallbacks {
static GoogleAccountCredential gAccountDaten;
static final int REQUEST_GOOGLE_PLAY_SERVICES = 1002;
static final int REQUEST_ACCOUNT_PICKER = 1000;
static final int REQUEST_AUTHORIZATION = 1001;
static final int REQUEST_PERMISSION_GET_ACCOUNTS = 1003;
private static final String PREF_ACCOUNT_NAME = "accountName";
private static final String[] SCOPES = { GmailScopes.GMAIL_LABELS, GmailScopes.GMAIL_READONLY , GmailScopes.MAIL_GOOGLE_COM, CalendarScopes.CALENDAR_READONLY};
private Boolean verbunden = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.googleauthactivitylayout);
gAccountDaten = GoogleAccountCredential.usingOAuth2(getApplicationContext(), Arrays.asList(SCOPES)).setBackOff(new ExponentialBackOff());
chooseAccount();
}
private String getGoogleAccountNameSettings(){
String toReturn = getPreferences(Context.MODE_PRIVATE)
.getString(PREF_ACCOUNT_NAME, null);
Log.d("ACCOUNT_DEBUG", "FUNC: getGoogleAccountNameSettings --> " + toReturn);
return toReturn;
}
private boolean setGoogleAccountNameSettings(String accountName){
try{
SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putString(PREF_ACCOUNT_NAME, accountName);
editor.apply();
Log.d("ACCOUNT_DEBUG", "FUNC: setGoogleAccountNameSettings --> " + accountName);
}catch (Exception exc){
Log.e("ACCOUNT_DEBUG", "FUNC: setGoogleAccountNameSettings --> ERROR");
return false;
}finally {
Log.e("ACCOUNT_DEBUG", "FUNC: setGoogleAccountNameSettings --> ERROR");
return true;
}
}
private boolean removeGoogleAccountNameSettings(){
try{
SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.remove(PREF_ACCOUNT_NAME);
editor.apply();
GoogleService.EMAIL_COUNT = 0;
GoogleService.lstKalender.clear();
Log.d("ACCOUNT_DEBUG", "FUNC: removeGoogleAccountNameSettings --> " + "rennt");
}catch (Exception exc){
Log.e("ACCOUNT_DEBUG", "FUNC: removeGoogleAccountNameSettings --> ERROR");
return false;
}finally {
Log.e("ACCOUNT_DEBUG", "FUNC: removeGoogleAccountNameSettings --> ERROR");
return true;
}
}
#AfterPermissionGranted(REQUEST_PERMISSION_GET_ACCOUNTS)
private void chooseAccount( ) {
removeGoogleAccountNameSettings();
if (EasyPermissions.hasPermissions(
this, android.Manifest.permission.GET_ACCOUNTS)) {
String accountName = getGoogleAccountNameSettings();
if (accountName != null) {
gAccountDaten.setSelectedAccountName(accountName);
this.startService(new Intent(this, GoogleService.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK));
Log.d("AUTH_DEBUG", "Already authed" + " | " + gAccountDaten.getScope());
//finish();
} else {
// Start a dialog from which the user can choose an account
startActivityForResult(
gAccountDaten.newChooseAccountIntent(),
REQUEST_ACCOUNT_PICKER);
}
} else {
// Request the GET_ACCOUNTS permission via a user dialog
EasyPermissions.requestPermissions(
this,
"This app needs to access your Google account .",
REQUEST_PERMISSION_GET_ACCOUNTS,
android.Manifest.permission.GET_ACCOUNTS);
}
}
#Override
protected void onActivityResult(
int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case REQUEST_GOOGLE_PLAY_SERVICES:
if (resultCode != RESULT_OK) {
//mOutputText.setText(
// "This app requires Google Play Services. Please install " +
// "Google Play Services on your device and relaunch this app.");
} else {
//getResultsFromApi();
}
break;
case REQUEST_ACCOUNT_PICKER:
if (resultCode == RESULT_OK && data != null && data.getExtras() != null) {
String accountName =
data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
if (accountName != null) {
setGoogleAccountNameSettings(accountName);
gAccountDaten.setSelectedAccountName(accountName);
Log.d("AUTH_DEBUG", "Authed after Picker -->" + accountName + " | " + gAccountDaten.getScope());
this.startService(new Intent(this, GoogleService.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK));
finish();
}
}
break;
case REQUEST_AUTHORIZATION:
if (resultCode == RESULT_OK) {
Log.d("AUTH_DEBUG", "started aufter authorization -->" + resultCode + " | " + gAccountDaten.getScope());
this.startService(new Intent(this, GoogleService.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK));
finish();
}
break;
}
}
/////PERMISSION CALLBACKS
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions,
#NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
EasyPermissions.onRequestPermissionsResult(
requestCode, permissions, grantResults, this);
}
/**
* Callback for when a permission is granted using the EasyPermissions
* library.
* #param requestCode The request code associated with the requested
* permission
* #param list The requested permission list. Never null.
*/
#Override
public void onPermissionsGranted(int requestCode, List<String> list) {
// Do nothing.
}
/**
* Callback for when a permission is denied using the EasyPermissions
* library.
* #param requestCode The request code associated with the requested
* permission
* #param list The requested permission list. Never null.
*/
#Override
public void onPermissionsDenied(int requestCode, List<String> list) {
Log.d("DEBUG_TEST", "NO PERM");
}
}
And here is my Google-Service Code. It will gather the information from the google api every 60 seconds and write it to static variables.
import android.*;
import android.app.Dialog;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import android.widget.RemoteViews;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.googleapis.extensions.android.gms.auth.GooglePlayServicesAvailabilityIOException;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.ExponentialBackOff;
import com.google.api.services.calendar.Calendar;
import com.google.api.services.calendar.CalendarScopes;
import com.google.api.services.calendar.model.CalendarList;
import com.google.api.services.calendar.model.CalendarListEntry;
import com.google.api.services.calendar.model.Event;
import com.google.api.services.calendar.model.EventDateTime;
import com.google.api.services.calendar.model.Events;
import com.google.api.services.gmail.GmailScopes;
import com.google.api.services.gmail.model.Label;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.EasyPermissions;
public class GoogleService extends Service implements EasyPermissions.PermissionCallbacks{
GoogleAccountCredential gAccountDaten;
static final int REQUEST_ACCOUNT_PICKER = 1000;
static final int REQUEST_AUTHORIZATION = 1001;
static final int REQUEST_GOOGLE_PLAY_SERVICES = 1002;
static final int REQUEST_PERMISSION_GET_ACCOUNTS = 1003;
private static final String PREF_ACCOUNT_NAME = "accountName";
static String testj = "";
static ArrayList<Kalender> lstKalender = new ArrayList<>();
static int EMAIL_COUNT = 0;
//GOOGLE BERECHTIGUNGEN
private static final String[] SCOPES = { GmailScopes.GMAIL_LABELS, GmailScopes.GMAIL_READONLY , GmailScopes.MAIL_GOOGLE_COM, CalendarScopes.CALENDAR_READONLY};
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("DEBUG_TEST", "onStartCommand");
gAccountDaten = GoogleAuthActivity.gAccountDaten;
if(gAccountDaten == null){
Log.d("DEBUG_TEST", "gAccountDaten == NULL!");
return 0;
}
getResultsFromApi();
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
getResultsFromApi();
handler.postDelayed(this, 60000);
}
};
handler.postDelayed(runnable, 60000);
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onPermissionsGranted(int requestCode, List<String> perms) {
}
#Override
public void onPermissionsDenied(int requestCode, List<String> perms) {
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
}
//HELFER FUNKTIONEN
private void getResultsFromApi() {
if (! isGooglePlayServicesAvailable()) {
acquireGooglePlayServices();
} else if (gAccountDaten.getSelectedAccountName() == null) {
Log.d("DEBUG_TEST", "ChooseAccount");
} else if (! isDeviceOnline()) {
//Gerät Offline
} else {
Log.d("DEBUG_TEST", "MakeRequestTask -->" + gAccountDaten.getSelectedAccountName());
new MakeRequestTask(gAccountDaten).execute();
}
}
//CHECK: GERÄT ONLINE ?
private boolean isDeviceOnline() {
ConnectivityManager connMgr =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}
//CHECK: GOOGLE SERVICE ONLINE ?
private boolean isGooglePlayServicesAvailable() {
GoogleApiAvailability apiAvailability =
GoogleApiAvailability.getInstance();
final int connectionStatusCode =
apiAvailability.isGooglePlayServicesAvailable(this);
return connectionStatusCode == ConnectionResult.SUCCESS;
}
private void acquireGooglePlayServices() {
GoogleApiAvailability apiAvailability =
GoogleApiAvailability.getInstance();
final int connectionStatusCode =
apiAvailability.isGooglePlayServicesAvailable(this);
}
/////////////////////////MAKE REQUEST KLASSE////////////////////////////////////
private class MakeRequestTask extends AsyncTask<Void, Void, List<String>> {
private com.google.api.services.gmail.Gmail mService = null;
private com.google.api.services.calendar.Calendar mServiceKalender = null;
private Exception mLastError = null;
public MakeRequestTask(GoogleAccountCredential credential) {
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
HttpTransport transport2 = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory2 = JacksonFactory.getDefaultInstance();
mService = new com.google.api.services.gmail.Gmail.Builder(
transport, jsonFactory, credential)
.setApplicationName("Gmail API Android Quickstart")
.build();
mServiceKalender = new com.google.api.services.calendar.Calendar.Builder(
transport2, jsonFactory2, credential)
.setApplicationName("Google Calendar API Android Quickstart")
.build();
Log.d("DEBUG_TEST", "mService und mServiceKalender Objecte instanzieren --> " + credential.getSelectedAccountName());
}
/**
* Background task to call Gmail API.
* #param params no parameters needed for this task.
*/
#Override
protected List<String> doInBackground(Void... params) {
try {
return getDataFromApi();
} catch (Exception e) {
mLastError = e;
cancel(true);
return null;
}
}
/**
* Fetch a list of Gmail labels attached to the specified account.
* #return List of Strings labels.
* #throws IOException
*/
private List<String> getDataFromApi() throws IOException {
// Get the labels in the user's account.
String user = "me";
List<String> labels = new ArrayList<String>();
Label label = mService.users().labels().get(user, "INBOX").execute();
Log.d("DEBUG_TEST", "getDataFromApi() --> " + user );
//EMAIL_COUNT = label.getMessagesUnread();
EMAIL_COUNT = label.getMessagesTotal();
labels.add("E-Mails: " + EMAIL_COUNT);
lstKalender.clear();
String pageToken = null;
do {
CalendarList calendarList = mServiceKalender.calendarList().list().setPageToken(pageToken).execute();
List<CalendarListEntry> items = calendarList.getItems();
for (CalendarListEntry calendarListEntry : items) {
String KALENDERNAME = calendarListEntry.getSummary();
String KALENDER_ID = calendarListEntry.getId();
Kalender neuerKalender = new Kalender();
neuerKalender.setKalenderName(KALENDERNAME);
neuerKalender.setKalenderId(KALENDER_ID);
Log.d("KALENDER_DEBUG", "Kalender: " + KALENDERNAME + "wurde angelegt! ID: " + KALENDER_ID);
String pageToken2 = null;
do {
Events events = mServiceKalender.events().list(KALENDER_ID).setPageToken(pageToken2).execute();
List<Event> items2 = events.getItems();
for (Event event : items2) {
String calName = event.getSummary();
EventDateTime calStart = event.getStart();
EventDateTime calEnde = event.getEnd();
String calLocation = event.getLocation();
String calID = event.getId();
if(neuerKalender.addEvent(calName,calStart,calEnde,calLocation,calID)){
//Log.d("KALENDER_DEBUG", "Event: " + calName + " wurde zum Kalender " + KALENDERNAME + " hinzugefügt!");
}
}
pageToken2 = events.getNextPageToken();
} while (pageToken2 != null);
lstKalender.add(neuerKalender);
Log.d("KALENDER_DEBUG", "Kalender: " + neuerKalender.getKalenderName() + " durchgelaufen und zur Globalen Liste hinzugefügt!");
}
pageToken = calendarList.getNextPageToken();
} while (pageToken != null);
DaWidgetProvider.updateEventList(getBaseContext());
UpdateService updateService = new UpdateService();
updateService.buildUpdate(getBaseContext());
DaWidgetProvider.updateAllWidgets(getBaseContext());
return labels;
}
#Override
protected void onPreExecute() {
}
#Override
protected void onPostExecute(List<String> output) {
if (output == null || output.size() == 0) {
// mOutputText.setText("No results returned.");
} else {
//output.add(0, "Data retrieved using the Gmail API:");
//mOutputText.setText(TextUtils.join("\n", output));
//mProgress.dismiss();
Context mContext = getApplicationContext();
}
}
#Override
protected void onCancelled() {
if (mLastError != null) {
if (mLastError instanceof GooglePlayServicesAvailabilityIOException) {
Log.d("DEBUG_TEST", "ERROR: " + mLastError.getMessage());
} else if (mLastError instanceof UserRecoverableAuthIOException) {
Log.d("DEBUG_TEST", "ERROR: UserRecoverableError" + mLastError.getMessage());
} else {
Log.d("DEBUG_TEST", "ERROR: " + mLastError.getMessage());
}
} else {
Log.d("DEBUG_TEST", "abgebrochen");
}
}
}
}
Thanks,
J. Doe ;)
Nice that seems to be the problem. But ive got a problem to fix it, because my Google-Service and my Google-Account Picker Activity are differented. I tried to pass the mLastError to my Activity in an Intent and start the Authentication-Request there but i got the following Error:
09-19 13:44:18.508: E/AndroidRuntime(7959): java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException)
And my Code changes in Google-Service and GoogleAuthActivity:
Google-Service:
protected void onCancelled() {
if (mLastError != null) {
if (mLastError instanceof GooglePlayServicesAvailabilityIOException) {
Log.d("DEBUG_TEST", "ERROR: " + mLastError.getMessage());
} else if (mLastError instanceof UserRecoverableAuthIOException) {
Log.d("DEBUG_TEST", "ERROR: UserRecoverableError" + mLastError.getCause().getMessage());
//KEINE BERECHTIGUNG GESETZT
[CODE CHANGES]
Intent startIntent = new Intent(getApplicationContext(), GoogleAuthActivity.class);
startIntent.putExtra("auththis", mLastError);
startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startIntent);
[/CODE CHANGES]
} else {
Log.d("DEBUG_TEST", "ERROR: " + mLastError.getMessage());
}
} else {
Log.d("DEBUG_TEST", "abgebrochen");
}
}
GoogleAuthActivity:
//EXTRA DATA???
if(getIntent().hasExtra("auththis")){
Intent edIntent = getIntent();
Bundle extras = edIntent.getExtras();
UserRecoverableAuthIOException mLastError = null;
mLastError = (UserRecoverableAuthIOException) extras.get("auththis");
startActivityForResult(
mLastError.getIntent(),
GoogleAuthActivity.REQUEST_AUTHORIZATION);
}else{
chooseAccount();
}
I am trying to access CallManager class object from com.android.internal.telephony package.
Here is my code:
ClassLoader classLoader = TestActivity.class.getClassLoader();
final ClassLoader classLoader = this.getClass().getClassLoader();
try {
final Class<?> classCallManager =
classLoader.loadClass("com.android.internal.telephony.CallManager");
Log.i("TestActivity", classCallManager);
} catch (final ClassNotFoundException e) {
Log.e("TestActivity", e);
}
Unfortunately, this is throwing a ClassNotFoundException. The same approach allows me to access PhoneFactory, but apparently I'm not allowed to access CallManager.
If I could reach the class, then I'd want to proceed using the class as follows:
Method method_getInstance;
method_getInstance = classCallManager.getDeclaredMethod("getInstance");
method_getInstance.setAccessible(true);
Object callManagerInstance = method_getInstance.invoke(null);
Can anyone help me on this?
Thanks in advance,
Harsha C
I could successfully load CallManager and its methods. However, when I invoke getState(), getActiveFgCallState(), it always return IDLE even when the app receives different call states from TelephonyManager, i.e. TelephonyManager.CALL_STATE_IDLE, TelephonyManager.CALL_STATE_OFFHOOK, TelephonyManager.CALL_STATE_RINGING.
I used the following code to load the class and its methods:
final Class<?> classCallManager = classLoader.loadClass("com.android.internal.telephony.CallManager");
Log.i(TAG, "Class loaded " + classCallManager.toString());
Method methodGetInstance = classCallManager.getDeclaredMethod("getInstance");
Log.i(TAG, "Method loaded " + methodGetInstance.getName());
Object objectCallManager = methodGetInstance.invoke(null);
Log.i(TAG, "Object loaded " + objectCallManager.getClass().getName());
Method methodGetState = classCallManager.getDeclaredMethod("getState");
Log.i(TAG, "Method loaded " + methodGetState.getName());
Log.i(TAG, "Phone state = " + methodGetState.invoke(objectCallManager));
Btw, what I am trying to do is detecting when the phone starts ringing. I saw in the source code that ALERTING is the internal event that I should listen to. Therefore, I tried to use CallManager to get Call.State, rather than Phone.State. I also tried to use registerForPreciseCallStateChanges() of CallManager class but none of approached worked so far.
I had to solve the exact same problem - getting the disconnection cause during call hangup. My solution was to grep the radio logs for the relevant lines. Seems to work - hope it helps.
private void startRadioLogListener() {
new Thread(new Runnable() {
public void run() {
Process process = null;
try {
// Clear the log first
String myCommandClear = "logcat -b radio -c";
Runtime.getRuntime().exec(myCommandClear);
String myCommand = "logcat -b radio";
process = Runtime.getRuntime().exec(myCommand);
Log.e(LogHelper.CAL_MON, "RadioLogProc: " + process);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
while (true) {
final String line = bufferedReader.readLine();
if (line != null) {
if (line.contains("disconnectCauseFromCode") || line.contains("LAST_CALL_FAIL_CAUSE")) {
Log.d(LogHelper.CAL_MON, "RadioLog: " + line);
radioLogHandler.post(new Runnable() {
public void run() {
consolePrint("Radio: " + line + "\n");
}
});
}
}
}
} catch (IOException e) {
Log.e(LogHelper.CAL_MON, "Can't get radio log", e);
} finally {
if (process != null) {
process.destroy();
}
}
}
}).start();
}
Have you tried this method found here on this blog?
By loading the Phone.apk might be the clue to getting around the ClassNotFound exception error...
I have written a program that recognize the phone calls and list all recent calls in a list. Maybe you can have a look on this code and it can help I think.
All you need is this:
String state = bundle.getString(TelephonyManager.EXTRA_STATE);
if(state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING))
but check this example also:
package org.java.sm222bt;
import org.java.sm222bt.R;
import android.app.ListActivity;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListAdapter;
import android.widget.SimpleCursorAdapter;
public class MainActivity extends ListActivity {
private CountryDbAdapter db;
private Cursor entrycursor;
private ListAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
registerForContextMenu(getListView());
db = new CountryDbAdapter(this);
updateEntry();
}
public void updateEntry(){
db.open();
entrycursor = db.fetchAllEntries();
adapter = new SimpleCursorAdapter(this, R.layout.row, entrycursor, new String[] {"phonenumber"}, new int[] {R.id.number});
setListAdapter(adapter);
db.close();
}
#Override
protected void onResume() {
super.onResume();
updateEntry();
}
public static final int Call = 0;
public static final int SendSMS = 1;
public static final int Share = 2;
public static final int Delete = 3;
public static final int ClearList = 4;
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo) {
menu.setHeaderTitle("Select:");
menu.add(0, Call, 0, "Call");
menu.add(0, SendSMS, 0, "Send SMS");
menu.add(0, Share, 0, "Share");
menu.add(0, Delete, 0, "Delete");
menu.add(0, ClearList, 0, "Clear all contacts");
}
#Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case Call:
//System.out.println(entrycursor.getString(1));
//EditText number=(EditText)findViewById(R.id.number);
String toDial="tel:"+entrycursor.getString(1);
//start activity for ACTION_DIAL or ACTION_CALL intent
startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(toDial)));
//update(entryCursor.getLong(0));
return true;
case SendSMS:
//EditText number=(EditText)findViewById(R.id.number);
//EditText msg=(EditText)findViewById(R.id.msg);
String sendUri="smsto:"+entrycursor.getString(1);
Intent sms=new Intent(Intent.ACTION_SENDTO,
Uri.parse(sendUri));
//sms.putExtra("sms_body", msg.getText().toString());
startActivity(sms);
return true;
case Share:
Intent i=new Intent(Intent.ACTION_SEND);
i.setType("text/plain");
i.putExtra(Intent.EXTRA_SUBJECT, "Hello");
i.putExtra(Intent.EXTRA_TEXT, "Sharing this number"+entrycursor.getString(1));
startActivity(Intent.createChooser(i,
entrycursor.getString(1)));
return true;
case Delete:
db.open();
db.deleteEntry(entrycursor.getLong(0));
db.close();
updateEntry();
return true;
case ClearList:
db.open();
db.deleteEntry();
db.close();
updateEntry();
return true;
default:
return super.onContextItemSelected(item);
}
}
}
and here is the incomming call receiver:
package org.java.sm222bt;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.widget.ListAdapter;
import android.widget.SimpleCursorAdapter;
public class IncomingCallReceiver extends BroadcastReceiver {
CountryDbAdapter db;
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Bundle bundle = intent.getExtras();
if(null == bundle)
return;
String state = bundle.getString(TelephonyManager.EXTRA_STATE);
if(state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING))
{
String phonenumber = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
System.out.println(phonenumber);
db = new CountryDbAdapter(context);
db.open();
db.insertEntry(phonenumber);
db.fetchAllEntries();
db.close();
}
}}
I understand that you want to detect when the call is disconnected. You can instead use the PhoneStateListener.LISTEN_CALL_STATE. For example:
final TelephonyManager telephony = (TelephonyManager)
getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(new PhoneStateListener() {
public void onCallStateChanged(final int state,
final String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.d("TestActivity", "Call disconnected");
break;
case TelephonyManager.CALL_STATE_RINGING:
break;
default:
break;
}
}
}, PhoneStateListener.LISTEN_CALL_STATE);
Use this :
telephone = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
private PhoneStateListener psl = new PhoneStateListener() {
#Override
public void onCallStateChanged (int state, String incomingNumber)
{
state = telephone.getCallState();
switch(state) {
case android.telephony.TelephonyManager.CALL_STATE_IDLE:
if (callsucces ) act();
break;
case android.telephony.TelephonyManager.CALL_STATE_RINGING:
callsucces = true;
break;
case android.telephony.TelephonyManager.CALL_STATE_OFFHOOK:
callsucces = true;
break;
}
}
};
private void call(String pnum) {
try {
callIntent = new Intent(Intent.ACTION_CALL);
callsucces = false;
if (telephone.getNetworkType() != 0) {
if (telephone.getCallState() == TelephonyManager.CALL_STATE_IDLE) {
callIntent.setData(Uri.parse("tel:"+pnum));
startActivity(callIntent);
telephone.listen(psl,PhoneStateListener.LISTEN_CALL_STATE);
}
} else act();
//callIntent.ACTION_NEW_OUTGOING_CALL
} catch (ActivityNotFoundException activityException) {
Toast.makeText(getBaseContext(), "Call failed",Toast.LENGTH_SHORT).show();
act();
}
}
Did you add READ_PHONE_STATE in AndroidManifest.xml ?
I think you miss that one.