I register geofence this way:
GeofencingClient client = LocationServices.getGeofencingClient(context);
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
builder.addGeofence(new Geofence.Builder()
.setRequestId(buildRequestId(objectId))
.setCircularRegion(location.getLatitude(), location.getLongitude(), 500)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
.build());
client.addGeofences(builder.build(), PendingIntent.getService(context, objectId,
new Intent(context, HomeGeofenceService.class).putExtra(KEY_OBJECT_ID, objectId), PendingIntent.FLAG_UPDATE_CURRENT)).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
ObjectManager.getInstance(objectId).setLocationNotifEnabled(false);
ObjectManager.save();
int statusCode = -1;
if (e instanceof ApiException)
statusCode = ((ApiException) e).getStatusCode();
context.sendBroadcast(new Intent(UiConstants.ACTION_GEOFENCE_ERROR).putExtra(KEY_CODE, statusCode));
}
});
Service in manifest:
<service android:name=".services.HomeGeofenceService"/>
play services version: implementation 'com.google.android.gms:play-services-location:15.0.1'
Service:
public class HomeGeofenceService extends IntentService {
public HomeGeofenceService() {
super(HomeGeofenceService.class.getSimpleName());
}
protected void onHandleIntent(Intent intent) { /***some code**/ }
}
List of permissions:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
targetSdkVersion 27
This code was working fine in our app from April 19th. Can this issue be connected to the fact that we're in russian region? With all IP bans. Or maybe there is some other issue here?
Related
I'm working on a simple system app in Oreo AOSP to turn ON wifi Hotspot with predefined SSID and preshared key.
As my APP is built as a system app so i don't need reflection.
MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
boolean result = false;
WifiManager mwifiManager;
mwifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
try {
Method method = mwifiManager.getClass().getMethod("getWifiApConfiguration");
WifiConfiguration netconfig = (WifiConfiguration) method.invoke(mwifiManager);
netconfig.SSID = "DummyApp";
netconfig.preSharedKey = "1234567890";
netconfig.allowedKeyManagement.set(4);
mwifiManager.setWifiEnabled(false);
method = mwifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
result = (boolean) method.invoke(mwifiManager, netconfig, true);
if (!result) {
Toast.makeText(this, "Hotspot creation failed", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Wifi Enabled", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
finish();
}
#Override
protected void onResume() {
super.onResume();
}
}
AndroidManifest.xml
android:protectionLevel="signature|privileged"
android:sharedUserId="android.uid.system">
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- for wifi -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.TETHER_PRIVILEGED" />
Wifi Should turn ON but getting following result:
Toast Message: Hotspot creation failed
Logcat: WifiManager: PACKAGE_NAME attempted call to setWifiApEnabled: enabled = true
update1: How to turn on/off wifi hotspot programmatically in Android 8.0 (Oreo)
I have tried above changes. It will turn on Hotspot locally but no custom SSID and password.
update2: After getting input from #Mr.AF.
Method setConfigMethod = mWifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
......code snip.........
netconfig.allowedKeyManagement.set(4);
Method Method = mWifiManager.getClass().getMethod("setWifiApConfiguration", WifiConfiguration.class);
HOTSPOT Creation FAiled
To turn ON Portable HotSpot in Android Nougat and below following code works.
Method method = mwifiManager.getClass().getMethod("getWifiApConfiguration");
WifiConfiguration netconfig = (WifiConfiguration) method.invoke(mwifiManager);
method = mwifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
result = (boolean) method.invoke(mwifiManager, netconfig, true);
Above API is deprecated in Oreo.
Following is a #system hidden API in oreo, If the android application is built as a system app then only below API code can be accessed. In my case, I can use the below API.
ConnectivityManager oncm = (ConnectivityManager)ontext.getSystemService(Context.CONNECTIVITY_SERVICE);
oncm.startTethering(ConnectivityManager.TETHERING_WIFI, true, new ConnectivityManager.OnStartTetheringCallback() {
#Override
public void onTetheringStarted() {
super.onTetheringStarted();
Log.i(TAG, "Hotspot is successfully opened");
}
#Override
public void onTetheringFailed() {
super.onTetheringFailed();
Log.e(TAG, "Hotspot failed to open");
}
});
You don't need to use reflection for versions>=Oreo. After android's public exposed API startLocalOnlyHotspot. I've explained this answer in detail on this question on Stackoveflow.
Receiver works on all android versions from 4.2 upto 8.0. Even if app is removed from Recent Apps But if removed from Recent Apps in Android Oreo, it then never triggers receiver again.
my manifest.xml :
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<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"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".WatchMan"
android:enabled="true"
android:exported="true" />
<receiver
android:name=".Receiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</application>
My receiver.java :
public class Receiver extends BroadcastReceiver
{
public String PhoneNumber = "UNKNOWN";
#Override
public void onReceive(Context context, Intent intent)
{
Log.d("RECEIVER :","CAPTURED THE EVENT.....");
try
{
PhoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
PhoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
context.startForegroundService(new Intent(context, WatchMan.class));
}
else
{
context.startService(new Intent(context, WatchMan.class));
}
}
catch (Exception e)
{
e.printStackTrace();
Log.e("RECEIVER EXCEPTION : ", "Exception is : ", e);
}
}
I want to know if i am doing any mistake in code? Android Developers Documentation asking to register receiver runtime using context. Then i searched for registering it in runtime on stackoverflow but looks no proper thread accepted as answer. How can make receiver to to be ready again, even if removed from recents of Android Oreo?
Thanking you in advance.
I have deleted unrelated posts. I am posting final answer as it may help others. #WIZARD help was thankful.
PHONE_STATE is implicit and will not be triggered on android Oreo or higher. So just place permissions in manifest like :
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<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"
android:excludeFromRecents="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".WatchMan"
android:enabled="true"
android:exported="true">
</service>
<service
android:name=".CatchNumbers"
android:enabled="true"
android:exported="true">
</service>
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
Register implicit receivers from foreground service :
public class WatchMan extends Service
{
NotificationManager mNotifyManager;
NotificationCompat.Builder mBuilder;
NotificationChannel notificationChannel;
String NOTIFICATION_CHANNEL_ID = "17";
private boolean running;
private BroadcastReceiver mCallBroadcastReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
String PhoneNumber = "UNKNOWN";
Log.d("RECEIVER : ","HERE HERE");
try
{
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if(state == null)
{
PhoneNumber = "UNKNOWN";
}
else if (state.equals(TelephonyManager.EXTRA_STATE_RINGING))
{
PhoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.d("INCOMING ","Incoming number : "+PhoneNumber);
}
if(intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL"))
{
PhoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Log.d("OUTGOING ","Outgoing number : "+PhoneNumber);
}
if(!PhoneNumber.contentEquals("UNKNOWN"))
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
context.startForegroundService(new Intent(context, CatchNumbers.class));
}
else
{
context.startService(new Intent(context, CatchNumbers.class));
}
}
}
catch (Exception e)
{
e.printStackTrace();
Log.e("RECEIVER EXCEPTION : ", "Exception is : ", e);
}
}
};
public WatchMan() { }
#Override
public void onCreate()
{
super.onCreate();
mBuilder = new NotificationCompat.Builder(this, null);
IntentFilter filterstate = new IntentFilter();
filterstate.addAction("android.intent.action.NEW_OUTGOING_CALL");
filterstate.addAction("android.intent.action.PHONE_STATE");
this.registerReceiver(mCallBroadcastReceiver, filterstate);
Log.d("RECEIVER : ", "\nCreated....");
mNotifyManager = (NotificationManager) getApplicationContext().getSystemService(NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this, null);
mBuilder.setContentTitle("Insta Promo")
.setContentText("Insta Promo Is Up..")
.setTicker("Insta Promo Is Up..")
.setSmallIcon(R.drawable.ic_launcher_background)
.setPriority(Notification.PRIORITY_HIGH)
.setDefaults(Notification.DEFAULT_ALL)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setOngoing(true)
.setAutoCancel(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_HIGH);
// Configure the notification channel.
notificationChannel.setDescription("Channel description");
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
notificationChannel.enableVibration(true);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
mNotifyManager.createNotificationChannel(notificationChannel);
}
running = true;
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
startForeground(17, mBuilder.build());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d("RECEIVER : ", "\nOnStartCommand....");
new Thread(new Runnable()
{
public void run()
{
while(running)
{
try
{
Log.d("RECEIVER : ", "\nALIVE..");
Thread.sleep(10000);
}
catch (InterruptedException e)
{
Log.d("RECEIVER : ", "\nThread : InterruptedException in Receiver...");
Log.e("RECEIVER : ", "\nException is : ", e);
}
catch (Exception e)
{
Log.d("RECEIVER : ", "\nThread : Exception Error in Receiver...");
Log.e("RECEIVER : ", "\nException is : ", e);
}
}
}
}).start();
return START_STICKY;
}
#Override
public void onDestroy()
{
this.unregisterReceiver(mCallBroadcastReceiver);
running = true;
Log.d("RECEIVER : ", "\nDestroyed....");
Log.d("RECEIVER : ", "\nWill be created again....");
}
#Override
public IBinder onBind(Intent intent)
{
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onTaskRemoved(Intent rootIntent)
{
super.onTaskRemoved(rootIntent);
Log.d("SERVICE : ", "\nTask Removed....");
}
}
There are some intent actions like NEW_OUTGOING_CALL AND BOOT_COMPLETED which are excluded and can be implemented in receiver and placed in manifest like :
public class MyReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Log.d("INSTA_BOOT : ", "\nBOOT_COMPLETE_EVENT_OF_INSTA....");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
context.startForegroundService(new Intent(context, WatchMan.class));
}
else
{
context.startService(new Intent(context, WatchMan.class));
}
}
}
As i wanted to re-register or say want to restart foreground service on REBOOT OR BOOT-COMPLETE
CatchNumbers.java is a simple service which performs operation when receiver triggers perticular actions.
It works good on every restart and as android:excludeFromRecents="true" is not needed anymore as even if user removes it from recents on Oreo it will restart the service as it is STICKY. Hope it helps someone like me..!!
Based on the documentation for restrictions on implicit broadcast in Android 8, you cannot use implicit receivers in your manifest (although there are some exceptions, but phone state receiver is not among those exceptions)
You have to use foreground service and register your receiver in your foreground service instead of manifest
remove phone state receiver from manifest
register receiver in onCreate of Service:
#Override
public void onCreate() {
super.onCreate();
phoneStateReceiver = new PhoneStateReceiver();
registerReceiver(phoneStateReceiver, new IntentFilter(TelephonyManager.ACTION_PHONE_STATE_CHANGED));
}
unregister in onDestroy:
#Override
public void onDestroy() {
unregisterReceiver(phoneStateReceiver);
super.onDestroy();
}
add a static method to your service to start service:
// start service even if your app is in stopped condition in android 8+
static void requestStart(#NonNull final Context context, #NonNull final String action){
final Context appContext = context.getApplicationContext();
Intent intent = new Intent(appContext, AppService.class);
intent.setAction(action);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// this is required to start the service if there is
// no foreground process in your app and your app is
// stopped in android 8 or above
appContext.startForegroundService(intent);
} else {
appContext.startService(intent);
}
}
start foreground in your onStartCommand
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(ACTION_START.equals(intent.getAction()))
startForeground(ID, notification);
else if(ACTION_STOP.equals(intent.getAction()))
stopForeground(true);
return START_STICKY;
}
I am currently working on a music tuner that uses html5 and a webview to display the 'application'. I've written the all the permission required in manifest and I think for webview there's another permission required.
I am using this https://jbergknoff.github.io/guitar-tuner/ as a sample redirect page for now
Here's my manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.raynordev.projectrosin">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MICROPHONE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:name="android.hardware.audio.low_latency" />
<uses-feature android:name="android.hardware.audio.pro" />
<uses-feature android:name="android.hardware.microphone" android:required="true"/>
<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:theme="#style/Theme.AppCompat.Light.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.raynordev.projectrosin.HomeActivity">
</activity>
</application>
</manifest>
Here's my .java
public class HomeActivity extends AppCompatActivity {
private WebView wv;
private String TAG = "HomeActivity";
private static final int REQUEST_INTERNET = 200;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
WebView wv = (WebView) findViewById(R.id.webView);
wv.getSettings().setJavaScriptEnabled(true);
wv.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
wv.setWebViewClient(new WebViewClient());
wv.setWebChromeClient(new WebChromeClient());
wv.loadUrl("https://jbergknoff.github.io/guitar-tuner/");
}
}
If require more information from me, please let me know.
Thank you everyone!!
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
Example:
MainActivity
public class MainActivity extends AppCompatActivity {
private static final int MY_PERMISSIONS_REQUEST_RECORD_AUDIO = 101;
private ActivityMainBinding mBinding;
private PermissionRequest myRequest;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
setWebView();
}
private void setWebView() {
mBinding.webView.getSettings().setJavaScriptEnabled(true);
mBinding.webView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
mBinding.webView.setWebViewClient(new WebViewClient());
mBinding.webView.getSettings().setSaveFormData(true);
mBinding.webView.getSettings().setSupportZoom(false);
mBinding.webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
mBinding.webViemBinding.webView.getSettings().setPluginState(WebSettings.PluginState.ON);
mBinding.webView.setWebChromeClient(new WebChromeClient() {
#Override
public void onPermissionRequest(final PermissionRequest request) {
myRequest = request;
for (String permission : request.getResources()) {
switch (permission) {
case "android.webkit.resource.AUDIO_CAPTURE": {
askForPermission(request.getOrigin().toString(), Manifest.permission.RECORD_AUDIO, MY_PERMISSIONS_REQUEST_RECORD_AUDIO);
break;
}
}
}
}
});
mBinding.webView.loadUrl("<your url");
}
#Override
public void onBackPressed() {
if (mBinding.webView.canGoBack()) {
mBinding.webView.goBack();
} else {
super.onBackPressed();
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_RECORD_AUDIO: {
Log.d("WebView", "PERMISSION FOR AUDIO");
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
myRequest.grant(myRequest.getResources());
mBinding.webView.loadUrl("<your url>");
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
}
// other 'case' lines to check for other
// permissions this app might request
}
}
public void askForPermission(String origin, String permission, int requestCode) {
Log.d("WebView", "inside askForPermission for" + origin + "with" + permission);
if (ContextCompat.checkSelfPermission(getApplicationContext(),
permission)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
permission)) {
// Show an expanation 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, we can request the permission.
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{permission},
requestCode);
}
} else {
myRequest.grant(myRequest.getResources());
}
}
}
Mainfest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MICROPHONE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:name="android.hardware.audio.low_latency" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-feature android:name="android.hardware.audio.pro" />
<uses-feature android:name="android.hardware.microphone"/>
Build.gradle:
android {
compileSdkVersion 26
defaultConfig {
applicationId "myapp.example.com.myapplication"
minSdkVersion 21
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
Summarising, you need the following components:
The MODIFY_AUDIO_SETTINGS permission.
A WebChromeClient and listen to callbacks for onPermissionRequest
Inside this callback, check for the the resources coming in the request object, create a global variable of this request object, iterate and look for specific permission inside the PermissionRequest class, ex. PermissionRequest.RESOURCE_VIDEO_CAPTURE which translates to the Manifest.permission.CAMERA permission, check if your app has this permission or not, using any mechanism you wish if not, request, if yes do 4.
In the permission callback or if the permission is granted, use the request object to grant the permission ex. request.grant(new String[]{PermissionRequest.RESOURCE_VIDEO_CAPTURE}) and you're good to go.
snippet:
webView.webChromeClient = object: WebChromeClient(){
override fun onPermissionRequest(request: PermissionRequest?) {
super.onPermissionRequest(request)
webkitPermissionRequest = request
request?.resources?.forEach {
when(it){
PermissionRequest.RESOURCE_AUDIO_CAPTURE-> {
askForWebkitPermission(it, Manifest.permission.RECORD_AUDIO, REQUEST_CODE_PERMISSION_AUDIO)
}
PermissionRequest.RESOURCE_VIDEO_CAPTURE->{
askForWebkitPermission(it, Manifest.permission.CAMERA, REQUEST_CODE_PERMISSION_CAMERA)
}
}
}
}
}
private fun askForWebkitPermission(webkitPermission: String, androidPermission: String, requestCode: Int){
val context = activity?: return
if (context.hasPermission(androidPermission)){
webkitPermissionRequest!!.grant(arrayOf(webkitPermission))
}else{
requestPermissions(arrayOf(androidPermission), requestCode)
}
}
Hope this helps.
Google's sample for the same: https://github.com/googlesamples/android-PermissionRequest
its problems for reload the webview , after too much research , found this code and create this below code :-
mwebView.setWebChromeClient(new WebChromeClient() {
#Override
public void onPermissionRequest(final PermissionRequest request) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
myRequest = request;
for (String permission : request.getResources()) {
if (permission.equals("android.webkit.resource.AUDIO_CAPTURE")) {
demandForPermission(request.getOrigin().toString(), Manifest.permission.RECORD_AUDIO, MY_PERMISSIONS_REQUEST_RECORD_AUDIO);
} else {
myRequest.grant(request.getResources());
}
}
}
}
#Override
public void onPermissionRequestCanceled(PermissionRequest request) {
super.onPermissionRequestCanceled(request);
}
more info in this link Android Webview
I am working on Sony Remote camera which is connected using WiFi.I need to click a picture using a camera and then upload it to my FTP server which is in another activity.for than I need to disconnect my camera wifi and connect to the another wifi network or mobile data.when I connect to the another wifi/mobile data and going to upload the picture on FTP server I got this error.
IOException Unable to resolve host No address associated with hostname
When a close application and start again, And then directly upload pictures without connecting/disconnection camera than it works fine.
someone, please tell me how can I solve this, because I checked each and every solution on stack overflow and not one solution work for me.
I added bellow permissions
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
Connection to a network is not inmediate.
Also, if the desired network has no internet connection, in recent versions of Android it will not connect (if the connection is made by a user, a popup shows a confirmation to connnect).
I solved both problems using Android APIs (2 versions, one for API<21 and the other for API>=21).
Try this code (I'm using AndroidAnnotations for dependency injection, but is not required):
public class WifiHelper extends BroadcastReceiver {
#RootContext
Context context;
#SystemService
ConnectivityManager connectivityManager;
#SystemService
WifiManager wifiManager;
// For API>=21
private WifiHelperNetworkCallback wnc;
// For API<21
private boolean isBroadcastRegistered;
private String desiredSSID;
private Runnable callback;
public void enableNetwork(String ssid, int networkId, Runnable callback) {
desiredSSID = ssid;
wifiManager.enableNetwork(networkId, true);
configureNetworkRequest();
}
private void networkAvailable() {
// this method will be called when the network is available
callback.run();
}
private void configureNetworkRequest() {
if (android.os.Build.VERSION.SDK_INT >= 21) {
configureNetworkRequestAPI21();
} else {
configureNetworkRequestLegacy();
}
}
#TargetApi(21)
private void configureNetworkRequestAPI21() {
NetworkRequest request = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build();
if (wnc == null) wnc = new WifiHelperNetworkCallback(this, connectivityManager);
connectivityManager.requestNetwork(request, wnc);
}
private void configureNetworkRequestLegacy() {
unregisterReceiver();
connectivityManager.startUsingNetworkFeature(ConnectivityManager.TYPE_WIFI, null);
IntentFilter intent = new IntentFilter();
intent.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
intent.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
context.registerReceiver(this, intent);
isBroadcastRegistered = true;
}
#TargetApi(21)
private void disableNetworkRequest() {
if (android.os.Build.VERSION.SDK_INT >= 21) {
if (wnc != null) connectivityManager.unregisterNetworkCallback(wnc);
ConnectivityManager.setProcessDefaultNetwork(null);
} else {
unregisterReceiver();
}
}
private void unregisterReceiver() {
if (isBroadcastRegistered) {
context.unregisterReceiver(this);
isBroadcastRegistered = false;
}
}
// API<21
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
NetworkInfo networkInfo =
intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if(networkInfo.isConnected()) {
// Wifi is connected
if (desiredSSID.equals(getCurrentSSID())) {
// Callback and unregister
networkAvailable();
unregisterReceiver();
}
}
}
}
public String getCurrentSSID() {
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
if (wifiInfo != null && wifiInfo.getSupplicantState()== SupplicantState.COMPLETED) {
return ssidWithoutQuotes(wifiInfo.getSSID());
}
else return null;
}
protected static String ssidWithoutQuotes(String ssid) {
if (ssid == null) return null;
else if (ssid.startsWith("\"") && ssid.endsWith("\"")) {
return ssid.substring(1, ssid.length() - 1);
} else {
return ssid;
}
}
protected String getDesiredSSID() {
return desiredSSID;
}
#TargetApi(21)
public static class WifiHelperNetworkCallback extends ConnectivityManager.NetworkCallback {
public final String LOG_TAG = WifiHelper.class.getSimpleName();
private ConnectivityManager connectivityManager;
private WifiHelper wifiHelper;
public WifiHelperNetworkCallback(WifiHelper wifiHelper, ConnectivityManager connectivityManager) {
this.wifiHelper = wifiHelper;
this.connectivityManager = connectivityManager;
}
public void onAvailable(Network network) {
// Do something once the network is available
NetworkInfo info = connectivityManager.getNetworkInfo(network);;
Log.i(LOG_TAG, "networkcallback!! " + info.getExtraInfo());
String desiredSSID = wifiHelper.getDesiredSSID();
if (desiredSSID != null && desiredSSID.equals(ssidWithoutQuotes(info.getExtraInfo()))) {
ConnectivityManager.setProcessDefaultNetwork(network);
wifiHelper.networkAvailable();
}
}
}
}
You will need this permissions:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" android:maxSdkVersion="18"/>
I want to use ContentObserver for handling microphone state. But it's doesn't work. Nothing comes in method onChange.
public class MainActivity extends Activity implements OnClickListener{
AudioManager amAudioManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
amAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
getContentResolver().registerContentObserver(
System.getUriFor(System.MUTE_STREAMS_AFFECTED),
false, mMuteObserver);
}
private ContentObserver mMuteObserver = new ContentObserver(new Handler()) {
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
amAudioManager.setMicrophoneMute(false);
}
};
#Override
public void onClick(View v) {
int id = v.getId();
//just for test functional
amAudioManager.setMicrophoneMute(true);
}
}
Android manifest file permissions:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />**