What will happen if permission is revoked when application is opened? I have already given it a try and found that application's process is suddenly terminated. Everything inside application just simply stopped. And locally saved Apputil values becomes null when i turned off the permission when app is opened.If anyone knows the reason please suggest me and how to resolve this issue
// I am extending drawer activity to get the saved card number here
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
LayoutInflater inflater = (LayoutInflater) this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View contentView = inflater.inflate(R.layout.activity_reward_yourself,
null, false);
titleTextView.setText(R.string.reward_yourself_title);
frameLayout.addView(contentView, 0);
rewardsSwipeLayout = (SwipeRefreshLayout) findViewById(R.id.rewardsSwipeContainer);
grid = (GridView) findViewById(R.id.gridReward);
tvPointsValue = (TextView) findViewById(R.id.tvPointsValue);
tvFirstText = (TextView) findViewById(R.id.tvFirstText);
rewardsSwipeLayout.setOnRefreshListener(this);
rewardsSwipeLayout.setColorScheme(android.R.color.black,
android.R.color.white, android.R.color.darker_gray,
android.R.color.black);
initialUiSetUp();
program = new Program();
String str= AppUtil.fxs.getCardNumber(); //becomes null when location is off when app is opened
checkPermission(MyActivity.this);
mAccInfo = new Account();
mTask = new GetAccount().execute();
}
You should always check explicitly whether permission is granted by system. For example in my case i am accessing location in my app. All location task will performed by function onLocationPermissionGranted(), So before calling that i will check location permission as below
if (!PermissionRequestManager.checkIfAlreadyhavePermission(getActivity(),Manifest.permission.ACCESS_FINE_LOCATION)) {
PermissionRequestManager.requestPermissionAccessFineLocation(getActivity());
} else onLocationPermissionGranted();
I hope..I am not late....
The best solution is to use third party libraries...to implement run time permissions in a simplest way...
https://github.com/hotchemi/PermissionsDispatcher
I have used the above library. it is best on annotations in java.
Related
We have an app that has a function using the Android share facility. If a property listing is shared from the Rightmove app, our app takes that property and adds the details to our server-side database. When the app is launched normally (not through share) it checks for updates on launch.
The app does what it is supposed to do when launched normally and also when launched by sharing from the Rightmove app. Except in the latter case it continues to check for updates which is not supposed to do.
Here is the onCreate() method where all the relevant code resides:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Intent rightmove = getIntent();
String action = rightmove.getAction();
String type = rightmove.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
String rm_text = rightmove.getStringExtra(Intent.EXTRA_TEXT);
if (rm_text.startsWith("I found this property on the Rightmove")) {
String[] parts = rm_text.split("/");
String rm_code = parts[parts.length - 1];
new UpdateList().execute(rm_code);
} else {
Toast.makeText(this.getApplicationContext(), "Lets Delight only takes share information from the Rightmove app", Toast.LENGTH_LONG).show();
}
this.finish();
}
user = findViewById(R.id.user);
status = findViewById(R.id.status);
message = findViewById(R.id.message);
Button dman = findViewById(R.id.button_decision);
Button todo = findViewById(R.id.button_todo);
new Update(status).check(this);
}
The if block for dealing with the share ends with this.finish(); but the code continues after this and checks for updates. It must therefore draw a UI that is not required or used.
Is it a case that finish(); takes a while to complete and, whilst it is doing so, the code continues to execute or is something else happening here? Either way, what is the "correct" way to handle having share information sent to an app that just processes that share data without presenting a UI to the user?
I am aware about the changes introduced in Android 6.0/SDKVersion 23 regarding the run-time permission. There is already discussion and talks on this topic in the below post which talks about the various aspects of new permission model.
"How to request permissions from a Service in Android Marshmallow"
Google I/O 2015 - Android M Permissions
"Mother, May I?" Asking for Permissions (Android Dev Summit 2015)
After going thorough these article,I believe below is suggested to "workaround" (as Service doesnot have UI support)this problem.
Check permission checkSelfPermission() in the context of
Service.
Notify it to status bar in case the permission is denied.
User would now click on status bar which would launch a new
DialogActivity to request for permission when users press on the
notification.
I am not able to make the workable version of the suggestions provided to achieve this task. When we launch DialogActivity to ask for permission, it would be assigned and available for that activity. It would not be applicable for background service who had put it on status bar and even after this service would not be granted this permission(instead the permission would be given to DialogActivity).
Could somebody provide the input(possibly workable logic/code) so that I can make it workable(.i.e. execute the code in the context of Service which would be dependent on whether permission is granted or not).
My Scenario
Develop application which would send the SMS at regular interval
regarding the my current location.
I have designed the UI for this application as mentioned below. It had some settings parameters and also buttons which would start the main logic which is:
Start monitoring the current location and
Send the SMS to configured contact numbers.
I believe user would minimize this application( as it does not have any interesting logic apart from sending the SMS) and it should continue to work in background(.i.e. monitoring the location and sending the SMS). Hence I thought to use move this logic in Service instead of keeping it the Activity itself. If I keep these logic in Activity itself, it works as expected however for that user is suppose to keep the application in foreground all the time.
So far I have been able to achieve the following:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Define START/STOP button handles.
mStartApp = (ImageButton)findViewById(R.id.startApp);
mStopApp = (ImageButton)findViewById(R.id.stopApp);
//Write event handlers for above grabbed buttons.
mStartApp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent startService = new Intent(getApplicationContext(),
CurrentLocationTrackerService.class);
startService(startService);
}
});
mStopApp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent stopService = new Intent(getApplicationContext(),
CurrentLocationTrackerService.class);
stopService(stopService);
}
});
// Support for the ActionBar widgets menu in current activity.
Toolbar mToolBar = (Toolbar)findViewById(R.id.myToolbar);
if(mToolBar != null) {
setSupportActionBar(mToolBar);
}
}
//Other methods.....
}
public class CurrentLocationTrackerService extends Service {
public CurrentLocationTrackerService() { }
#Override
public void onCreate() { }
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
int permissionLocationAccess = ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.ACCESS_FINE_LOCATION);
// If permissionLocationAccess is true execute further
// If permissionLocationAccess false(which would always as we are in Service and it is dangerous
// permission) we need to put some information to status bar. Post that user would click on that
// which would launch some new activity where UI of asking permission would be shown. But still
// Service would not get the permission( only new activity would have that permission but it is
// of no use here as I am planning to put these logic iside the Service as my app may not be always
// be in foreground)
}
}
Hope I have provided all detail regarding the problem and also my application context regarding why I require to model in this way.The real point over here is how to achieve this.
I am really stuck at this point and any help would be highly appreciated. Kindly let me know in case anything else is required from my side.
I have a networkStateReceiver, that checks if I have internet or not.
If I do, I reinitiate instabug, if not, I want to deactivate. How can I do that?
I tried just setting it as null, but it doesn't work.
if(haveConnectedMobile || haveConnectedWifi){
//TODO will need to make a queue, and go through all that queue
PSLocationCenter.getInstance().initInstabug();
}else{
PSLocationCenter.getInstance().instabug = null;
}
This is my init:
public void initInstabug() {
String[] feedbackArray = getResources().getStringArray(R.array.feedback);
String randomStr = feedbackArray[new Random().nextInt(feedbackArray.length)];
Instabug.DEBUG = true;
instabug = Instabug.initialize(this)
.setAnnotationActivityClass(InstabugAnnotationActivity.class)
.setShowIntroDialog(true, PSTimelineActivity.class)
.enableEmailField(true, false)
.setEnableOverflowMenuItem(true)
.setDebugEnabled(true)
.setCommentRequired(true)
.setPostFeedbackMessage(randomStr)
.setPostBugReportMessage(randomStr) //TODO will be the post report message, random from array
.setCommentFieldHint("Please describe what went wrong")
.setPreSendingRunnable(new Runnable() {
#Override
public void run() {
String[] files = new String[2];
files[0] = Environment.getExternalStorageDirectory() + "/Passenger/passenger_log.txt";
files[1] = Environment.getExternalStorageDirectory() + "/Passenger/passenger_log2.txt";
Compress compress = new Compress(files, Environment.getExternalStorageDirectory() + "/Passenger/log.zip");
compress.zip(new CrudStateCallback() {
#Override
public void onResponse(String string) {
Log.i("", "ended making the archive");
}
});
}
})
.attachFileAtLocation(Environment.getExternalStorageDirectory() + "/Passenger/log.zip");
}
You can use this code to disable Instabug automatic invocation:
Instabug.getInstance().setInvocationEvent(IBGInvocationEvent.IBGInvocationEventNone)
This way it won't be invoked automatically. This will only affect the next Activity though (not the current one). You may force to stop and restart all listeners by calling onPause and onResume on the current Activity. (We may address that soon though, so that such changes are applied on the currently running Activity).
Don't forget to also enable the shake invocation event when internet access is restored.
Please keep in mind that Instabug SDK already caches all reports and will re-attempt to send them on next app launch until they're uploaded successfully.
Just wanted to post the updated answer.
The newer SDK has changed the name and now you can disable it by the following code:
Instabug.changeInvocationEvent(InstabugInvocationEvent.NONE)
Notice, if you want to disable it for entire application, just call this method in your Application class
I use GCM in my project.Where do I get an ID, so it is always available at all times? Here is my code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (!CloudMessaging.checkPlayServices(this)) {
return;
}
CloudMessaging.getInstance(this).setRegistrationListener(eventHandler);
}
"but if I turn aside and then expand Programmes at, then again will get ID." ->Possibly:
If I change my orientation, then again I get a new Id.
You can get your ID for GCM
if (m_gcm == null)
{
m_gcm = GoogleCloudMessaging.getInstance(m_context);
}
m_regid = m_gcm.register("Your project id from google api console");
Note : please do this network operation in background thread..
Use SharedPreferences to store your ID once you get a new one.
Steps required: (do this in your onCreate)
Check if you already have a valid GCM id in your SharedPreferences
If you already have one, use it.
Otherwise, request a new one and save it in your SharedPreferences.
Since Ice-Cream-Sandwich there is a developer-option called "force GPU-rendering". If enabled it refuses to Display some large Drawables. Therefore I want to find out, if this option is enabled, to inform the User that he has to switch it off, if he wants to see that drawable.
Find a View that you know shouldn't be accelerated, which should be any View if you add
android:hardwareAccelerated="false"
to your <application> in Android Manifest, then in your code, call
view.isHardwareAccelerated();
If it returns true, the option is set as on. This has been confirmed to work on my Galaxy Nexus.
With the help of Kai I found this Hardware Acceleration topic on android-developers. Unfortunately We wanna stay compatible to 2.1 so I add my solution for anyone who has a similar problem. So inside an Activity:
public View contentView
public void onCreate(Bundle savedInstanceState){
contentView = findViewById(R.id.someId);
//initialize Views ...
setContentView(contentView);
//use a handler as easiest method to post a Runnable Delayed.
//we cannot check hardware-acceleration directly as it will return reasonable results after attached to Window.
Handler handler = new Handler();
handler.postDelayed(HardwareAccelerationRunnable(), 500);
}
public class HardwareAccelerationRunnable implements Runnable{
public void run(){
//now lets check for HardwareAcceleration since it is only avaliable since ICS.
// 14 = ICS_VERSION_CODE
if (android.os.Build.VERSION.SDK_INT >= 14){
try{
//use reflection to get that Method
Method isHardwareAccelerated = contentView.getClass().getMethod("isHardwareAccelerated", null);
Object o = isHardwareAccelerated.invoke(contentView, null);
if (null != o && o instanceof Boolean && (Boolean)o){
//ok we're shure that HardwareAcceleration is on.
//Now Try to switch it off:
Method setLayerType = contentView.getClass().getMethod("setLayerType", int.class, android.graphics.Paint.class);
setLayerType.invoke(contentView, 1, null);
}
} catch(Exception e){
e.printStackTrace();
}
}
}
}
}
I don't think that you can turn it off by adding
android:hardwareAccelerated="false"
If you trace the code into Window.setWindowManager(), you can see the following
public void setWindowManager(...) {
...
mHardwareAccelerated = hardwareAccelerated
|| SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
...
}
Where,
hardwareAccelerated: comes from android:hardwareAccelerated
PROPERTY_HARDWARE_UI property is set by the "Force GPU rendering" option.
You can see that if user manually check the "Force GPU rendering" option, mHardwareAccelerated variable will be assigned with a TRUE value no matter what android:hardwareAccelerated is.