I'm trying to do a method that checks for android permissions. But when I call it I have a Missing Permission warning.
Here is a simplification of my code:
public void lintTestMethod(){
if(isPermissionGranted()) {
requiresLocationPermission();
}
}
public boolean isPermissionGranted(){
return true;
}
#RequiresPermission(anyOf = {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION})
public void requiresLocationPermission(){
}
I tried adding:
#SuppressLint("MissingPermission")
public boolean isPermissionGranted(){
return true;
}
But it's not working (I also tried using SuppressWarning).
Ideally, I would like to not have to modify the lintTestMethod method.
Does anyone have an idea on how to deal with that ?
I found a workaround to my problem by reading the lint code checking the permissions (Code). The solution is to name my method called 'isPermissionGranted' : 'check*Permission'. It's not really the solution I was looking for but it works. If anyone has a better way to do it I'm still interested.
Here is the interesting part of the code:
String name = node.astName().astValue();
if ((name.startsWith("check") || name.startsWith("enforce")) && name.endsWith("Permission")) {
mChecksPermission = true;
mDone = true;
}
You place suppression in wrong place:
Single statement suppression:
public void lintTestMethod(){
if(isPermissionGranted()) {
//noinspection MissingPermission
requiresLocationPermission();
}
}
Method range suppression:
#SuppressWarnings("MissingPermission")
public void lintTestMethod(){
if(isPermissionGranted()) {
requiresLocationPermission();
}
}
It can be done using Android Studio quick fix menu.
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Add this in your AndroidManifest.xml file.
Related
I have implemented Billing Library from the following url
https://developer.android.com/google/play/billing/billing_library_overview#java
I am getting error on this line
if (billingResult.getResponseCode() == BillingResponse.OK) {
it says Cannot resolve symbol 'BillingResponse'
here is the complete code from above link
billingClient.startConnection(new BillingClientStateListener() {
#Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingResponse.OK) {
// The BillingClient is ready. You can query purchases here.
}
}
#Override
public void onBillingServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
}
});
I have added following dependency in my apps build.gradle file
dependencies {
...
implementation 'com.android.billingclient:billing:2.1.0'
}
but I am getting error
I cannot even import it manually
import com.android.billingclient.api.BillingClient.BillingResponse;
I know its simple solution is to just replace
BillingResponse.OK
with
BillingClient.BillingResponseCode.OK
but my question is why its not given in documentation then?
I checked the source codes and figured out the correct code.
Though the code on google documentation says billingResult.getResponseCode() == BillingResponse.OK it should be billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
So all you need to do is replace BillingResponse.OK with BillingClient.BillingResponseCode.OK
Is there a switch/flag that allows to do this? I spent hours finding those but couldn't find anything that works. The other thing I'm planning to do is intercept the cefRequest by adding my own CefRequestHandler, examine the resource type and if it matches RT_IMAGE, cancel the request. Everything seems easy except the part when I have to cancel a request. How do I stop/block/cancel a cefRequest? I probably should not be doing it this way but it doesn't work anyway:
public class CefClientRequestHandler extends CefRequestHandlerAdapter {
#Override
public boolean onBeforeResourceLoad(CefBrowser cefBrowser, CefFrame cefFrame, CefRequest cefRequest) {
if (cefRequest.getResourceType().equals(CefRequest.ResourceType.RT_IMAGE)) {
cefRequest.setURL("");
}
return false;
}
// more overides
}
Any ideas?
So here's a hack that works. The trick is to change the Request Method to HEAD, and because HEAD requests aren't returned the body, images won't be part of the response.
public class CefClientRequestHandler extends CefRequestHandlerAdapter {
#Override
public boolean onBeforeResourceLoad(CefBrowser cefBrowser, CefFrame cefFrame, CefRequest cefRequest) {
if (cefRequest.getResourceType().equals(RT_IMAGE)) {
cefRequest.setMethod("HEAD");
}
return false;
}
// other overridden methods here...
}
I believe that this approach should be avoided mainly because of the following two reasons:
Changing the method from GET to HEAD does not prevent CEF from making the request to the server. The overhead of opening a connection and handling a request is still there which makes it slower than simply blocking the request.
I'm not sure if images won't be displayed if they are available from browser cache. Currently, I don't know of any methods to test this. Suggestions are welcome.
Edit 1:
Changing URL didn't work in the example I posted in the question because I was passing an empty String as the new URL. If we set the URL to some address that is not an "active" domain name (e.g. https://absolutegarbage-sdjdjfbskdfb.com), the request for that resource fails immediately:
#Override
public boolean onBeforeResourceLoad(CefBrowser cefBrowser, CefFrame cefFrame, CefRequest cefRequest) {
if (cefRequest.getResourceType().equals(CefRequest.ResourceType.RT_IMAGE)) {
cefRequest.setURL("https://yghjbnbk.com");
System.out.println("LOL!");
}
return false;
}
As you can probably guess, this still is not the best solution. Please post an answer or comment if someone has found a better solution.
Edit 2: Finally I have a clean working solution, thanks to user amaitland. We just have to pass a command line switch while setting the CefAppHandler. We can do that by overriding the method onBeforeCommandLineProcessing like this:
CefApp.addAppHandler(new CefAppHandlerAdapter(null) {
#Override
public void onBeforeCommandLineProcessing(String s, CefCommandLine cefCommandLine) {
cefCommandLine.appendSwitch("disable-image-loading");
}
#Override
public void stateHasChanged(CefApp.CefAppState state) {
if (state == CefApp.CefAppState.TERMINATED) System.exit(0);
}
});
I m trying to get the Internal Storage path of a Android Device.
Since most of the devices late off return Internal Storage path using Environment.getExternalStorageDirectory().getPath(); so I am using this to get the path.
Every thing is working fine except that when I am calling Environment.getExternalStorageDirectory().getPath(); from an non Activity class it is returning null whereas if I call it from a Activity class it returns the correct path.
I Tried searching other posts but could not find anything useful.
Any help would be really grateful.
EDIT:
if(getExtSdCardPath(con)!=null)
{ path=getExtSdCardPath(con);
if(new File(path).getPath().equal(Environment.getExternalStorageDirectory().getPath())) // This line give null "Null Pointer exception"
{
return null;
}
return path;
}
I am checking if the SD Card path is same as the path which is returned by Environment.getExternalStorageDirectory().getPath()
Ideally, getExtSdCardPath() would be "idempotent", which is a fancy way of saying "does the same work and returns the same thing no matter how many times you call it".
In your case, it is not. The first call to getExtSdCardPath() is returning the value that you want, and the second call to getExtSdCardPath() is returning null.
In your case, there is no particular need to call getExtSdCardPath() twice, and so you can work around the idempotence issue by rewriting your code to be something like:
path=getExtSdCardPath(con);
if(path!=null)
{
if(new File(path).getPath().equal(Environment.getExternalStorageDirectory().getPath())) // This line give null "Null Pointer exception"
{
return null;
}
return path;
}
Sounds like you forgot to put the requested permission in the manifest OR/AND forgot to ask for such a permission in runtime (in case you run this on devices with android 6.0 and above).
try to addto your manifest : <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Here a quick and simple implementation example of how to request the permission in runtime:
public class MainActivity extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback{
private static final int REQUEST_WRITE_PERMISSION = 111; //Number is not matter, just put what you want
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == REQUEST_WRITE_PERMISSION && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//Do your stuff with the file
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestPermission();
}
private void requestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_PERMISSION);
} else {
//Do your stuff with the file
}
}
}
I started my android studio and when I ran my app, I get a lot of error comming from drawable.java. For example, in the following piece of drawable.java I got:
NonNull, TRACE_TAG_RESOURCES, traceBegin, traceEnd, insets,
DENSITY_DEVICE, noncompatDensityDpi and getOpticalInsets all shows the
error "cannot resolve symbol" or "cannot resolve method".
public boolean getPadding(#NonNull Rect padding) {
padding.set(0, 0, 0, 0);
return false;
}
public Insets getOpticalInsets() {
return Insets.NONE;
}
public void getOutline(#NonNull Outline outline) {
outline.setRect(getBounds());
outline.setAlpha(0);
}
public Drawable mutate() {
return this;
}
public void clearMutated() {
// Default implementation is no-op.
}
public static Drawable createFromStream(InputStream is, String srcName) {
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, srcName != null ? srcName : "Unknown drawable");
try {
return createFromResourceStream(null, null, is, srcName);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
}
}
public static Drawable createFromResourceStream(Resources res, TypedValue value,
InputStream is, String srcName) {
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, srcName != null ? srcName : "Unknown drawable");
try {
return createFromResourceStream(res, value, is, srcName, null);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
I have never even touched drawable.java and I did not even know it ever existed. I tried cleaning up the project but nothing has changed. Is there any solution to this problem?
On Android Studio try to go to:
File -> Invalidate Caches/Restart -> Invalidate & restart.
As far as I can guess that, you've done something wrong with you layout or xml files. Please check if all the layouts are error free.
I would like to suggest a TODO list for you so that you look for all the reasons which might create this type of error.
Check all the layout files for errors.
Check all the drawables.
Check if any layout file name contains any capital letter.
Check if any image file name contains any capital letter.
If everything is okay, then do a clean and rebuild the application.
I found a couple of solutions how to do that in Java, but did not find how can I do it in QML or Qt. I know that first I should set the WAKE_LOCK permission in AndroidManifest.xml. What should I do to make it possible to turn on and off the screen locking from Qt in runtime?
Use window.callMethod<void> instead of window.callObjectMethod
Run on GUI thread with QtAndroid::runOnAndroidThread
Clear exceptions afterwards
To disable always on behaviour, use clearFlags
This is tested Qt 5.7 code:
void keep_screen_on(bool on) {
QtAndroid::runOnAndroidThread([on]{
QAndroidJniObject activity = QtAndroid::androidActivity();
if (activity.isValid()) {
QAndroidJniObject window =
activity.callObjectMethod("getWindow", "()Landroid/view/Window;");
if (window.isValid()) {
const int FLAG_KEEP_SCREEN_ON = 128;
if (on) {
window.callMethod<void>("addFlags", "(I)V", FLAG_KEEP_SCREEN_ON);
} else {
window.callMethod<void>("clearFlags", "(I)V", FLAG_KEEP_SCREEN_ON);
}
}
}
QAndroidJniEnvironment env;
if (env->ExceptionCheck()) {
env->ExceptionClear();
}
});
}
You can use the Qt Android Extras module and use JNI to call the relevant Java function from C++. Something like :
void keepScreenOn()
{
QAndroidJniObject activity = QtAndroid::androidActivity();
if (activity.isValid()) {
QAndroidJniObject window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;");
if (window.isValid()) {
const int FLAG_KEEP_SCREEN_ON = 128;
window.callObjectMethod("addFlags", "(I)V", FLAG_KEEP_SCREEN_ON);
}
}
}
You can achieve this by editing the java file used by qt itself. In installation path under src in android path you will find QtActivity.java file. In the onCreate function add the below line
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
WAKE_LOCK permission in AndroidManifest.xml also should be added.
Build the project, it will work fine.