Android permission at runtime with external class - android-permissions

I apologize for my English.
I try for a few hours to create a class that allows a request for permission to run time. I think the basic system makes the code unreadable if you have permission requested in several different activity.
So I created the following class
public class PermissionsHelper {
public interface PermissionHelperListener{
void accepted();
void rejected();
}
private static PermissionsHelper mInstance;
private static AppCompatActivity mContext;
public static ArrayList<PermissionHelperListener> permissionHelperListeners;
public static PermissionsHelper getInstance(AppCompatActivity context){
mContext = context;
if(mInstance == null){
mInstance = new PermissionsHelper();
}
return mInstance;
}
public void requestPermissions(String perm, PermissionHelperListener permissionHelperListener){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (mContext.checkSelfPermission(perm) != PackageManager.PERMISSION_GRANTED) {
int index = permissionHelperListeners.size();
permissionHelperListeners.add(permissionHelperListener);
mContext.requestPermissions(new String[]{perm}, index);
}
}
}
public void requestPermissions (String[] perms, PermissionHelperListener permissionHelperListener){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int index = permissionHelperListeners.size();
permissionHelperListeners.add(permissionHelperListener);
mContext.requestPermissions(perms, index);
}
}
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
permissionHelperListeners.get(requestCode).accepted();
} else {
permissionHelperListeners.get(requestCode).rejected();
}
permissionHelperListeners.remove(requestCode);
}
}
I call my class in onRequestPermissionsResultlike this
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
PermissionsHelper.getInstance(this).onRequestPermissionsResult(requestCode, permissions, grantResults);
}
everything is right until now. but when I use requestPermissions in my activity there is always the warning to check permission. I used #SuppressWarnings("ALL") and it work but I do not really like it. is there an other way to remove this warning or ask permissions with a callback like this ?
Thanks a lot

Updated:
I've found an awesome solution for this.
Just rename the method that you are using to check the permissions in your helper class to 'checkSelfPermission'. I'm guessing Lint scans the code for these words to decide when to show that dreaded red underline.
Older Answer:
Another way would be to use a try and catch block with a security exception.
try {
//code with the warning goes here
} catch (SecurityException e){
//do nothing here or ask for permission and recall this method
//again if the user grants the permission
}

Related

RecyclerView.Adapter notifyDataSetChanged not working with AsyncTask Callback

I am sure it's just a simple fault, but I'm not able to solve it.
My RecyclerView.Adapter loads its data with help of an AsyncTask (LoadAllPersonsFromDb) out of a SQLite DB. The response is handled by a callback interface (ILoadPersonFromDb.onFindAll).
Here is the code of the Adapter:
public class ListViewAdapter extends RecyclerView.Adapter<ListViewViewholder> implements LoadAllPersonsFromDb.ILoadPersonFromDb {
private int layout;
private List<Person> persons;
private Context context;
private AdapterDataSetListener adapterDataSetListener;
public ListViewAdapter(int layout, Context context,
AdapterDataSetListener adapterDataSetListener) {
this.layout = layout;
persons = new ArrayList<>();
this.context = context;
this.adapterDataSetListener = adapterDataSetListener;
new LoadAllPersonsFromDb(context, this).execute();
}
#Override
public ListViewViewholder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(layout, parent, false);
return new ListViewViewholder(view, context);
}
#Override
public void onBindViewHolder(ListViewViewholder holder, int position) {
holder.assignData(persons.get(position));
}
#Override
public int getItemCount() {
return persons.size();
}
#Override
public void onFindAll(List<Person> persons) {
Log.d("LISTVIEW", "Counted: " + persons.size() + " elements in db");
if (this.persons != null) {
this.persons.clear();
this.persons.addAll(persons);
} else {
this.persons = persons;
}
adapterDataSetListener.onChangeDataSet();
//notifyDataSetChanged();
}
public interface AdapterDataSetListener {
void onChangeDataSet();
}
}
As you can see, I tried more than one way to get it running. The simple notifyDataSetChanged did not do anything, so I made another interface which is used to delegate the ui information to the relating fragment. Following code documents this interface which is implemented in the relating fragment:
#Override
public void onChangeDataSet() {
Log.d("Callback", "called");
listViewAdapter.notifyDataSetChanged();
/*
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
listViewAdapter.notifyDataSetChanged();
}
});
*/
}
Here I also tried to put it on the MainUiThread but nothing works. I'm just not able to see where my problem is. Hopefully any of you guys can give me a hint.
The logging works, which is the prove for the working callbacks.
Thank you in advance.
PS: If you need any more code, just tell me and I will provide it.
instead of using the interface-llistener pattern, try this
#Override
public void onFindAll(List<Person> persons) {
Log.d("LISTVIEW", "Counted: " + persons.size() + " elements in db");
if (this.persons != null) {
this.persons.clear();
this.persons.addAll(persons);
} else {
this.persons = persons;
}
refereshAdapter(persons);
}
public void refereshAdapter(List<Person> persons){
listViewAdapter.clear();
listViewAdapter.addAll(persons);
listViewAdapter.notifyDataSetChanged();
}
To tell the background, I used RecyclerView in Version 23.1.1 because the latest 23.2.0 had some weird behaviour in holding a huge space for each card.
//Update: the problem with the space between cards, was because of a failure of myself in the layout file (match_parent instead of wrap_content). -_-
The upshot was using the latest version again and everything worked just fine. I have no idea why, but at the moment I am just happy, that I can go on. This little problem wasted enough time.
Maybe somebody has a similar situation and can use this insight.
Thx anyway #yUdoDis.

E4 Preference Initializer won´t get called

I´m trying to migrate my e3-rcp-app to a e4-rcp-app.
Therefore I need to define my default Preferences. (Not the Pref.Pages)
And by doing and trying so, I just can´t get my Initializer called. Here Is my initializer-class:
public class MyPreferenceInitializer extends AbstractPreferenceInitializer {
public MyPreferenceInitializer (){}
#Override
public void initializeDefaultPreferences() {
Preferences defaults = DefaultScope.INSTANCE.getNode(InspectIT.ID);
// Set defaults using things like:
defaults.put("DUMMY", "DUMMYCONTENT");
try {
defaults.flush();
} catch (BackingStoreException e) {
e.printStackTrace();
}
//And this other approach to make sure that one of them works
IPreferenceStore store = InspectIT.getDefault().getPreferenceStore();
store.setDefault("DUMMY", "DUMMYCONTENT");
try {
((Preferences) store).flush();
} catch (BackingStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Dummy impl
default Preferences....,
}
}
I also got an Activator class with the following structure: (Just posting the relevant methods(?))
public class Activator implements BundleActivator {
private static BundleContext context;
static BundleContext getContext() {
return context;
}
private static Activator plugin;
private volatile ScopedPreferenceStore preferenceStore;
public void start(BundleContext context) throws Exception {
plugin = this;
Activator.context = context;
locateRuntimeDir();
logListener = new LogListener();
Platform.addLogListener(logListener);
//access to my initializor
String text = getPreferenceStore().getDefaultString("DUMMY");
String text2 = getPreferenceStore().getString("DUMMY");
}
public void stop(BundleContext context) throws Exception {
Activator.context = null;
plugin = null;
}
public static <E> E getService(Class<E> clazz) {
ServiceReference<E> reference = context.getServiceReference(clazz);
if (null != reference) {
return context.getService(reference);
}
throw new RuntimeException("Requested service of the class " + clazz.getName() + " is not registered in the bundle.");
}
public ScopedPreferenceStore getPreferenceStore() {
if (null == preferenceStore) {
synchronized (this) {
if (null == preferenceStore) {
preferenceStore = new ScopedPreferenceStore(ConfigurationScope.INSTANCE, ID);
}
}
}
return preferenceStore;
}
}
The ScopedPreferenceStore I´m using is the one available at: https://github.com/opcoach/e4Preferences/tree/master/com.opcoach.e4.preferences
As well, I declared the plugin.xml Extension like this (I do need this, right?)
...
<extension
point="org.eclipse.core.runtime.preferences">
<initializer class="MyApplication.rcp.preferences.MyPreferenceInitializer ">
</initializer>
</extension>
...
I´m using Eclipse 4.5.1 on a win7 x64
I googled a lot and found a lot of Threads concerning this, but I just can´t find my mistake =/.
Anyone got a suggestion for why my default preferences initializer won´t get called?
Thanks in advance
You must still use the org.eclipse.core.runtime.preferences extension point to define the preferences initializer.
<extension
point="org.eclipse.core.runtime.preferences">
<initializer
class="package.MyPreferenceInitializer">
</initializer>
</extension>
In the initializer use:
#Override
public void initializeDefaultPreferences()
{
Preferences defaults = DefaultScope.INSTANCE.getNode(Activator.ID);
// Set defaults using things like:
defaults.putInt("pref id", 0);
}
Finally I found a solution for this issue.
Accidentally got over this problem again and the mistake was in the Activator. I wrongly set the ID onto a wrong name. I reset it to my projects name and now it is working!
public ScopedPreferenceStore getPreferenceStore() {
if (null == preferenceStore) {
synchronized (this) {
if (null == preferenceStore)
preferenceStore = new ScopedPreferenceStore(ConfigurationScope.INSTANCE, ID);
}
}
return preferenceStore;
}
ID = Project-Name

how to handle runtime permission auth in android M

I want to know the best practise to ask user for permission check and the code to run if user declines that particular permission access.
This example set states for CONTACTS permission
private static final int PERMISSIONS_REQUEST_READ_CONTACTS = 1;
private static String[] PERMISSIONS_CONTACT = {Manifest.permission.READ_CONTACTS}
if (checkSelfPermission(PERMISSIONS_CONTACT)) {
Log.i(TAG,
"Contact permissions have already been granted. Displaying contact details.");
} else {
Log.i(TAG, "Contact permissions has NOT been granted. Requesting permission.");
requestPermissions(PERMISSIONS_CONTACT, PERMISSIONS_REQUEST_READ_CONTACTS);
}
…
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case PERMISSIONS_REQUEST_READ_CONTACTS: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! do the
// calendar task you need to do.
Log.d(TAG, "permission granted");
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Log.d(TAG, "permission denied");
}
return;
}
}
}
You can follow the link
http://www.applicoinc.com/blog/android-m-permissions-review/
Dexter is an Android library that simplifies the process of requesting permissions at runtime.
Usage of Dexter
Some hint:
Always check for permission before calling operations on Google Play Services because they require permission but the management is in charge of you;
Don't ask for granted permissions: when you call request permissions with multiple permissions the system doesn't care if one or two permissions are already granted, the dialog is shown for all! So keep track only of permissions really needed. It could be strange for user grant already granted permissions;
Always check if it's needed to show a reason to the user using the method shouldShowRequestPermissionRationale() it could be not really obvious why you are asking a permission;
Send a notification to the user if you are checking for permission in background, in a service for example and allow it to grant the permission going with a tap in the app details system activity directly.
Take a look here - there's a flowchart that explains the whole process quite well.
Bottom line is that according to Android's documentation, you should always check and ask for permission if you don't have it (Android will automatically return DENIED in the callback if the user said to never ask again) and you should display a short message if the user has already declined you once in the past but hasn't marked the never ask again option.
For Example Camera Run time permission :
This Code you have to put in to camera button click
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
givePerMissons();
} else {
openCamera();
}
public void givePerMissons() {
if ((Utils.checkPermission(MainActivity.this, Manifest.permission.CAMERA)) {
openCamera();
} else {
Utils.givePermisson(MainActivity.this, Manifest.permission.CAMERA, Utils.PERMISSOIN);
if (!Utils.permissionsList.isEmpty()) {
requestPermissions(Utils.permissionsList.toArray(new String[Utils.permissionsList.size()]), Utils.PERMISSOIN_CODE);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case Utils.PERMISSOIN_CODE: {
if ((Utils.checkPermission(MainActivity.this, Manifest.permission.CAMERA)) {
openCamera();
} else {
Toast.makeText(getApplicationContext(),"Write Your message",Toast.LENGTH_LONG).show();
}
}
}
}
This Code you have to put in your utils Class:
public static final List<String> permissionsList = new ArrayList<String>();
public static void givePermisson(Context context, String permisson, String permissonType) {
int per = context.checkSelfPermission(permisson);
if (per != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(permisson);
} else if (per != PackageManager.PERMISSION_DENIED) {
}
}
public static boolean checkPermission(Context context, String permission) {
try {
PackageManager pm = context.getPackageManager();
if (pm.checkPermission(permission, context.getPackageName()) == PackageManager.PERMISSION_GRANTED) {
return true;
} } catch (Exception e) {
e.printStackTrace();
}
return false;
}
if ( ActivityCompat.shouldShowRequestPermissionRationale (this, Manifest.permission.CAMERA) || ActivityCompat.shouldShowRequestPermissionRationale (this,
Manifest.permission.RECORD_AUDIO) ) {
Toast.makeText (this,
R.string.permissions_needed,
Toast.LENGTH_LONG).show ();
} else {
ActivityCompat.requestPermissions (
this,
new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO},
CAMERA_MIC_PERMISSION_REQUEST_CODE);
}

How to move a window between desktops using powershell/.net on windows 10 [duplicate]

I love that Windows 10 now has support for virtual desktops built in, but I have some features that I'd like to add/modify (e.g., force a window to appear on all desktops, launch the task view with a hotkey, have per-monitor desktops, etc.)
I have searched for applications and developer references to help me customize my desktops, but I have had no luck.
Where should I start? I am looking for Windows API functions (ideally, that are callable from a C# application) that will give me programmatic access to manipulate virtual desktops and the windows therein.
The Windows SDK Support Team Blog posted a C# demo to switch Desktops via IVirtualDesktopManager:
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("a5cd92ff-29be-454c-8d04-d82879fb3f1b")]
[System.Security.SuppressUnmanagedCodeSecurity]
public interface IVirtualDesktopManager
{
[PreserveSig]
int IsWindowOnCurrentVirtualDesktop(
[In] IntPtr TopLevelWindow,
[Out] out int OnCurrentDesktop
);
[PreserveSig]
int GetWindowDesktopId(
[In] IntPtr TopLevelWindow,
[Out] out Guid CurrentDesktop
);
[PreserveSig]
int MoveWindowToDesktop(
[In] IntPtr TopLevelWindow,
[MarshalAs(UnmanagedType.LPStruct)]
[In]Guid CurrentDesktop
);
}
[ComImport, Guid("aa509086-5ca9-4c25-8f95-589d3c07b48a")]
public class CVirtualDesktopManager
{
}
public class VirtualDesktopManager
{
public VirtualDesktopManager()
{
cmanager = new CVirtualDesktopManager();
manager = (IVirtualDesktopManager)cmanager;
}
~VirtualDesktopManager()
{
manager = null;
cmanager = null;
}
private CVirtualDesktopManager cmanager = null;
private IVirtualDesktopManager manager;
public bool IsWindowOnCurrentVirtualDesktop(IntPtr TopLevelWindow)
{
int result;
int hr;
if ((hr = manager.IsWindowOnCurrentVirtualDesktop(TopLevelWindow, out result)) != 0)
{
Marshal.ThrowExceptionForHR(hr);
}
return result != 0;
}
public Guid GetWindowDesktopId(IntPtr TopLevelWindow)
{
Guid result;
int hr;
if ((hr = manager.GetWindowDesktopId(TopLevelWindow, out result)) != 0)
{
Marshal.ThrowExceptionForHR(hr);
}
return result;
}
public void MoveWindowToDesktop(IntPtr TopLevelWindow, Guid CurrentDesktop)
{
int hr;
if ((hr = manager.MoveWindowToDesktop(TopLevelWindow, CurrentDesktop)) != 0)
{
Marshal.ThrowExceptionForHR(hr);
}
}
}
it includes the API to detect on which desktop the Window is shown and it can switch and move a Windows the a Desktop.
Programmatic access to the virtual desktop feature is very limited, as Microsoft has only exposed the IVirtualDesktopManager COM interface. It does provide two key functions:
IVirtualDesktopManager::GetWindowDesktopId allows you to retrieve the ID of a virtual desktop, based on a window that is already assigned to that desktop.
IVirtualDesktopManager::MoveWindowToDesktop allows you to move a window to a specific virtual desktop.
Unfortunately, this is not nearly enough to accomplish anything useful. I've written some C# code based on the reverse-engineering work done by NickoTin. I can't read much of the Russian in his blog post, but his C++ code was pretty accurate.
I do need to emphasize that this code is not something you want to commit to in a product. Microsoft always feels free to change undocumented APIs whenever they feel like it. And there is a runtime risk as well: this code does not necessarily interact well when the user is tinkering with the virtual desktops. Always keep in mind that a virtual desktop can appear and disappear at any time, completely out of sync with your code.
To use the code, create a new C# class library project. I'll first post ComInterop.cs, it contains the COM interface declarations that match NickoTin's C++ declarations:
using System;
using System.Runtime.InteropServices;
namespace Windows10Interop {
internal static class Guids {
public static readonly Guid CLSID_ImmersiveShell =
new Guid(0xC2F03A33, 0x21F5, 0x47FA, 0xB4, 0xBB, 0x15, 0x63, 0x62, 0xA2, 0xF2, 0x39);
public static readonly Guid CLSID_VirtualDesktopManagerInternal =
new Guid(0xC5E0CDCA, 0x7B6E, 0x41B2, 0x9F, 0xC4, 0xD9, 0x39, 0x75, 0xCC, 0x46, 0x7B);
public static readonly Guid CLSID_VirtualDesktopManager =
new Guid("AA509086-5CA9-4C25-8F95-589D3C07B48A");
public static readonly Guid IID_IVirtualDesktopManagerInternal =
new Guid("AF8DA486-95BB-4460-B3B7-6E7A6B2962B5");
public static readonly Guid IID_IVirtualDesktop =
new Guid("FF72FFDD-BE7E-43FC-9C03-AD81681E88E4");
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("FF72FFDD-BE7E-43FC-9C03-AD81681E88E4")]
internal interface IVirtualDesktop {
void notimpl1(); // void IsViewVisible(IApplicationView view, out int visible);
Guid GetId();
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("AF8DA486-95BB-4460-B3B7-6E7A6B2962B5")]
internal interface IVirtualDesktopManagerInternal {
int GetCount();
void notimpl1(); // void MoveViewToDesktop(IApplicationView view, IVirtualDesktop desktop);
void notimpl2(); // void CanViewMoveDesktops(IApplicationView view, out int itcan);
IVirtualDesktop GetCurrentDesktop();
void GetDesktops(out IObjectArray desktops);
[PreserveSig]
int GetAdjacentDesktop(IVirtualDesktop from, int direction, out IVirtualDesktop desktop);
void SwitchDesktop(IVirtualDesktop desktop);
IVirtualDesktop CreateDesktop();
void RemoveDesktop(IVirtualDesktop desktop, IVirtualDesktop fallback);
IVirtualDesktop FindDesktop(ref Guid desktopid);
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("a5cd92ff-29be-454c-8d04-d82879fb3f1b")]
internal interface IVirtualDesktopManager {
int IsWindowOnCurrentVirtualDesktop(IntPtr topLevelWindow);
Guid GetWindowDesktopId(IntPtr topLevelWindow);
void MoveWindowToDesktop(IntPtr topLevelWindow, ref Guid desktopId);
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("92CA9DCD-5622-4bba-A805-5E9F541BD8C9")]
internal interface IObjectArray {
void GetCount(out int count);
void GetAt(int index, ref Guid iid, [MarshalAs(UnmanagedType.Interface)]out object obj);
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("6D5140C1-7436-11CE-8034-00AA006009FA")]
internal interface IServiceProvider10 {
[return: MarshalAs(UnmanagedType.IUnknown)]
object QueryService(ref Guid service, ref Guid riid);
}
}
Next is Desktop.cs. It contains the friendly C# classes that you can use in your code:
using System;
using System.Runtime.InteropServices;
namespace Windows10Interop
{
public class Desktop {
public static int Count {
// Returns the number of desktops
get { return DesktopManager.Manager.GetCount(); }
}
public static Desktop Current {
// Returns current desktop
get { return new Desktop(DesktopManager.Manager.GetCurrentDesktop()); }
}
public static Desktop FromIndex(int index) {
// Create desktop object from index 0..Count-1
return new Desktop(DesktopManager.GetDesktop(index));
}
public static Desktop FromWindow(IntPtr hWnd) {
// Creates desktop object on which window <hWnd> is displayed
Guid id = DesktopManager.WManager.GetWindowDesktopId(hWnd);
return new Desktop(DesktopManager.Manager.FindDesktop(ref id));
}
public static Desktop Create() {
// Create a new desktop
return new Desktop(DesktopManager.Manager.CreateDesktop());
}
public void Remove(Desktop fallback = null) {
// Destroy desktop and switch to <fallback>
var back = fallback == null ? DesktopManager.GetDesktop(0) : fallback.itf;
DesktopManager.Manager.RemoveDesktop(itf, back);
}
public bool IsVisible {
// Returns <true> if this desktop is the current displayed one
get { return object.ReferenceEquals(itf, DesktopManager.Manager.GetCurrentDesktop()); }
}
public void MakeVisible() {
// Make this desktop visible
DesktopManager.Manager.SwitchDesktop(itf);
}
public Desktop Left {
// Returns desktop at the left of this one, null if none
get {
IVirtualDesktop desktop;
int hr = DesktopManager.Manager.GetAdjacentDesktop(itf, 3, out desktop);
if (hr == 0) return new Desktop(desktop);
else return null;
}
}
public Desktop Right {
// Returns desktop at the right of this one, null if none
get {
IVirtualDesktop desktop;
int hr = DesktopManager.Manager.GetAdjacentDesktop(itf, 4, out desktop);
if (hr == 0) return new Desktop(desktop);
else return null;
}
}
public void MoveWindow(IntPtr handle) {
// Move window <handle> to this desktop
DesktopManager.WManager.MoveWindowToDesktop(handle, itf.GetId());
}
public bool HasWindow(IntPtr handle) {
// Returns true if window <handle> is on this desktop
return itf.GetId() == DesktopManager.WManager.GetWindowDesktopId(handle);
}
public override int GetHashCode() {
return itf.GetHashCode();
}
public override bool Equals(object obj) {
var desk = obj as Desktop;
return desk != null && object.ReferenceEquals(this.itf, desk.itf);
}
private IVirtualDesktop itf;
private Desktop(IVirtualDesktop itf) { this.itf = itf; }
}
internal static class DesktopManager {
static DesktopManager() {
var shell = (IServiceProvider10)Activator.CreateInstance(Type.GetTypeFromCLSID(Guids.CLSID_ImmersiveShell));
Manager = (IVirtualDesktopManagerInternal)shell.QueryService(Guids.CLSID_VirtualDesktopManagerInternal, Guids.IID_IVirtualDesktopManagerInternal);
WManager = (IVirtualDesktopManager)Activator.CreateInstance(Type.GetTypeFromCLSID(Guids.CLSID_VirtualDesktopManager));
}
internal static IVirtualDesktop GetDesktop(int index) {
int count = Manager.GetCount();
if (index < 0 || index >= count) throw new ArgumentOutOfRangeException("index");
IObjectArray desktops;
Manager.GetDesktops(out desktops);
object objdesk;
desktops.GetAt(index, Guids.IID_IVirtualDesktop, out objdesk);
Marshal.ReleaseComObject(desktops);
return (IVirtualDesktop)objdesk;
}
internal static IVirtualDesktopManagerInternal Manager;
internal static IVirtualDesktopManager WManager;
}
}
And finally a little test WinForms project that I used to test the code. Just drop 4 buttons on a form and name them buttonLeft/Right/Create/Destroy:
using Windows10Interop;
using System.Diagnostics;
...
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void buttonRight_Click(object sender, EventArgs e) {
var curr = Desktop.FromWindow(this.Handle);
Debug.Assert(curr.Equals(Desktop.Current));
var right = curr.Right;
if (right == null) right = Desktop.FromIndex(0);
if (right != null) {
right.MoveWindow(this.Handle);
right.MakeVisible();
this.BringToFront();
Debug.Assert(right.IsVisible);
}
}
private void buttonLeft_Click(object sender, EventArgs e) {
var curr = Desktop.FromWindow(this.Handle);
Debug.Assert(curr.Equals(Desktop.Current));
var left = curr.Left;
if (left == null) left = Desktop.FromIndex(Desktop.Count - 1);
if (left != null) {
left.MoveWindow(this.Handle);
left.MakeVisible();
this.BringToFront();
Debug.Assert(left.IsVisible);
}
}
private void buttonCreate_Click(object sender, EventArgs e) {
var desk = Desktop.Create();
desk.MoveWindow(this.Handle);
desk.MakeVisible();
Debug.Assert(desk.IsVisible);
Debug.Assert(desk.Equals(Desktop.Current));
}
private void buttonDestroy_Click(object sender, EventArgs e) {
var curr = Desktop.FromWindow(this.Handle);
var next = curr.Left;
if (next == null) next = curr.Right;
if (next != null && next != curr) {
next.MoveWindow(this.Handle);
curr.Remove(next);
Debug.Assert(next.IsVisible);
}
}
}
The only real quirk I noticed while testing this is that moving a window from one desktop to another can move it to the bottom of the Z-order when you first switch the desktop, then move the window. No such problem if you do it the other way around.
There is this guy that made a application to map keyboard shorcut to move a window between virtual desktop.
https://github.com/Grabacr07/SylphyHorn
(I use it every day )
He has a blog where he explain what he did
http://grabacr.net/archives/5701 ( you can use google translate it is in japanese)
He in fact used the same api mantionned in the Alberto Tostado response.
http://www.cyberforum.ru/blogs/105416/blog3671.html
and the api can be found on his github https://github.com/Grabacr07/VirtualDesktop
The api is really simple to use BUT it seems impossible to move a window from another process.
public static bool MoveToDesktop(IntPtr hWnd, VirtualDesktop virtualDesktop)
{
ThrowIfNotSupported();
int processId;
NativeMethods.GetWindowThreadProcessId(hWnd, out processId);
if (Process.GetCurrentProcess().Id == processId) // THAT LINE
{
var guid = virtualDesktop.Id;
VirtualDesktop.ComManager.MoveWindowToDesktop(hWnd, ref guid);
return true;
}
return false;
}
To workaround this problem they made another implementation that they use alongside the one in the russian blog
if (VirtualDesktopHelper.MoveToDesktop(hWnd, right) //<- the one in the russian blog
|| this.helper.MoveWindowToDesktop(hWnd, right.Id)) <- the second implementation
The second implementation can be found here: https://github.com/tmyt/VDMHelper
This one can move a window from another process to another desktop. BUT it is buggy right now. For exemple when i try to move some window like google chrome it crash.
So this is the result of my research. I m rigth now trying to make a StickyWindow feature with these api.
I fear that all about "Virtual desktops" in Windows 10 is undocumented, but in a Russian page I've seen documented the interfaces. I don't speak Russian but seems that they have used reversed engineering. Anyway, the code is very clear (Thanks to them!).
Keep an eye here:
http://www.cyberforum.ru/blogs/105416/blog3671.html
I've been trying to see if the old API's CreateDesktop, OpenDesktop, etc... is linked to the new Virtual-Desktops, but no way...
The interfaces work with the final production release of Windows 10 (2015-05-08), but you shouldn't use them in a real wide distributed application until Microsoft documents them. Too much risk.
Regards.

My Android App is crashed when I register SensorManager.registerListener

Below is my code. I am having a problem when I call SensorManager.registerListener, my app will crash. Can someone tell me what's going on?
I just follw the web guide to setup SensorManger, Sensor(Accelerometer) and then register the action lintener to detect the montion of accelerometer.
I used API 21 to develop this app.
public class MainActivity extends ActionBarActivity implements SensorEventListener{
private TextView tip;
private SensorManager mSensorManager;
private Sensor mSensor;
private float axisX = 0;
private float axisY = 0 ;
private float axisZ = 0;
#Override
protected void onResume() {
super.onResume();
setUpAcceleratorSensor();
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUpAcceleratorSensor();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void setUpAcceleratorSensor(){
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
if((mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)) != null);
else
Toast.makeText(this, "No Sensor Device Exist", Toast.LENGTH_LONG).show();
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
Sensor mySensor = event.sensor;
if (mySensor.getType() == Sensor.TYPE_ACCELEROMETER) {
if(event.values[0] != 0 || event.values[1] != 0 || event.values[2] != 0){
axisX = event.values[0];
axisY = event.values[1];
axisZ = event.values[2];
tip.setText("Detect your montion");
}
}
else
Toast.makeText(this, "Cannot Get Sensor Device", Toast.LENGTH_LONG).show();
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
}
Thanks.
First that I always check when something like this goes wrong, is to check that you have all the correct permissions in the Android Manifest; however, I don't believe that there are any permissions associated with using the position sensors. I would check on this first. That is what comes to mind first, after you post logcat, we will be able to give a more detailed answer.
Try getting the sensor this way
mSensor = mSensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0); instead in your setUpAccelerometer() method.