In Android 10 getDeviceID value is null - google-contacts-api

In android 10, couldn't get device id using permission "READ_PHONE_STATE". I got an error while trying to get deviceID "The user 10296 does not meet the requirements to access device identifiers". I referred the developer site, but couldn't get proper solution. Also "READ_PRIVILEGE_PHONE_STATE" permission also not accessible.
Please prefer any solution to get deviceID from Android 10 mobile's and help me to resolve this issue.
Thanks in advance

getDeviceId() has been deprecated since API level 26.
"READ_PRIVILEGE_PHONE_STATE" is only accessible by The best practices suggest that you should "Avoid using hardware identifiers." for unique identifiers. You can use an instance id from firebase e.g FirebaseInstanceId.getInstance().getId();.
Or you can generate a custom globally-unique ID (GUID) to uniquely identify the app instance e.g
String uniqueID = UUID.randomUUID().toString();
or the least recommended way
String deviceId = android.provider.Settings.Secure.getString(
context.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);

You can also use this one, it's getting token from Firebase:-
String deviceId = FirebaseInstanceId.getInstance().getToken();
and this way is also working:-
String deviceId = UUID.randomUUID().toString();

As per the latest release in Android 10, Restriction on non-resettable device identifiers.
pps must have the READ_PRIVILEGED_PHONE_STATE privileged permission in order to access the device's non-resettable identifiers, which include both IMEI and serial number.
Check this for Privacy Changes in Android 10
To avoid such scenarios use UUID.randomUUID().toString() that represents an immutable universally unique identifier (UUID). A UUID represents a 128-bit value.

This is the definitive solution !
String myuniqueID;
int myversion = Integer.valueOf(android.os.Build.VERSION.SDK);
if (myversion < 23) {
WifiManager manager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
WifiInfo info = manager.getConnectionInfo();
myuniqueID= info.getMacAddress();
if (myuniqueID== null) {
TelephonyManager mngr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
return;
}
myuniqueID= mngr.getDeviceId();
}
}
else if (myversion > 23 && myversion < 29) {
TelephonyManager mngr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
return;
}
myuniqueID= mngr.getDeviceId();
}
else
{
String androidId = Settings.Secure.getString(this.getContentResolver(), Settings.Secure.ANDROID_ID);
myuniqueID= androidId;
}

Related

Kernel32.dll - DeviceIOControl returns false while trying to get String descriptor in Win 10

I am currently using the DeviceIOControl API from kernel32.dll to get the String Descriptors of the list of connected USB devices.
public static String GetStringDescriptor(IntPtr deviceHandle, Int32 ConnectionIndex, Byte DescriptorIndex, UInt16 LanguageID)
{
USB_DESCRIPTOR_REQUEST Buffer = new USB_DESCRIPTOR_REQUEST();
Buffer.ConnectionIndex = ConnectionIndex;
Buffer.SetupPacket.wValue = (UInt16)((USB_STRING_DESCRIPTOR_TYPE << 8) | DescriptorIndex);
Buffer.SetupPacket.wIndex = LanguageID;
Buffer.SetupPacket.wLength = MAXIMUM_USB_STRING_LENGTH;
Int32 nBytesReturned;
Boolean Status = DeviceIoControl(deviceHandle,
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
ref Buffer,
Marshal.SizeOf(Buffer),
ref Buffer,
Marshal.SizeOf(Buffer),
out nBytesReturned,
IntPtr.Zero);
if (Status)
return Buffer.Data.bString;
else
return null;
}
We use this function to get the descriptor details such as Language ID, Serial number, Manufacturer and Product String. Only while requesting the Serial Number, the Status returned is TRUE and we get the expected values. But the status returns false for Language id, manufacturer and Product string.
I checked the error status returned by the DeviceIoControl using:
int error = Marshal.GetLastWin32Error();
It returns 31 as the error code which means that the Device is not working properly/ the driver for the device is not properly installed.
I tried all the obvious solutions like reinstalling the driver for the device and restarting the PC etc., but none seems to work. I am sure there are no issues in the device or the code because it works flawlessly in windows 7 PCs. Also, since I am able to get the serial number, I think the device handle is also proper.
I am not able to proceed with any further debugging. Is there some update to the DeviceIoControl function in Windows 10? Or is the way to get the languageID, manufacturer and Product String changed in Windows 10?
Most probably the device you are trying to get string descriptors from is in low power state. Check its current power state first, and if it differs from "PowerDeviceD0" - string descriptors may not be obtained (depending on device, actually, and actual power state level D1, D2, D3). This could be the cause of error code 31 from DeviceIOControl().
Try to wake the device first or get some stored strings with SetupAPI.

Working with date time in web api

I have created a WEB APIusing MySQL database. The table includes the data about the meter's serial numbers it's signal strength values and the date time on which the signal strength has comes. For now i am successful in getting data by sending the meter's serial number.
Now I am also sending the date time parameter to it also. But it's not working for me. Below is what i have done.
public HttpResponseMessage GetByMsn(string msn, DateTime dt)
{
try
{
return Request.CreateResponse(HttpStatusCode.Found, medEntitites.tj_xhqd.Where(m=> m.msn == msn).Where(a=> a.date_time < dt ));
}
catch (Exception ex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
}
}
The WebApiConfig file includes
config.Routes.MapHttpRoute(
name: "GetByMsn",
routeTemplate: "api/{controller}/{action}/{msn}/{dt}",
defaults: null,
constraints: new { msn = #"^[0-9]+$" , dt = #"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$" }
);
After that I am passing the URL like http://localhost:14909/api/meters/GetByMsn/000029000033/2017-10-06T07:52:27
The error I am getting is A potentially dangerous Request.Path value was detected from the client (:).
For this I have also searched for the solutions but couldn't find out the correct one. Also I have replaced : in date time but still it's not working for me
Update 1
While passing only date2017-10-06 it works for me but when I append it with time it doesn't works
For a quick check I checked this question but still i am unable to solve the solution.
I must be missing something that I don't know
Any help would be highly appreciated.
After a lot of searching I finally found a solution.
I have changed the predefined disallowed/invalid characters in my Web.config. Under , added the following: <httpRuntime requestPathInvalidCharacters="<,>,%,&,*,\,?" />. I've removed the : from the standard list of invalid characters.
For more information see this solution

Is there a way to inquire if a class contains an instance variable with some known name?

When intercepting an error from MySql, it's not known beforehand what will be the contents of the error-class passed to me. So I code:
.catchError((firstError) {
sqlMessage = firstError.message;
try {
sqlError = firstError.osError;
} catch (noInstanceError){
sqlError = firstError.sqlState;
}
});
In this specific case I'd like to know whether e contains instance variable osError or sqlState, as any of them contains the specific errorcode. And more in general (to improve my knowledge) would it be possible write something like if (firstError.instanceExists(osError)) ..., and how?
This should do what you want:
import 'dart:mirrors';
...
// info about the class declaration
reflect(firstError).type.declarations.containsKey(#osError);
// info about the current instance
var m = reflect(firstError).type.instanceMembers[#osError];
var hasOsError = m != null && m.isGetter;
Günter's answer correctly shows how to use mirrors, however for your particular use case I'd recommend using an "is" check instead of mirrors. I don't know the mysql API specifically but it could look something like this:
.catchError((error) {
sqlMessage = error.message;
if (error is MySqlException) {
sqlError = error.sqlState;
} else if (error is OSError) {
sqlError = error.errorCode;
}
})
Perhaps ask James Ots, the author of sqljocky for advice.

Dapper And System.Data.OleDb DbType.Date throwing 'OleDbException : Data type mismatch in criteria expression'

Not sure if I should raise an issue regarding this, so thought I would ask if anybody knew a simple workaround for this first. I am getting an error when I try to use Dapper with OleDbConnection when used in combination with MS Access 2003 (Jet.4.0) (not my choice of database!)
When running the test code below I get an exception 'OleDbException : Data type mismatch in criteria expression'
var count = 0;
using (var conn = new OleDbConnection(connString)) {
conn.Open();
var qry = conn.Query<TestTable>("select * from testtable where CreatedOn <= #CreatedOn;", new { CreatedOn = DateTime.Now });
count = qry.Count();
}
I believe from experience in the past with OleDb dates, is that when setting the DbType to Date, it then changes internally the value for OleDbType property to OleDbTimeStamp instead of OleDbType.Date. I understand this is not because of Dapper, but what 'could' be considered a strange way of linking internally in the OleDbParameter class
When dealing with this either using other ORMs, raw ADO or my own factory objects, I would clean up the command object just prior to running the command and change the OleDbType to Date.
This is not possible with Dapper as far as I can see as the command object appears to be internal. Unfortunately I have not had time to learn the dynamic generation stuff, so I could be missing something simple or I might suggest a fix and contribute rather than simply raise an issue.
Any thoughts?
Lee
It's an old thread but I had the same problem: Access doesn't like DateTime with milliseconds, so you have to add and extension method like this :
public static DateTime Floor(this DateTime date, TimeSpan span)
{
long ticks = date.Ticks / span.Ticks;
return new DateTime(ticks * span.Ticks, date.Kind);
}
And use it when passing parameters:
var qry = conn.Query<TestTable>("select * from testtable where CreatedOn <= #CreatedOn;", new { CreatedOn = DateTime.Now.Floor(TimeSpan.FromSeconds(1)) });
Unfortunately, with current Dapper version (1.42), we cannot add custom TypeHandler for base types (see #206).
If you can modify Dapper (use the cs file and not the DLL) merge this pull request and then you do not have to use Floor on each parameters :
public class DateTimeTypeHandler : SqlMapper.TypeHandler<DateTime>
{
public override DateTime Parse(object value)
{
if (value == null || value is DBNull)
{
return default(DateTime);
}
return (DateTime)value;
}
public override void SetValue(IDbDataParameter parameter, DateTime value)
{
parameter.DbType = DbType.DateTime;
parameter.Value = value.Floor(TimeSpan.FromSeconds(1));
}
}
SqlMapper.AddTypeHandler<DateTime>(new DateTimeTypeHandler());

exception in Linq to sql

my query is :
var ReadAndUnreadMessages =
(from m in MDB.Messages
orderby m.Date descending
where m.ID_Receive == (Guid)USER.ProviderUserKey && m.Delete_Admin == false
select new AllMessages()
{
id = (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).ID_Message,
parent = (Guid)(LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).ID_Message_Parent,
sender = (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).ID_Sender,
receiver = (Guid)USER.ProviderUserKey,
subject = (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Subject.Subject1.ToString() == "Other" ?
(LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Other_Subject
:
(LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Subject.Subject1.ToString(),
body = (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Body.Length > 26 ?
(LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Body.Substring(0, 25) + "..."
:
(LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Body,
date = (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).Date.ToShortDateString(),
read =(LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).IsRead,
finished = (LoadMessageChildren(m.ID_Message)[LoadMessageChildren(m.ID_Message).Count - 1] as Message).IsFinished,
count = MessageClass.LoadAll(m.ID_Message).Count
}).ToList();
and exception is :
The argument 'value' was the wrong type. Expected 'Message'. Actual 'System.Object'.
what does meaning it?
LoadMessageChildren :
public static ArrayList LoadMessageChildren(Guid Parent)
{
ArrayList arr = new ArrayList();
Guid id = Parent;
while (id != Guid.Empty)
{
arr.Add(LoadMessage(id));
try
{
id = (Guid)MDB.Messages.Single(a => a.ID_Message_Parent == id).ID_Message;
}
catch
{
id = Guid.Empty;
}
}
return arr;
}
LoadMessage :
public static Message LoadMessage(Guid id)
{
var mess = from m in MDB.Messages
where m.ID_Message == id
select m;
return mess.Single();
}
The code is unreadable, and as a bad case of code repetition (and multiple executions of LoadMessageChildren).
For starters, consider the following:
from m in MDB.Messages
orderby m.Date descending
where m.ID_Receive == (Guid)USER.ProviderUserKey && m.Delete_Admin == false
let children = LoadMessageChildren(m.ID_Message)
let lastChildMessage = children.Last()
select new AllMessages()
{
id = lastChildMessage.ID_Message,
...
}
This may solve your problem, as it is might be caused by using the [] indexer.
Aside from that, it is not clear the posted code is causing the exception.
The only thing I see you using LoadChildMessages() for in the end is to get the child message count... Unless I am wrong I would think you could write it as a join. You doing a lot of queries with in queries that don't seem necessary and are probably causing multiple hits to the database. My question to that would be why isn't there a relationship in your dmbl/sql database so that LinqToSql knows to create a property as a List<Message> ChildMessages
But here is my take:
var query = from message in MDB.Messges
join childmessage in MDB.Messages.Where(child => child.ID_Message_Parent == message.ID_Message) into childMessages
from childMessage in childMessages.DefaultIfEmpty() // This creates a
// left outer join so you get parent messages that don't have any children
where message.ID_Receive == (Guid)USER.ProviderUserKey && message.Delete_Admin == false
select new AllMessages()
{
id = message.ID_Message,
parent = message.ID_Message_Parent,
sender = message.ID_Sender,
receiver = (Guid)USER.ProviderUserKey,
subject = message.Subject.Subject1.ToString() == "Other" ?
message.Other_Subject
:
message.Subject.Subject1.ToString(),
body = message.Body.Length > 26 ?
message.Body.Substring(0, 25) + "..."
:
message.Body,
date = message.Date.ToShortDateString(),
read =message.IsRead,
finished = message.IsFinished,
count = childMessage.Count() // This might have to be this
//count = childMessage == null ? 0 : childMessage.Count()
};
var ReadAndUnreadMessages = query.ToList();
But it's hard to say because I can't run the code... Please respond and let me know if this works.
Note: May I suggest using a class that links to your DataContext.Log property that writes the generated TSQL code to the debugger window. Here is an article on writing your own. It has really help me know when I am making unnecessary calls to the database.
The error is most likely caused by the use of the ArrayList.
The problem is that LINQ was designed to work with generic collections that implement the System.Collections.Generic.IEnumerable<T> interface. The ArrayList is a nongeneric collection that internally stores everything as an Object. So when you retrieve something from the ArrayList you need to cast it to a Message.
Looking at your error message it looks like somewhere a Message object is expected, but the instance in your ArrayList (an Object) is not casted to a Message object when that reference occurs. Also, the ArrayList does not implement the IEnumerable<T> interface which might get you into trouble in certain situations also.
How to fix it?
I suggest changing the implementation of your LoadMessageChildren to use a generic list (List<Message>):
public static List<Message> LoadMessageChildren(Guid Parent)
{
List<Message> arr = new List<Message>();
Guid id = Parent;
while (id != Guid.Empty)
{
arr.Add(LoadMessage(id));
try
{
id = (Guid)MDB.Messages.Single(a => a.ID_Message_Parent == id).ID_Message;
}
catch
{
id = Guid.Empty;
}
}
return arr;
}
You will have to make also change the code that interacts with the generic list in terms of retrieving/referencing items. But that is just syntax. Since equivalent methods for dealist with lists and items exist.
There are also advantages in terms of performance and compile-time validation for switching from ArrayList to List<T>. The ArrayList is basically an inheritance from version 1.0 of the .Net Framework when there was no support for generics and it just get kept in the framework probably for compatibility reasons.
There are greater benefits for using generics.
UPDATED ANSWER:
The "Method 'System.Collections.Generic.List'1[Message] LoadMessageChildren(System.Guid)' has no supported translation to SQL" exception that you are getting is caused by the fact that your LoadMessageChildren method is not mapping to a stored procedure or a user defined function in your database.
You cannot have any regular C# method call inside your LINQ to SQL queries. The LINQ to SQL object model interprets a method found inside your query as either a stored procedure or a user defined function. So the engine is basically looking for a method called LoadMessageChildren that maps to a stored procedure or a user defined function in your database. Because there are no mappings, it tells you that no supported translation to SQL was found. The LINQ to SQL object model link shows you how to use method attributes to map a method that executes a stored procedure.
You have a few choices now:
create stored procedures of your regular C# method calls
rewrite your LINQ query to use joins to select child messages