I want to protect my APK from reverse engineering, by showing Toast, or do something if package name changed, now if package changed the app will stop working.
if (getPackageName().compareTo("com.apk.example") != 0) {
String error = null;
error.getBytes();
}
You need to check both your package name and application id to make sure your app haven't been tampered with:
String yourPackageName = "com.apk.example"; // android package name
String packageName = getApplicationContext().getPackageName();
// can be different from your package name if you're using flavor
// in app.build.gradle,
String yourApplicationId = "com.apk.example";
if(packageName.equals(yourPackageName) && BuildConfig.APPLICATION_ID.equals(yourApplicationId)) {
// no problem here
} else {
// app is tampered, do something
}
Related
I am trying to export repeat grid data to excel. To do this, I have provided a button which runs "MyCustomActivity" activity via clicking. The button is placed above the grid in the same layout. It also worth pointing out that I am utulizing an article as a guide to configure. According to the guide my "MyCustomActivity" activity contains two steps:
Method: Property-Set, Method Parameters: Param.exportmode = "excel"
Method: Call pzRDExportWrapper. And I pass current parameters (There is only one from the 1st step).
But after I had got an issue I have changed the 2nd step by Call Rule-Obj-Report-Definition.pzRDExportWrapper
But as you have already understood the solution doesn't work. I have checked the log files and found interesting error:
2017-04-11 21:08:27,992 [ WebContainer : 4] [OpenPortal] [ ] [ MyFW:01.01.02] (ctionWrapper._baseclass.Action) ERROR as1|172.22.254.110 bar - Activity 'MyCustomActivity' failed to execute; Failed to find a 'RULE-OBJ-ACTIVITY' with the name 'PZRESOLVECOPYFILTERS' that applies to 'COM-FW-MyFW-Work'. There were 3 rules with this name in the rulebase, but none matched this request. The 3 rules named 'PZRESOLVECOPYFILTERS' defined in the rulebase are:
2017-04-11 21:08:42,807 [ WebContainer : 4] [TABTHREAD1] [ ] [ MyFW:01.01.02] (fileSetup.Code_Security.Action) ERROR as1|172.22.254.110 bar - External authentication failed:
If someone have any suggestions and share some, I will appreciate it.
Thank you.
I wanted to provide a functionality of exporting retrieved works to a CSV file. The functionality should has a feature to choose fields to retrieve, all results should be in Ukrainian and be able to use any SearchFilter Pages and Report Definition rules.
At a User Portal I have two sections: the first section contains text fields and a Search button, and a section with a Repeat Grid to display results. The textfields are used to filter results and they use a page Org-Div-Work-SearchFilter.
I made a custom parser to csv. I created two activities and wrote some Java code. I should mention that I took some code from the pzPDExportWrapper.
The activities are:
ExportToCSV - takes parameters from users, gets data, invokes the ConvertResultsToCSV;
ConvertResultsToCSV - converts retrieved data to a .CSV file.
Configurations of the ExportToCSV activity:
The Pages And Classes tab:
ReportDefinition is an object of a certain Report Definition.
SearchFilter is a Page with values inputted by user.
ReportDefinitionResults is a list of retrieved works to export.
ReportDefinitionResults.pxResults denotes a type of a certain work.
The Parameters tab:
FileName is a name of a generated file
ColumnsNames names of columns separated by comma. If the parameter is empty then CSVProperties is exported.
CSVProperties is a props to display in a spreadsheet separated by comma.
SearchPageName is a name of a page to filter results.
ReportDefinitionName is a RD's name used to retrieve results.
ReportDefinitionClass is a class of utilized report definition.
The Step tab:
Lets look through the steps:
1. Get an SearchFilte Page with a name from a Parameter with populated fields:
2. If SearchFilter is not Empty, call a Data Transform to convert SearchFilter's properties to Paramemer properties:
A fragment of the data Transform:
3. Gets an object of a Report Definition
4. Set parameters for the Report Definition
5. Invoke the Report Definition and save results to ReportDefinitionResults:
6. Invoke the ConvertResultsToCSV activity:
7. Delete the result page:
The overview of the ConvertResultsToCSV activity.
The Parameters tab if the ConvertResultsToCSV activity:
CSVProperties are the properties to retrieve and export.
ColumnsNames are names of columns to display.
PageListProperty a name of the property to be read in the primay page
FileName the name of generated file. Can be empty.
AppendTimeStampToFileName - if true, a time of the file generation.
CSVString a string of generated CSV to be saved to a file.
FileName a name of a file.
listSeperator is always a semicolon to separate fields.
Lets skim all the steps in the activity:
Get a localization from user settings (commented):
In theory it is able to support a localization in many languages.
Set always "uk" (Ukrainian) localization.
Get a separator according to localization. It is always a semicolon in Ukrainian, English and Russian. It is required to check in other languages.
The step contains Java code, which form a CSV string:
StringBuffer csvContent = new StringBuffer(); // a content of buffer
String pageListProp = tools.getParamValue("PageListProperty");
ClipboardProperty resultsProp = myStepPage.getProperty(pageListProp);
// fill the properties names list
java.util.List<String> propertiesNames = new java.util.LinkedList<String>(); // names of properties which values display in csv
String csvProps = tools.getParamValue("CSVProperties");
propertiesNames = java.util.Arrays.asList(csvProps.split(","));
// get user's colums names
java.util.List<String> columnsNames = new java.util.LinkedList<String>();
String CSVDisplayProps = tools.getParamValue("ColumnsNames");
if (!CSVDisplayProps.isEmpty()) {
columnsNames = java.util.Arrays.asList(CSVDisplayProps.split(","));
} else {
columnsNames.addAll(propertiesNames);
}
// add columns to csv file
Iterator columnsIter = columnsNames.iterator();
while (columnsIter.hasNext()) {
csvContent.append(columnsIter.next().toString());
if (columnsIter.hasNext()){
csvContent.append(listSeperator); // listSeperator - local variable
}
}
csvContent.append("\r");
for (int i = 1; i <= resultsProp.size(); i++) {
ClipboardPage propPage = resultsProp.getPageValue(i);
Iterator iterator = propertiesNames.iterator();
int propTypeIndex = 0;
while (iterator.hasNext()) {
ClipboardProperty clipProp = propPage.getIfPresent((iterator.next()).toString());
String propValue = "";
if(clipProp != null && !clipProp.isEmpty()) {
char propType = clipProp.getType();
propValue = clipProp.getStringValue();
if (propType == ImmutablePropertyInfo.TYPE_DATE) {
DateTimeUtils dtu = ThreadContainer.get().getDateTimeUtils();
long mills = dtu.parseDateString(propValue);
java.util.Date date = new Date(mills);
String sdate = dtu.formatDateTimeStamp(date);
propValue = dtu.formatDateTime(sdate, "dd.MM.yyyy", "", "");
}
else if (propType == ImmutablePropertyInfo.TYPE_DATETIME) {
DateTimeUtils dtu = ThreadContainer.get().getDateTimeUtils();
propValue = dtu.formatDateTime(propValue, "dd.MM.yyyy HH:mm", "", "");
}
else if ((propType == ImmutablePropertyInfo.TYPE_DECIMAL)) {
propValue = PRNumberFormat.format(localeCode,PRNumberFormat.DEFAULT_DECIMAL, false, null, new BigDecimal(propValue));
}
else if (propType == ImmutablePropertyInfo.TYPE_DOUBLE) {
propValue = PRNumberFormat.format(localeCode,PRNumberFormat.DEFAULT_DECIMAL, false, null, Double.parseDouble(propValue));
}
else if (propType == ImmutablePropertyInfo.TYPE_TEXT) {
propValue = clipProp.getLocalizedText();
}
else if (propType == ImmutablePropertyInfo.TYPE_INTEGER) {
Integer intPropValue = Integer.parseInt(propValue);
if (intPropValue < 0) {
propValue = new String();
}
}
}
if(propValue.contains(listSeperator)){
csvContent.append("\""+propValue+"\"");
} else {
csvContent.append(propValue);
}
if(iterator.hasNext()){
csvContent.append(listSeperator);
}
propTypeIndex++;
}
csvContent.append("\r");
}
CSVString = csvContent.toString();
5. This step forms and save a file in server's catalog tree
char sep = PRFile.separatorChar;
String exportPath= tools.getProperty("pxProcess.pxServiceExportPath").getStringValue();
DateTimeUtils dtu = ThreadContainer.get().getDateTimeUtils();
String fileNameParam = tools.getParamValue("FileName");
if(fileNameParam.equals("")){
fileNameParam = "RecordsToCSV";
}
//append a time stamp
Boolean appendTimeStamp = tools.getParamAsBoolean(ImmutablePropertyInfo.TYPE_TRUEFALSE,"AppendTimeStampToFileName");
FileName += fileNameParam;
if(appendTimeStamp) {
FileName += "_";
String currentDateTime = dtu.getCurrentTimeStamp();
currentDateTime = dtu.formatDateTime(currentDateTime, "HH-mm-ss_dd.MM.yyyy", "", "");
FileName += currentDateTime;
}
//append a file format
FileName += ".csv";
String strSQLfullPath = exportPath + sep + FileName;
PRFile f = new PRFile(strSQLfullPath);
PROutputStream stream = null;
PRWriter out = null;
try {
// Create file
stream = new PROutputStream(f);
out = new PRWriter(stream, "UTF-8");
// Bug with Excel reading a file starting with 'ID' as SYLK file. If CSV starts with ID, prepend an empty space.
if(CSVString.startsWith("ID")){
CSVString=" "+CSVString;
}
out.write(CSVString);
} catch (Exception e) {
oLog.error("Error writing csv file: " + e.getMessage());
} finally {
try {
// Close the output stream
out.close();
} catch (Exception e) {
oLog.error("Error of closing a file stream: " + e.getMessage());
}
}
The last step calls #baseclass.DownloadFile to download the file:
Finally, we can post a button on some section or somewhere else and set up an Actions tab like this:
It also works fine inside "Refresh Section" action.
A possible result could be
Thanks for reading.
So I'm making a simple code redemption plugin for a Minecraft server. What's weird is when I type /redeem (the valid code), nothing happens, although it's supposed to... The valid code is the a code entered into the plugins configuration by the user.
Here's my code...
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args)
{
//Assigns the commands chosen in config to strings
String commandChosen1 = this.getConfig().getString("Command for code 1");
String commandChosen2 = this.getConfig().getString("Command for code 2");
String commandChosen3 = this.getConfig().getString("Command for code 3");
//Assigns the codes to strings
String validCode1 = this.getConfig().getString("Valid Code 1");
String validCode2 = this.getConfig().getString("Valid Code 2");
String validCode3 = this.getConfig().getString("Valid Code 3");
//If the redeem command is sent from a player
if(cmd.getName().equalsIgnoreCase("redeem") && sender instanceof Player)
{
//Casts the sender to a new player.
Player player = (Player) sender;
//Creates object hasUSed to store whether or not the player has already redeemed a code
Object hasUsed = this.getConfig().get(player.getName());
//Gives an error message of the arguments don't equal 1.
if(args.length != 1)
{
player.sendMessage(ChatColor.DARK_RED + "Please enter a valid promo code. Find them on our twitter!");
}
if(args.length == 1)
{
//If the player hasn't used the code yet and the arguments given are equal to a code then give them the reward...
if(args[0] == validCode1 && hasUsed == null)
{
this.getConfig().set(player.getName(), 1);
player.sendMessage(ChatColor.GREEN + "Promo code successfully entered!");
if(commandChosen1 == "xp")
{
Bukkit.dispatchCommand(player, commandChosen1 + getConfig().getString("XP Given") + "L" + " " + player.getName());
}
}
}
return true;
}
return false;
}
The problem occurs on "if (args[0] == validCode1 && hasUsed == null)". The code that's supposed to happen if both those things check out, doesn't happen and I have no clue why.
Make sure to use equals() when comparing Strings. Using commandChosen1 == "xp" compares string references not values; use commandChosen1.equals("xp") or if you prefer "xp".equals(commandChosen1).
Also,
While it is possible to use a this.getConfig().getString()with a key value that contains spaces, it can make configuration files hard to read and cluttered. Whenever I design plugins I'll design my config.yml as such
VoteGUI:
message: 'hello'
and then run a this.getConfig().getString("VoteGUI.message");
For yours I'd suggest something like this
Promo-Codes:
validCode1: 'insert code here'
validCode2: 'insert code here'
validCode3: 'insert code here'
and then put this in your onCommand method:
String validCode1 = this.getConfig().getString("Promo-Codes.validCode1");
String validCode2 = this.getConfig().getString("Promo-Codes.validCode2");
String validCode3 = this.getConfig().getString("Promo-Codes.validCode3");
If this does not resolve the issue, copy and paste the exception being thrown from the console and I may be of further assistance
This question already has answers here:
How do I programmatically determine operating system in Java?
(22 answers)
Closed 3 years ago.
I have an app that runs on several mobile devices running either Fedora or Android. To consolidate my codebase and distribution I would like to determine which OS I am on. I tried System.getProperty("os.name"), but that just returns "Linux". Is there something unique to Android in the System properties?
Thanks
There are several properties you could check. Candidates are:
java.vendor.url --> http://www.android.com
java.vm.name --> Dalvik (I don't know, which one Fedora is using...)
java.vm.vendor --> The Android Project
java.vendor --> The Android Project
Maybe you want to check by yourself?
Properties p = System.getProperties();
Enumeration keys = p.keys();
while(keys.hasMoreElements()) {
String key = (String) keys.nextElement();
String value = (String) p.get(key);
System.out.println(key + " >>>> " + value);
}
I do not know Android but if you do not find some unique system property you can sometimes identify the system if some specific class exists there. So you can do the following:
boolean isAndroid() {
try {
Class.forName("the class name");
return true;
} catch(ClassNotFoundException e) {
return false;
}
}
Here is some code that I wrote using the information from this page, in case you want to copy-paste:
private static YLogger ylogger;
public static YLogger getLogger() {
if (ylogger == null){
// need to find a new logger. Let's check if we have Android running
if (System.getProperty("java.vm.name").equalsIgnoreCase("Dalvik")){
ylogger = new AndroidLogger();
ylogger.d("YLoggerFactory", "Instantiating Android-based logger");
} else {
// fallback option, system logger.
ylogger = new SystemLogger();
ylogger.d("YLoggerFactory", "Instantiating System-based logger");
}
}
return ylogger;
}
The list of defined system properties is here: https://developer.android.com/reference/java/lang/System#getProperties()
I'm using
boolean android = "The Android Project".equals(System.getProperty("java.specification.vendor"));
I use this in my processing sketch to determine in which mode I'm running i.e. where I'm running it.
enum Mode {
java, android
}
Mode getMode() {
return System.getProperty("java.runtime.name").equals("Android Runtime") ? Mode.android : Mode.java;
}
if (getMode() == Mode.java){
// do something
// eg: do something that android can't handle
} else {
// do android stuff
// eg: scale the sketch by 2 to improve visibility
}
How to get Android device name? I am using HTC desire. When I connected it via HTC Sync the software is displaying the Name 'HTC Smith' . I would like to fetch this name via code.
How is this possible in Android?
In order to get Android device name you have to add only a single line of code:
android.os.Build.MODEL;
Found here: getting-android-device-name
You can see answers at here Get Android Phone Model Programmatically
public String getDeviceName() {
String manufacturer = Build.MANUFACTURER;
String model = Build.MODEL;
if (model.startsWith(manufacturer)) {
return capitalize(model);
} else {
return capitalize(manufacturer) + " " + model;
}
}
private String capitalize(String s) {
if (s == null || s.length() == 0) {
return "";
}
char first = s.charAt(0);
if (Character.isUpperCase(first)) {
return s;
} else {
return Character.toUpperCase(first) + s.substring(1);
}
}
I solved this by getting the Bluetooth name, but not from the BluetoothAdapter (that needs Bluetooth permission).
Here's the code:
Settings.Secure.getString(getContentResolver(), "bluetooth_name");
No extra permissions needed.
On many popular devices the market name of the device is not available. For example, on the Samsung Galaxy S6 the value of Build.MODEL could be "SM-G920F", "SM-G920I", or "SM-G920W8".
I created a small library that gets the market (consumer friendly) name of a device. It gets the correct name for over 10,000 devices and is constantly updated. If you wish to use my library click the link below:
AndroidDeviceNames Library on Github
If you do not want to use the library above, then this is the best solution for getting a consumer friendly device name:
/** Returns the consumer friendly device name */
public static String getDeviceName() {
String manufacturer = Build.MANUFACTURER;
String model = Build.MODEL;
if (model.startsWith(manufacturer)) {
return capitalize(model);
}
return capitalize(manufacturer) + " " + model;
}
private static String capitalize(String str) {
if (TextUtils.isEmpty(str)) {
return str;
}
char[] arr = str.toCharArray();
boolean capitalizeNext = true;
String phrase = "";
for (char c : arr) {
if (capitalizeNext && Character.isLetter(c)) {
phrase += Character.toUpperCase(c);
capitalizeNext = false;
continue;
} else if (Character.isWhitespace(c)) {
capitalizeNext = true;
}
phrase += c;
}
return phrase;
}
Example from my Verizon HTC One M8:
// using method from above
System.out.println(getDeviceName());
// Using https://github.com/jaredrummler/AndroidDeviceNames
System.out.println(DeviceName.getDeviceName());
Result:
HTC6525LVW
HTC One (M8)
Try it. You can get Device Name through Bluetooth.
Hope it will help you
public String getPhoneName() {
BluetoothAdapter myDevice = BluetoothAdapter.getDefaultAdapter();
String deviceName = myDevice.getName();
return deviceName;
}
You can use:
From android doc:
MANUFACTURER:
String MANUFACTURER
The manufacturer of the product/hardware.
MODEL:
String MODEL
The end-user-visible name for the end product.
DEVICE:
String DEVICE
The name of the industrial design.
As a example:
String deviceName = android.os.Build.MANUFACTURER + " " + android.os.Build.MODEL;
//to add to textview
TextView textView = (TextView) findViewById(R.id.text_view);
textView.setText(deviceName);
Furthermore, their is lot of attribute in Build class that you can use, like:
os.android.Build.BOARD
os.android.Build.BRAND
os.android.Build.BOOTLOADER
os.android.Build.DISPLAY
os.android.Build.CPU_ABI
os.android.Build.PRODUCT
os.android.Build.HARDWARE
os.android.Build.ID
Also their is other ways you can get device name without using Build class(through the bluetooth).
Following works for me.
String deviceName = Settings.Global.getString(.getContentResolver(), Settings.Global.DEVICE_NAME);
I don't think so its duplicate answer. The above ppl are talking about Setting Secure, for me setting secure is giving null, if i use setting global it works. Thanks anyways.
universal way to get user defined DeviceName working for almost all devices and not requiring any permissions
String userDeviceName = Settings.Global.getString(getContentResolver(), Settings.Global.DEVICE_NAME);
if(userDeviceName == null)
userDeviceName = Settings.Secure.getString(getContentResolver(), "bluetooth_name");
Try this code. You get android device name.
public static String getDeviceName() {
String manufacturer = Build.MANUFACTURER;
String model = Build.MODEL;
if (model.startsWith(manufacturer)) {
return model;
}
return manufacturer + " " + model;
}
#hbhakhra's answer will do.
If you're interested in detailed explanation, it is useful to look into Android Compatibility Definition Document. (3.2.2 Build Parameters)
You will find:
DEVICE - A value chosen by the device implementer containing the
development name or code name identifying the configuration of the
hardware features and industrial design of the device. The value of
this field MUST be encodable as 7-bit ASCII and match the regular
expression “^[a-zA-Z0-9_-]+$”.
MODEL - A value chosen by the device implementer containing the name
of the device as known to the end user. This SHOULD be the same name
under which the device is marketed and sold to end users. There are no
requirements on the specific format of this field, except that it MUST
NOT be null or the empty string ("").
MANUFACTURER - The trade name of the Original Equipment Manufacturer
(OEM) of the product. There are no requirements on the specific format
of this field, except that it MUST NOT be null or the empty string
("").
UPDATE
You could retrieve the device from buildprop easitly.
static String GetDeviceName() {
Process p;
String propvalue = "";
try {
p = new ProcessBuilder("/system/bin/getprop", "ro.semc.product.name").redirectErrorStream(true).start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
propvalue = line;
}
p.destroy();
} catch (IOException e) {
e.printStackTrace();
}
return propvalue;
}
But keep in mind, this doesn't work on some devices.
Simply use
BluetoothAdapter.getDefaultAdapter().getName()
static String getDeviceName() {
try {
Class systemPropertiesClass = Class.forName("android.os.SystemProperties");
Method getMethod = systemPropertiesClass.getMethod("get", String.class);
Object object = new Object();
Object obj = getMethod.invoke(object, "ro.product.device");
return (obj == null ? "" : (String) obj);
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
you can get 'idol3' by this way.
Tried These libraries but nothing worked according to my expectation and was giving absolutely wrong names.
So i created this library myself using the same data.
Here is the link
AndroidPhoneNamesFinder
To use this library just add this for implementation
implementation 'com.github.aishik212:AndroidPhoneNamesFinder:v1.0.2'
Then use the following kotlin code
DeviceNameFinder.getPhoneValues(this, object : DeviceDetailsListener
{
override fun details(doQuery: DeviceDetailsModel?)
{
super.details(doQuery)
Log.d(TAG, "details: "+doQuery?.calculatedName)
}
})
These are the values you will get from DeviceDetailsModel
val brand: String? #This is the brandName of the Device
val commonName: String?, #This is the most common Name of the Device
val codeName: String?, #This is the codeName of the Device
val modelName: String?, #This is the another uncommon Name of the Device
val calculatedName: String?, #This is the special name that this library tries to create from the above data.
Example of Android Emulator -
brand=Google
commonName=Google Android Emulator
codeName=generic_x86_arm
modelName=sdk_gphone_x86
calculatedName=Google Android Emulator
Within the GNU/Linux environment of Android, e.g., via Termux UNIX shell on a non-root device, it's available through the /system/bin/getprop command, whereas the meaning of each value is explained in Build.java within Android (also at googlesource):
% /system/bin/getprop | fgrep ro.product | tail -3
[ro.product.manufacturer]: [Google]
[ro.product.model]: [Pixel 2 XL]
[ro.product.name]: [taimen]
% /system/bin/getprop ro.product.model
Pixel 2 XL
% /system/bin/getprop ro.product.model | tr ' ' _
Pixel_2_XL
For example, it can be set as the pane_title for the status-right within tmux like so:
tmux select-pane -T "$(getprop ro.product.model)"
Gets an Android system property, or lists them all
adb shell getprop >prop_list.txt
Find your device name in prop_list.txt to get the prop name
e.g. my device name is ro.oppo.market.name
Get oppo.market Operator
adb shell getprop ro.oppo.market.name
My case on windows as follows
D:\winusr\adbl
λ *adb shell getprop ro.oppo.market.name*
OPPO R17
I have a Serial-to-USB device with a similarly named device driver in the Windows device manager. The devices do not always grab the same COM port on system boot, so my program needs to identify it on start up.
I've tried using RXTX to enumerate the COM ports on the system, but this didn't work because CommPortIdentifier.getName() simply returns the COM name (eg. COM1, COM2, etc.) I need to acquire either the driver manufacturer name, or the driver name as it appears in the device manager, and associate it with the COM name.
Can this easily be done in Java? (I'd be interested in any 3rd party Java libraries that support this.) Otherwise, how I could begin to accomplish this via the win32 API?
I achieved what I wanted by using the WinRegistry class provided by David in this SO question to obtain the FriendlyName from registry key associated with my USB device. I then parse out the COM number from the friendly name.
Some things to consider:
USB devices are located at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\ in the registry (tested on WinXP, Win7.)
I required the device VID + PID to identify the correct device key (eg. VID_xxxx&PID_xxxx.) Since VID and PID are device specific, this key should be reliable across multiple systems.
The VID_xxxx&PID_xxxx key contains another sub-key with device values. I had some trouble enumerating the sub-keys with WinRegistry, so I hard-coded the sub-key name as a quick hack during development. A much safer solution would search sub-keys to find the correct name.
The device keys exist in the registry regardless of whether the device is currently connected. This code makes the assumption that Windows will update FriendlyName if the device is reconnected to a different COM port. I haven't verified this, but things looked good during use-testing.
Example
String keyPath = "SYSTEM\\CurrentControlSet\\Enum\\USB\\Vid_067b&Pid_2303\\";
String device1 = "5&75451e6&0&1";
System.out.println("First COM device: " + getComNumber(keyPath + device1));
Code
import java.util.regex.Pattern;
import java.util.regex.Matcher;
// Given a registry key, attempts to get the 'FriendlyName' value
// Returns null on failure.
//
public static String getFriendlyName(String registryKey) {
if (registryKey == null || registryKey.isEmpty()) {
throw new IllegalArgumentException("'registryKey' null or empty");
}
try {
int hkey = WinRegistry.HKEY_LOCAL_MACHINE;
return WinRegistry.readString(hkey, registryKey, "FriendlyName");
} catch (Exception ex) { // catch-all:
// readString() throws IllegalArg, IllegalAccess, InvocationTarget
System.err.println(ex.getMessage());
return null;
}
}
// Given a registry key, attempts to parse out the integer after
// substring "COM" in the 'FriendlyName' value; returns -1 on failure.
//
public static int getComNumber(String registryKey) {
String friendlyName = getFriendlyName(registryKey);
if (friendlyName != null && friendlyName.indexOf("COM") >= 0) {
String substr = friendlyName.substring(friendlyName.indexOf("COM"));
Matcher matchInt = Pattern.compile("\\d+").matcher(substr);
if (matchInt.find()) {
return Integer.parseInt(matchInt.group());
}
}
return -1;
}
#robjb Your code does not allow for more than one device to be connected. How will the user know the device name? I added to your code thus to return a list of com ports:
ArrayList<String> subKeys = WinRegistry.readStringSubKeys(WinRegistry.HKEY_LOCAL_MACHINE, keyPath);
ArrayList<Integer> comPorts = new ArrayList<Integer>();
for (String subKey : subKeys) {
String friendlyName = getFriendlyName(keyPath + subKey);
if (friendlyName != null && friendlyName.contains("MyDriverName") && friendlyName.contains("COM")) {
int beginIndex = friendlyName.indexOf("COM") + 3 /*length of 'COM'*/;
int endIndex = friendlyName.indexOf(")");
comPorts.add(Integer.parseInt(friendlyName.substring(beginIndex, endIndex)));
}
}
Update: I don't think these are solutions. Why? This information is statically stored in the registry - even when the device is not connected.
Great example, using JNA, here.
The author (Geir Arne Ruud) has released it under Public Domain License.
My example code
public static String getFriendlyName(GoGPSModel model, String name)
{
if(model.getSystem().getOSType() != OSType.Windows32
&& model.getSystem().getOSType() != OSType.Windows64) {
return name;
}
for (DeviceInformation devInfo : infoObjects) {
System.out.println(devInfo.toString());
String friendlyName = devInfo.getFriendlyName();
if(friendlyName != null && !friendlyName.equals("") && friendlyName.contains(name)) {
return devInfo.getManufacturer() + ": " + friendlyName;
}
}
return name;
}