I'm trying to use usb camera devices connected to my android device. So initially i have got the details of the usb devices connected through UsbManager.getDeviceList() method. Then i iterated through every device and requested for permission if permission was already not granted.
Prior to requesting the permission i have registered a global BroadCastReceiver to listen to the response of the requested permission.
Here is the MainActivity.java:
public class MainActivity extends AppCompatActivity {
private UsbManager usbManager_;
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
public PendingIntent permissionIntent;
private static String TAG = "testing";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// SurroundView surroundView = new SurroundView(this);
// setContentView(surroundView);
usbManager_ = (UsbManager) getSystemService(USB_SERVICE);
permissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
requestUsbPermissions();
}
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i(TAG, "received intent by broadcast " + intent.getAction());
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if (device != null) {
Log.i(TAG, "got the permission");
}
} else {
Log.d(TAG, "permission denied for device " + device);
}
}
}
}
};
public void requestUsbPermissions(){
HashMap<String, UsbDevice> deviceList = usbManager_.getDeviceList();
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
this.registerReceiver(usbReceiver, filter);
Log.i(TAG, "registered broadcast receiver!");
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
while (deviceIterator.hasNext()) {
UsbDevice device = deviceIterator.next();
Log.i(TAG,
"Camera: device Id " + device.getDeviceId() + " device mName : " + device.getDeviceName());
if (!usbManager_.hasPermission(device)) {
Log.i(TAG, "requesting permission");
usbManager_.requestPermission(device, permissionIntent);
}
}
}
}
So when i run the app it detects one usb device connected and requests permission for the same. But the dialog box which asks for user input never comes. Instead when the intent is received by the BroadCastReceiver the value of intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false) will always be false which means the permission is already denied. Can anyone explain to me why the dialog box is not coming in the first place and why the permission is denied automatically.
Here is my AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.vision_sdk_testing">
<uses-feature android:name="android.hardware.usb.host" android:required="true"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
And below is the output log:
2020-05-01 17:56:05.282 30769-30769/com.example.vision_sdk_testing I/testing: registered broadcast receiver!
2020-05-01 17:56:05.283 30769-30769/com.example.vision_sdk_testing I/testing: Camera: device Id 1003 device mName : /dev/bus/usb/001/003
2020-05-01 17:56:05.283 30769-30769/com.example.vision_sdk_testing I/testing: requesting permission
2020-05-01 17:56:05.301 30769-30769/com.example.vision_sdk_testing I/testing: received intent by broadcast com.android.example.USB_PERMISSION
2020-05-01 17:56:05.302 30769-30769/com.example.vision_sdk_testing D/testing: permission denied for device UsbDevice[mName=/dev/bus/usb/001/003,mVendorId=1443,mProductId=38192,mClass=239,mSubclass=2,mProtocol=1,mManufacturerName=Sonix Technology Co., Ltd.,mProductName=USB 2.0 Camera,mVersion=1.00,mSerialNumberReader=android.hardware.usb.IUsbSerialReader$Stub$Proxy#d41ebfa,mConfigurations=[
UsbConfiguration[mId=1,mName=null,mAttributes=128,mMaxPower=128,mInterfaces=[
UsbInterface[mId=0,mAlternateSetting=0,mName=HD USB Camera,mClass=14,mSubclass=1,mProtocol=0,mEndpoints=[]]
UsbConfiguration[mId=3,mName=null,mAttributes=3,mMaxPower=88,mInterfaces=[]]
Any help is appreciated. Thanks!
For me, I had to go into the app's permissions in the settings menu and give my app the Camera permission. I'm guessing it's because my USB device is a camera? Once I granted this permission, the app worked just as described in the docs https://developer.android.com/guide/topics/connectivity/usb/host
Related
I'm trying to connect to a bluetooth headset to record audio from device , the issue is that it shows that it is connected but right after it goes to disconnected for some reason , i'm debugging the code but could not figure out the problem , i would appreciate anyone giving some help , Thank you
Manifest File
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
<uses-permission android:name="android.permission.BLUETOOTH" android:required="false" />
Registering receiver
public void onCreate() {
super.onCreate();
recorder = new Recorder(getApplicationContext());
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
nm = (NotificationManager) getApplicationContext()
.getSystemService(Context.NOTIFICATION_SERVICE);
settings = Core.getInstance().getCache().getPrefs();
self = this;
// register new receiver for bluetooth headset
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if(bluetoothAdapter.isEnabled()){
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); // API 11
intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); // API 8
intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); // API 14
registerReceiver(broadcastReceiver,intentFilter);
audioManager.startBluetoothSco();
}
}
Receiver code
// when the call starts it executed CONNECTED then right after it goes to DISCONNECTED
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,-1);
if(AudioManager.SCO_AUDIO_STATE_CONNECTED == state){
Log.d("TAG","Connected");
audioManager.setSpeakerphoneOn(false);
audioManager.setBluetoothScoOn(true);
} else if (AudioManager.SCO_AUDIO_STATE_DISCONNECTED == state){
Log.d("TAG","Disconnected");
}
}
};
So to alleviate the issue of having to grant permission every time the app is launched, I've followed this answer
So I have my device filter setup
<resources>
<usb-device vendor-id="1234" product-id="5678" />
</resources>
The activity in the manifest
<activity
android:name=".demo.Activity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="#string/title_demo"
android:theme="#style/FullscreenTheme">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="#xml/usb_device_filter" />
</activity>
Then in my java file
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver()
{
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action))
{
synchronized (this)
{
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if(device != null)
{
checkDevice();
}
}
}
}
};
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
mContext.registerReceiver(mUsbReceiver, filter);
If I start the app with the device connected, it doesn't light up and the API for the device won't communicate with it (it does show in the UsbManager.getDeviceList() call, however)
As soon as I physically remove it and plug it back in again, it works
Is there a way I can 'reconnect' the device programatically, or some other fix? Thanks
check if device exist in the device list on app start.
UsbManager manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
Iterator devices = manager.getDeviceList().entrySet().iterator();
while (devices.hasNext()) {
Map.Entry pair = (Map.Entry) devices.next();
Log.i(TAG, pair.getKey() + " = " + pair.getValue());
UsbDevice device = (UsbDevice) pair.getValue();
Log.i(TAG, "UsbDevice: " + device.toString());
if(device.getVendorId() == 1234 && device.getProductId() == 5678) {
}
}
I'm having some trouble with Intent Action_Call. I put the permission in Manifest, but it doesn't work. I press the button to Call and nothing happens. The app that I'm making is an app that does multiple Intents so the code isn't in MainActivity. I don't know if it helps, but I'm using API 28.
Thanks for reading.
MANIFEST:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.intentsimplicitas">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".SmsActivity"></activity>
<activity android:name=".DialActivity" />
<activity android:name=".WaysActivity" />
<activity android:name=".MapActivity" />
<activity android:name=".PageActivity" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
JAVA (DialActivity.java)
public class DialActivity extends Activity {
Button btnDial;
EditText edtPhone;
String phone;
Intent it;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dial);
btnDial = (Button)findViewById(R.id.btnDial);
edtPhone = (EditText)findViewById(R.id.edtPhone);
}
public void dialClick (View v) {
phone = edtPhone.getText().toString();
Uri uri = Uri.parse("tel: " + phone);
it = new Intent(Intent.ACTION_CALL);
it.setData(uri);
startActivity(it);
}
}
From https://developer.android.com/training/permissions/requesting:
Requesting permission:
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.CALL_PHONE)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.CALL_PHONE)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed; request the permission
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.CALL_PHONE},
MY_PERMISSIONS_REQUEST_CALL_PHONE);
// MY_PERMISSIONS_REQUEST_CALL_PHONE is an
// app-defined int constant. The callback method gets the
// result of the request.
}
} else {
// Permission has already been granted
}
Verifying:
#Override
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_CALL_PHONE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request.
}
}
You can do via Intent
public void dialClick (View v) {
phone = edtPhone.getText().toString();
Uri uri = Uri.parse("tel: " + phone);
it = new Intent(Intent.ACTION_DIAL);
it.setData(uri);
startActivity(it);
}
You need to add the permissions at run time to be able to make the call, I recommend the following library, since it is much easier to implement the permissions in time of execution.
https://github.com/Karumi/Dexter
I have my main activity that start a service (Location service) and I want that service to broadcast the new location each time a new location is found.
Thanks to the log I know the service is working and I have new locations every seconds or so, but I never get the broadcast.
MainActivity.java
public class MainActivity extends Activity {
private static final String TAG = "mainActivity";
private CMBroadcastReceiver mMessageReceiver = new CMBroadcastReceiver();
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
// Start Service
startService(new Intent(this, LocationService.class));
super.onCreate(savedInstanceState);
}
#Override
public void onResume()
{
LocalBroadcastManager.getInstance(this).registerReceiver(
mMessageReceiver, new IntentFilter(CMBroadcastReceiver.RECEIVE_LOCATION_UPDATE));
super.onResume();
}
#Override
public void onPause()
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
super.onPause();
}
}
CMBroadcastReceiver.java
public class CMBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "CMBroadcastReceiver";
public static final String RECEIVE_LOCATION_UPDATE = "LOCATION_UPDATES";
#Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "Received broadcast");
String action = intent.getAction();
if (action.equals(RECEIVE_LOCATION_UPDATE))
{
Log.i(TAG, "Received location update from service!");
}
}
}
LocationService.java
/**
* Callback that fires when the location changes.
*/
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
Log.i(TAG, "onLocationChanged " + location);
Intent intent = new Intent(CMBroadcastReceiver.RECEIVE_LOCATION_UPDATE);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
Log.i(TAG, "Broadcast sent");
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cyclemapapp.gpstracker">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main"
android:theme="#style/AppTheme.NoActionBar">
android:configChanges="orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".LocationService" android:process=":location_service" />
</application>
I the log I can see that "Broadcast Sent" But I never get the "Broadcast Received"
Any help will would be greatly appreciated.
EDIT:
Edited how the intent was created in the location service as Shaishav suggested.
Still doesn't work.
LocalBroadcastManager does not work across processes. Your Service is running in a separate process.
You can either run your Service in the same process as the Activity - by removing the process attribute from the <service> element - or use some sort of IPC instead - e.g., by sending and receiving the broadcasts on a Context instead of LocalBroadcastManager.
In your LocationService, send local broadcast using:
Intent intent = new Intent(CMBroadcastReceiver.RECEIVE_LOCATION_UPDATE);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
<service android:name=".LocationService" android:process=":location_service" />
Your service is in a separate process from the activity. LocalBroadcastManager is only for use in one process. Either remove android:process from the <service>, or use some IPC mechanism (e.g., system broadcasts, properly secured).
I am building a voice recognition app that does something when I say a specific word such as "open" and it opens something etc. but the problem is that my app keep crashing when I run it on my phone (real device) and I tap the speak button. I don't know what else to do? I tried giving it internet and voice recognition permission but it still doesn't help
here is the code in java (android studio)
public class MainActivity extends Activity {
private static final int VOICE_RECOGNITION_REQUEST_CODE = 1234;
private TextView resultText;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button speakButton = (Button) findViewById(R.id.SpeakButton);
speakButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
startVoiceRecognitionActivity();
}
});
}
void startVoiceRecognitionActivity(){
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, getClass().getPackage().getName());
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 5);
startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);
}
#Override
protected void onActivityResult (int requestCode,int resultCode, Intent data){
String wordStr = null;
String[] words = null;
String firstWord = null;
String secondWord = null;
if (requestCode == VOICE_RECOGNITION_REQUEST_CODE && resultCode == RESULT_OK)
{
ArrayList<String> matches = data
.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
wordStr = matches.get(0);
words = wordStr.split(" ");
firstWord = words[0];
secondWord = words[1];
}
if (firstWord.equals("open"))
{
resultText = (TextView)findViewById(R.id.ResultText);
resultText.setText("Results: Open Command Works");
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.starlinginteractivesoftworks.musiccompanion">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
I look at the log and it said:
08-07 20:12:57.813 14350-14350/? E/BoostFramework: BoostFramework() :
Exception_1 = java.lang.ClassNotFoundException: Didn't find class
"com.qualcomm.qti.Performance" on path:
DexPathList[[],nativeLibraryDirectories=[/system/lib64,
/vendor/lib64]] 08-07 20:12:58.509
14350-14350/com.starlinginteractivesoftworks.musiccompanion
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.starlinginteractivesoftworks.musiccompanion, PID: 14350
android.content.ActivityNotFoundException: No Activity found to handle
Intent { act=android.speech.action.RECOGNIZE_SPEECH
launchParam=MultiScreenLaunchParams { mDisplayId=0 mFlags=0 } (has
extras) }
at
android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1839)
at
android.app.Instrumentation.execStartActivity(Instrumentation.java:1531)
at android.app.Activity.startActivityForResult(Activity.java:4399)
at android.app.Activity.startActivityForResult(Activity.java:4358)
at
com.starlinginteractivesoftworks.musiccompanion.MainActivity.startVoiceRecognitionActivity(MainActivity.java:55)
at
com.starlinginteractivesoftworks.musiccompanion.MainActivity$1.onClick(MainActivity.java:43)
at android.view.View.performClick(View.java:6205)
at android.widget.TextView.performClick(TextView.java:11103)
at android.view.View$PerformClick.run(View.java:23653)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6682)
at java.lang.reflect.Method.invoke(Native Method)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
The boost framework log is just a warning, no worry about it. The real problem is the
ActivityNotFoundException: No Activity found to handle Intent
It can come from:
a poor connectivity
the voice app is missing on your phone
Possible solutions
Ensure you have a recognition app installed (see ActivityNotFoundException: No Activity found to handle Intent (RECOGNIZE_SPEECH) for more details).
Try to enable offline mode as explained here:
On your device go to Settings -> Language and Input. Click on icon on Google voice input.
Under ALL tab select the language you want to download.
Once the language package downloaded, you can see it under INSTALLED tab.
Workarounds
Catch the exception and open a webview to download a recognition app:
try{
...
}
catch(ActivityNotFoundException e) {
Intent i = new Intent(Intent.ACTION_VIEW,
Uri.parse("https://market.android.com/details?id=APP_PACKAGE_NAME"));
startActivity(i);
}
Check that a recognition app is available before the startActivity (see https://stackoverflow.com/a/35290037/2667536):
PackageManager manager = context.getPackageManager();
List<ResolveInfo> infos = manager.queryIntentActivities(intent, 0);
if (infos.size() > 0) {
//Then there is application can handle your intent
}else{
//No Application can handle your intent
}