/**
* Calls {#code GET API_SALES_ORDER_SRV/A_SalesOrder} through
* {#link FluentHelperRead} to get the SalesOrder events expanded to sales
* order items and filtered by {#code keys} list
*
* #param keys
* the list of sales orders IDs to be fetched
* #return the list of sales orders or an empty list if {#code keys} is empty
*
* #throws ODataException
* in case the request was not successful
* #throws IllegalArgumentException
* in case {#code keys} is null
*
* #see //ProcessSalesOrderService#getAllSalesOrder()
* #see <a href=
* "https://api.sap.com/shell/discover/contentpackage/SAPS4HANACloud/api/API_SALES_ORDER_SRV?resource=A_SalesOrder&operation=get_A_SalesOrder">SAP
* API Business Hub</a> for details of
* {#code GET API_SALES_ORDER_SRV/A_SalesOrder} endpoint
*/
public List<SalesOrderHeader> getByKeys(#NonNull Collection<String> keys) throws IllegalArgumentException, ODataException {
if (keys.size() == 0) {
return Collections.emptyList();
}
// create OData $filter with all keys
final ExpressionFluentHelper<SalesOrderHeader> filter = keys.stream()
.map(key -> SalesOrderHeader.SALES_ORDER.eq(key))
.reduce(ExpressionFluentHelper::or)
.get();
try {
HttpDestinationProperties destinationprop = null;
return salesOrderService.getAllSalesOrder()
.select(SalesOrderHeader.ALL_FIELDS, SalesOrderHeader.TO_ITEM)
.filter(filter)
.execute(destinationprop );
} catch (com.sap.cloud.sdk.odatav2.connectivity.ODataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I found the above sample code but since I am new to SAP and my system is an OnPrem version deployed on AWS. I am not sure how to pass the HttpDestinationProperties destinationprop
Further that method seems to be deprecated.
I am looking for some sample code to call the Sales order Odata Service using the code I generated using the instructions provided.
I generated the code using a maven plugin. https://sap.github.io/cloud-sdk/docs/java/features/odata/generate-typed-odata-v2-and-v4-client-for-java I am using the odata V2 Plugin
Usually you would use the SAP BTP Cloud Foundry Destination Service and Connectivity Service. Make sure to also have a Cloud Connector connected to your sub-account, it will act as reverse-proxy to the On-Premise system. You bind the destination service (e.g. plan lite) as well as the connectivity service (e.g. plan lite) to your application.
Once the prerequisites are met, you can use the SAP Cloud SDK code to resolve destinations:
// General API usage:
Destination destination = DestinationAccessor.getDestination("my-destination");
// Cast to HTTP destination:
HttpDestination httpDestination = destination.asHttp();
// Apply dedicated ERP logic for SAP S/4HANA
HttpDestination erpHttpDestination = httpDestination.decorate(DefaultErpHttpDestination::new);
(Of course you can boil it down to a one-liner.)
The OData call itself can be called like the following without try-catch:
return salesOrderService.getAllSalesOrder()
.select(SalesOrderHeader.ALL_FIELDS, SalesOrderHeader.TO_ITEM)
.filter(filter)
.executeRequest( erpHttpDestination );
That's it!
PS.: If you want to define your destination in static code, that would be possible with the DefaultErpHttpDestination.builder("http://your-proxy-host:44300") API. However this is obviously not best-practice.
Related
Our application involves an external device that mounts as a USB mass storage device. I need to be able to check the integrity of that USB mass storage device from a Java application, running on Windows.
Currently I execute "chkdsk", which works fine unless the user's computer isn't configured for English. (Because I need to examine the chkdsk output to determine the state of the drive.) And, surprise, surprise, not every computer in the world is configured for English!
There is a Win32 class called "Win32_Volume" with a method called "Chkdsk" that is just what I'm looking for.
I need to call it from Java, and JNA seems the way to go.
How can I use COM to call a method from a Win32 WMI class?
You can send an FSCTL_IS_VOLUME_DIRTY message using DeviceIoControl.
Here is and example of calling DeviceIoControl.
Or you can use WMI, both the the Win32_Volume and the Win32_LogicalDisk class expose a DirtyBitSet property. However WMI is really inteded for scripting languages and is not preferred because of it's incredible performance overhead.
The Win32_Volume documentation with the Chkdsk method you cite indicates it is a legacy API, but has not yet been deprecated so you could use it.
The current Storage Management API equivalent is MSFT_Volume. It has a Diagnose method that looks to perform similar functionality.
To execute a method on a WMI object via COM you need to obtain a pointer to a WbemServices object. It has an ExecMethod method you can invoke that does what you want for WMI classes. The code to retrieve this object is in JNA's WbemcliUtil class as a return type from the connectServer() method.
You will also need the full path to the Class Object; this is available by querying WMI for the __PATH, similarly to how you'd query any other field. That same WbemcliUtil class has a WmiQuery class you can instantiate to execute the query, collecting that path from the WmiResult. See the JNA test classes for examples on using these.
Finally, you can execute the WMI method. The code below will accomplish it for String properties, e.g., the MSFT_StorageDiagnoseResult object you'd get from MSFT_Volume's Diagnose method. You'd have to treat other return types differently.
/**
* Convenience method for executing WMI methods without any input parameters
*
* #param svc
* The WbemServices object
* #param clsObj
* The full path to the class object to execute (result of WMI
* "__PATH" query)
* #param method
* The name of the method to execute
* #param properties
* One or more properties returned as a result of the query
* #return An array of the properties returned from the method
*/
private static String[] execMethod(WbemServices svc, String clsObj, String method, String... properties) {
List<String> result = new ArrayList<>();
PointerByReference ppOutParams = new PointerByReference();
HRESULT hres = svc.ExecMethod(new BSTR(clsObj), new BSTR(method), new NativeLong(0L), null, null, ppOutParams,
null);
if (COMUtils.FAILED(hres)) {
return new String[0];
}
WbemClassObject obj = new WbemClassObject(ppOutParams.getValue());
VARIANT.ByReference vtProp = new VARIANT.ByReference();
for (String prop : properties) {
hres = obj.Get(new BSTR(prop), new NativeLong(0L), vtProp, null, null);
if (!COMUtils.FAILED(hres)) {
result.add(vtProp.getValue() == null ? "" : vtProp.stringValue());
}
}
obj.Release();
return result.toArray(new String[result.size()]);
}
A more complete example of querying a COM object, where I extracted the above code, is in this utility class which queries the GetOwner() and GetOwnerSid() methods on the Win32_Process object. It's legacy code from before I contributed the WbemCli class to JNA, so you'll have to adapt some of it, but it should be a good starting point.
Given that AIDL contain interface definitions, it is important to incorporate them into our javadoc.
However, Android Studio completely refuses to see Javadoc comments added either to aidl files or those to be found in the java files generated from them.
This is what I have in my .aidl test file:
/**
* Displays a Toast Message containing the specified String.
* To be used for testing purpose only.
*
* #param message the Message to be displayed
* #return whether or not the Message could be shown
*/
boolean testMessage(String message);
and this is in the generated .java file:
/**
* Displays a Toast Message containing the specified String.
* To be used for testing purpose only.
*
* #param message the Message to be displayed
* #return whether or not the Message could be shown
*/
#Override public boolean testMessage(java.lang.String message) throws android.os.RemoteException
{
return false;
}
I can generate JavaDoc for the implementation file (e.g. AidlImpl.java in case of IAidl.aidl), but that would yield wrong references in the JavaDoc as the end user would have to use IAidl and not AidlImpl.
How's that supposed to work?
#edit: I ended up writing a wrapper class for the library which can contain javadoc comments the usual way.
Not exactly the most elegant solution, but reasonably straightforward.
Thanks for your attention!
I use Google Maps API and need to get details of the place using lat and lon.
I've tried to get via Geocoder, but Class "Address" has no
parameters PLACE_ID
Geocoder gcd = new Geocoder(getApplicationContext(), Locale.getDefault());
List<Address> addresses = null;
try {
addresses = gcd.getFromLocation(52.2641, 76.9597, 1);
} catch (IOException e) {
e.printStackTrace();
}
if (addresses.size() > 0) {
Toast.makeText(this, addresses.get(0).getPlaceID(), Toast.LENGTH_SHORT).show();
}
else {
// do your stuff
}
To get a place ID from coordinate you should execute a reverse geocoding lookup using a REST API.
The native Android API geocoder doesn't support getting place ID in getFromLocation() results. Unfortunately, Google Maps Android SDK doesn't provide built-in Geocoder neither. The feature request exists for a long time, but it looks like it doesn't have high priority:
https://issuetracker.google.com/issues/35823852
So, to obtain a place ID you are stick to the REST API. There is a Java client library for Google Maps API Web Services that you can find on github:
https://github.com/googlemaps/google-maps-services-java
You can use this library to call Geocoding API from your Java code.
GeoApiContext context = new GeoApiContext.Builder()
.apiKey("AIza...")
.build();
GeocodingResult[] results = GeocodingApi.newRequest(context)
.latlng(new LatLng(52.2641, 76.9597)).await();
System.out.println(results[0].placeId);
Note that API key for web services must be different from an API key that you use in Google Maps Android SDK, because web services don't support Android app restriction.
Also take into account this important note from the library documentation
The Java Client for Google Maps Services is designed for use in server applications. This library is not intended for use inside of an Android app, due to the potential for loss of API keys.
If you are building a mobile application, you will need to introduce a proxy server to act as intermediary between your mobile application and the Google Maps API Web Services. The Java Client for Google Maps Services would make an excellent choice as the basis for such a proxy server.
I hope this helps!
you can get place Id on the bases of the marker. something like this:
mGoogleMap.setOnPoiClickListener(new GoogleMap.OnPoiClickListener() {
#Override
public void onPoiClick(PointOfInterest pointOfInterest)
{
addOrSaveMarkerToMap(pointOfInterest.latLng.latitude, pointOfInterest.latLng.longitude, pointOfInterest.name, "", pointOfInterest.placeId, true, true);
//Toast.makeText(GoogleMapsActivity.this,""+pointOfInterest.name+" (lat: "+pointOfInterest.latLng.latitude+", long: "+pointOfInterest.latLng.longitude+") " +" is added in your favorite list",Toast.LENGTH_LONG).show();
}
});
If you want to read more about what is point of interest is please take a look at this documentation link.
https://developers.google.com/maps/documentation/android-sdk/poi
Best way is to use google places API. It will give you the whole information about a specific place.
If you want to use google places API then follow this link:
How to get place or placeid by latLng in android using google places api?
FYI
Geocoder did't provide getPlaceID().
Supply a placeId to find the address for a given place ID. The place
ID is a unique identifier that can be used with other Google APIs
The GeocoderRequest object literal contains the following fields:
{
address: string,
location: LatLng,
placeId: string,
bounds: LatLngBounds,
componentRestrictions: GeocoderComponentRestrictions,
region: string
}
You should read Retrieving an Address for a Place ID.
/**
* Requests the details of a Place.
*
* <p>We are only enabling looking up Places by placeId as the older Place identifier, reference,
* is deprecated. Please see the <a
* href="https://web.archive.org/web/20170521070241/https://developers.google.com/places/web-service/details#deprecation">
* deprecation warning</a>.
*
* #param context The context on which to make Geo API requests.
* #param placeId The PlaceID to request details on.
* #return Returns a PlaceDetailsRequest that you can configure and execute.
*/
public static PlaceDetailsRequest placeDetails(GeoApiContext context, String placeId) {
PlaceDetailsRequest request = new PlaceDetailsRequest(context);
request.placeId(placeId);
return request;
}
try this one
Geocoder geocoder;
List<Address> addresses;
geocoder = new Geocoder(this, Locale.getDefault());
addresses = geocoder.getFromLocation(latitude, longitude, 1);
// Here 1 represent max location result to returned, by documents it recommended 1 to 5
String address = addresses.get(0).getAddressLine(0);
// If any additional address line present than only, check with max
available address lines by getMaxAddressLineIndex()
String city = addresses.get(0).getLocality();
String state = addresses.get(0).getAdminArea();
String country = addresses.get(0).getCountryName();
String postalCode = addresses.get(0).getPostalCode();
String knownName = addresses.get(0).getFeatureName();
// Only if available else return NULL
I use an application (AppWorx! Someone please create this tag!) that allows documentation to be entered about scheduled jobs as html.
I've been trying to create on-call documentation that would have a link something like this:
1 (806) xxx - xxxx
The page is displayed inside the Java app itself, and any link to http:// is opened in the user's browser window. But a tel link like above causes a big error window to pop up that shows the following error:
java.net.MalformedURLException: For input string: "+1806xxxxxxx"
at java.net.URL.<init>(Unknown Source)
at java.net.URL.<init>(Unknown Source)
at java.net.URL.<init>(Unknown Source)
at com.appworx.client.screen.modmgr.M$2.hyperlinkUpdate(NotesPanel.java:191)
at javax.swing.JEditorPane.fireHyperlinkUpdate(Unknown Source)
at javax.swing.text.html.HTMLEditorKit$LinkController.activateLink(Unknown Source)
at javax.swing.text.html.HTMLEditorKit$LinkController.mouseClicked(Unknown Source)
at java.awt.AWTEventMulticaster.mouseClicked(Unknown Source)
Other protocols fail as well (except http). If I have a mailto: link, instead of getting the error as above, it takes me to the domain portion of the email address.
I believe that whatever version of this class that the app was compiled with is several (and maybe many) years old.
Can anyone tell me what the limitations of this class are, or if workarounds exist?
The documentation for Appworx suggests that even http links will not work unless the app is invoked from the jnlp (is this a sandbox thing somehow?). Though on that note, no one here starts the application any other way.
Can anyone tell me what the limitations of this class are?
To give you an idea of how outdated the EditorKit classes are, as of Java 7 HTMLEditorKit "supports HTML version 3.2 (with some extensions), and is migrating toward version 4.0". No surprise then that the URL class (responsible for the MalformedURLException in the trace you posted) supports just the basic protocols, some of which you mentioned above:
Http
Https
Ftp
File
Jar
Can anyone tell me if workarounds exist?
Well, you can get your hands dirty with the code (if you have access to it), use a custom protocol handler and register it. Luckily for you there is one already for the tel protocol courtesy of the J2ME Polish project:
package de.enough.polish.browser.protocols;
import java.io.IOException;
import javax.microedition.io.StreamConnection;
import javax.microedition.midlet.MIDlet;
import de.enough.polish.browser.ProtocolHandler;
/**
* Protocol handler to handle the <code>tel:</code> protocol. This class calls the given phonenumber on MIDP 2.0 phones.
* Example: <a href="tel:+441231234567#22">Call Me</a>
* Note that this handler requires MIDP 2.0 or higher.
* The tel protocol handler allows you to separate the phone number and the dialtone (dtmf) that should be send after
* establishing the phone call using the '#' sign.
*
* This protocol could actually be realized using the ExternalProtocolHandler as well, however in this
* way we can deal post dial tones (DTMF) in a better way - in the HTML code they just need to be
* separated from the phonenumber using a '#'.
*/
public class TelProtocolHandler
extends ProtocolHandler
{
private MIDlet midlet;
/**
* Creates an TellProtocolHandler object using the default "tel" protocol name.
*
* #param midlet the midlet object of the application
*/
public TelProtocolHandler(MIDlet midlet)
{
this( "tel", midlet );
}
/**
* Creates an TelProtocolHandler object using the specified protocol name.
*
* #param protocolName the name of the protocol to handle
* #param midlet the midlet object of the application
*/
public TelProtocolHandler(String protocolName, MIDlet midlet)
{
super( protocolName );
this.midlet = midlet;
}
/* (non-Javadoc)
* #see de.enough.polish.browser.ProtocolHandler#getConnection(java.lang.String)
*/
public StreamConnection getConnection(String url) throws IOException
{
this.midlet.platformRequest( "tel:" + extractMsisdn(url));
return null;
}
/**
* Strips the MSISDN part off an url.
* In contrast to other protocol handlers, the external protocol handler only uses a single colon to
* separate the external protocol from the folllowing protocol, e.g. external:http://www.j2mepolish.org
*
* #param url the url to remove the protocol from
*
* #return the host and part part of the given url
*/
protected String extractMsisdn(String url)
{
String msisdn = url.substring(this.protocolName.length() + 1);
String separator = null;
//#if polish.dtmf.separator:defined
//#= separator = "${polish.dtmf.separator}";
//# if (!separator.equals("#")) {
//# int pos = msisdn.indexOf('#');
//# if (pos != -1) {
//# msisdn = msisdn.substring(0, pos) + separator + msisdn.substring(pos + 1);
//# }
//# }
//#endif
return msisdn;
}
}
Hope that helps!
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 4 years ago.
Improve this question
I am looking for a way to analyze user agent strings to determine whether they were generated by mobile devices. This needs to be java-based and usable in large batch log file analysis on hadoop for generating statistics (i.e., a web service wouldn't be appropriate).
I have seen WURFL, but given that I just need a binary mobile/not mobile response, the license fee seems prohibitive.
So far I have been using UADetector, which is almost exactly what I need. However, I have encountered some limitations with it. In my testing, I have found many user agent strings that provide enough information to determine that the user agent is from a mobile device, but are reported as UNKNOWN by UADetector.
For example, poorly-standardized Android apps can send the UA string "Android". This is enough to know that it came from a mobile device, but UADetector reports this UserAgentType as UNKNOWN rather than MOBILE_BROWSER.
Apache Mobile Filter's Lite Device Detection does the right thing, but I need something I can use from Java.
Can anyone recommend a better solution?
I'm the founder and maintainer of the MobileESP project, a free open source cross-platform library for detecting mobile devices. It's still very much alive! :-)
www.mobileesp.org
MobileESP only gives binary "is mobile" responses. You can detect by platform like iOS, Android or Windows Phone, or by device category, like "iPhone Tier" smartphones vs. tablet. Be sure to take a quick review of the API page.
As you may know, useragent strings vary widely. If the browser shipped on the device, the manufacturer may customize it. For example, HTC often customizes the native Android browser's useragent string.
Google provides recommendations on how the OEM should customize the useragent. If the device should be considered a phone, then Google recommends including the word "mobile" element in the string. But if the device should be considered a tablet, then the string should not contain "mobile." Adherence to this recommendation varies widely, of course.
Third party browsers like Opera or Maxthon can put whatever they want to in the useragent string -- and do! Certain "new" browsers which shall remain nameless have been doing very poor jobs of putting the correct information in their useragent strings for each platform (e.g., Android vs. iOS versions). There's not much you can do unless you get a lot of traffic from these browsers and wish to invest in tracking their exact useragent values per platform and software rev.
Anyway, MobileESP was created with the vision of doing the detection on a page-by-page basis when the page is served. I purposefully wrote the code to be very easy to read and customize, too.
To do the batch processing, you might do something like this:
1.) In the constructor, comment out the initDeviceScan() method. You won't need this for bulk processing.
2.) Pass the UserAgent and an empty string in to the constructor (UAgentInfo()).
3.) Then run whatever detect methods you're interested in. Be thoughtful about the order in which you do them to save time, based on a scan of your users.
For example, if most of your users are on iPhone and that's one of the detection criteria you're interested in, then run that check first. If this example, you certainly wouldn't run the BlackBerry method first!
My contact info is in the source code and on the web site. Send me a note if you have any questions or run into any bugs. Definitely look around the MobileESP.org web site for some tips.
Best wishes on your project, Aniket!
Anthony
Another thread suggests using the following library:
https://github.com/ahand/mobileesp/blob/master/Java/UAgentInfo.java
which seems OK.
How to read the Apache Mobile Filter value in JSP (for Tomcat)?
Before in the httpd.conf file where you have to configure mod_jk you muse add this:
JkEnvVar AMF_IS_MOBILE undefined
The Java code is:
request.getAttribute("AMF_IS_MOBILE")
from: http://wiki.apachemobilefilter.org
51Degrees has a free open source Java API that allows you to run offline processing. You can access it from the GitHub Repository here. https://github.com/51Degrees/Java-Device-Detection.
As part of the API there is an offline processing example (code also shown below) this takes a CSV file of User-Agents and returns the required properties into an Output file. The following example just uses 3 of the properties within the data set, for a full list you can look at the dictionary here https://51degrees.com/resources/property-dictionary
// output file in current working directory
public String outputFilePath = "batch-processing-example-results.csv";
// pattern detection matching provider
private final Provider provider;
/**
* Initialises the device detection Provider with the included Lite data
* file. For more data see:
* <a href="https://51degrees.com/compare-data-options">compare data options
* </a>
*
* #throws IOException if there was a problem reading from the data file.
*/
public OfflineProcessingExample() throws IOException {
provider = new Provider(StreamFactory.create(
Shared.getLitePatternV32(), false));
}
/**
* Reads a CSV file containing User-Agents and adds the IsMobile,
* PlatformName and PlatformVersion information for the first 20 lines.
* For a full list of properties and the files they are available in please
* see: <a href="https://51degrees.com/resources/property-dictionary">
* Property Dictionary</a>
*
* #param inputFileName the CSV file to read from.
* #param outputFilename where to save the file with extra entries.
* #throws IOException if there was a problem reading from the data file.
*/
public void processCsv(String inputFileName, String outputFilename)
throws IOException {
BufferedReader bufferedReader =
new BufferedReader(new FileReader(inputFileName));
try {
FileWriter fileWriter = new FileWriter(outputFilename);
try {
// it's more efficient over the long haul to create a match
// once and reuse it in multiple matches
Match match = provider.createMatch();
// there are 20k lines in supplied file, we'll just do a couple
// of them!
for (int i = 0; i < 20; i++) {
// read next line
String userAgentString = bufferedReader.readLine();
// ask the provider to match the UA using match we created
provider.match(userAgentString, match);
// get some property values from the match
Values isMobile = match.getValues("IsMobile");
Values platformName = match.getValues("PlatformName");
Values platformVersion = match.getValues("PlatformVersion");
// write result to file
fileWriter.append("\"")
.append(userAgentString)
.append("\", ")
.append(getValueForDisplay(isMobile))
.append(", ")
.append(getValueForDisplay(platformName))
.append(", ")
.append(getValueForDisplay(platformVersion))
.append('\n')
.flush();
}
} finally {
fileWriter.close();
}
} finally {
bufferedReader.close();
}
}
/**
* Match values may be null. A helper method to get something displayable
* #param values a Values to render
* #return a non-null String
*/
protected String getValueForDisplay(Values values) {
return values == null ? "N/A": values.toString();
}
/**
* Closes the {#link fiftyone.mobile.detection.Dataset} by releasing data
* file readers and freeing the data file from locks. This method should
* only be used when the {#code Dataset} is no longer required, i.e. when
* device detection functionality is no longer required, or the data file
* needs to be freed.
*
* #throws IOException if there was a problem accessing the data file.
*/
#Override
public void close() throws IOException {
provider.dataSet.close();
}
/**
* Instantiates this class and starts
* {#link #processCsv(java.lang.String, java.lang.String)} with default
* parameters.
*
* #param args command line arguments.
* #throws IOException if there was a problem accessing the data file.
*/
public static void main(String[] args) throws IOException {
System.out.println("Starting Offline Processing Example");
OfflineProcessingExample offlineProcessingExample =
new OfflineProcessingExample();
try {
offlineProcessingExample.processCsv(Shared.getGoodUserAgentsFile(),
offlineProcessingExample.outputFilePath);
System.out.println("Output written to " +
offlineProcessingExample.outputFilePath);
} finally {
offlineProcessingExample.close();
}
}
Hope this helps.
Disclosure: I work at 51Degrees.
To detect iPhone, Android and other mobile devices in Java user-agent can be used. If you are using Spring you can customize the below code as per your need.
#Override
public ModelAndView redirectToAppstore(HttpServletRequest request) {
String userAgent = request.getHeader("user-agent").toLowerCase();
String iphoneStoreUrl = "IPONE_STORE_URL";
String androidStoreUrl = "ANDROID_STORE_URL";
if (userAgent.contains("iphone"))
return new ModelAndView("redirect:" + iphoneStoreUrl);
else if (userAgent.contains("android"))
return new ModelAndView("redirect:" + androidStoreUrl);
return new ModelAndView("redirect:/");
}