Any app I could find on GPlay counts traffic for both SIM while in Settings-Data Usage traffic is counted for each SIM. I used jd-gui to see how it's done and have found that classes from private API were used.
import android.net.INetworkStatsService;
import android.net.INetworkStatsService.Stub;
import android.net.INetworkStatsSession;
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
import android.net.NetworkStats;
import android.net.NetworkStats.Entry;
import android.net.NetworkStatsHistory;
import android.net.NetworkStatsHistory.Entry;
import android.net.NetworkTemplate;
Can I use reflection to use them?
Update.
I've tried to use Reflection. Executing this code give me an exception "java.lang.InstantiationException: can't instantiate class android.net.INetworkStatsService"
Class<Object> MyINetworkStatsService = null;
try {
MyINetworkStatsService = (Class<Object>) Class.forName("android.net.INetworkStatsService");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Object mStatsService = null;
try {
mStatsService = MyINetworkStatsService != null ? MyINetworkStatsService.newInstance() : null;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
Upd. Because both StatsService and StatsSession are interfaces, I can't instantiate them and should use Proxy. Can anyone help with that?
Upd. I've made an effort
String id = getActiveSubscriberId(mContext);
try {
Object tmpl = null;
long stats = 0;
Class<?> a = Class.forName("android.net.NetworkTemplate");
Class<?> b = Class.forName("android.net.INetworkStatsService");
Method getState = b.getMethod("getNetworkTotalBytes", a, long.class, long.class);
Method[] am = a.getDeclaredMethods();
Method getTemplate = null;
for (Method m : am) {
if (m.getName().equalsIgnoreCase("buildTemplateMobileAll")) {
getTemplate = m;
break;
}
}
if (getTemplate != null) {
getTemplate.setAccessible(true);
tmpl = getTemplate.invoke(a.getClass(), id);
}
Object object = Proxy.newProxyInstance(b.getClass().getClassLoader(), b.getInterfaces(), new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("getNetworkTotalBytes")) {
return method.invoke(args[0], args[1], args[2], args[3]);
}
throw new RuntimeException("no method found");
}
});
Object[] args = {b.getClass(), tmpl, Long.MIN_VALUE, Long.MAX_VALUE};
stats = (long) ((b.getClass()) object).getState(args);
} catch (ClassNotFoundException e0) {
} catch (NoSuchMethodException e0) {
} catch (IllegalAccessException e0) {
} catch (InvocationTargetException e0) {
}
But it says that there is an error "Method call expected" in
stats = (long) ((b.getClass()) object).getState(args);
If I change this string like this
stats = (long) ((b) object).getState(args);
I get another error - "Unknown class: 'b'"
Related
I can't get to work java reflection in Spring boot with Controller and JdbcTemplate.
Default controller looks like:
public class DefaultController {
private static final Logger logger = LoggerFactory.getLogger(DefaultController.class);
public JsonResponseDataModel selectOneAuto(Long id, Class<?> repository, HttpServletResponse response){
final JsonResponseDataModel result = new JsonResponseDataModel();
System.out.println("The name of class is " + repository.getName());
Method[] methods = repository.getMethods();
for (Method method : methods) {
System.out.println("Method: " + method.getName());
}
try {
//Method method = repository.getClass().getMethod("selectOne", Long.class);
Method method = repository.getClass().getDeclaredMethod("selectOne", Long.class);
method.invoke(repository, id);
logger.info("selectOneAuto : id={} ", id);
} catch (EmptyResultDataAccessException e) {
result.setEmptyResultDataAccessException("id", id.toString());
} catch (DataAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return result;
}
}
Inside CompanyRepository class is defined selectOne method with Long input:
#Transactional(readOnly=true)
public CompanyModel selectOne(Long id) {
CompanyModel result = null;
final String sql = "SELECT * FROM company WHERE id=?";
return jdbcTemplate.queryForObject(sql, new Object[]{id}, new CompanyRowMapper());
}
When I create a new class "CompanyController extends DefaultController" and call method selectOneAuto:
selectOneAuto(id, new CompanyRepository().getClass(), response);
Then it ends with error on line "Method method = repository.getClass().getDeclaredMethod("selectOne", Long.class);"
"Java.lang.NoSuchMethodException: java.lang.Class.selectOne(java.lang.Long)"
But the for loop inside "selectOneAuto" method outputs method named "selectOne". What is wrong here?
Your code attempts to call the method on an instance of Class.
method.invoke(repository, id);
repository object is an instance of Class since you are passing new CompanyRepository().getClass() as parameter.
The second point to be noted is repository is an instance of Class already so there is no need to call getClass() on this object.
You should obtain the method object using the following code :
Method method = repository.getDeclaredMethod("selectOne", Long.class);
And then this should work :
CompanyRepository repsitoryObj = new CompanyRepository();
method.invoke(repsitoryObj, id);
Or a better and cleaner way is to simply change the type of your repository parameter as CompanyRepository your method will look as follows:
public JsonResponseDataModel selectOneAuto(Long id, CompanyRepository repository, HttpServletResponse response){
final JsonResponseDataModel result = new JsonResponseDataModel();
System.out.println("The name of class is " + repository.getClass().getName());
Method[] methods = repository.getClass().getMethods();
for (Method method : methods) {
System.out.println("Method: " + method.getName());
}
try {
//Method method = repository.getClass().getMethod("selectOne", Long.class);
Method method = repository.getClass().getDeclaredMethod("selectOne", Long.class);
method.invoke(repository, id);
logger.info("selectOneAuto : id={} ", id);
} catch (EmptyResultDataAccessException e) {
result.setEmptyResultDataAccessException("id", id.toString());
} catch (DataAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return result;
}
In commons-collections 3.2.1 the following one-liner worked nicely to retrieve the myProperty values of the objects inside myCollection:
Collection<MyType> myTypes = (Collection<MyType>) CollectionUtils.collect(myCollection, new BeanToPropertyValueTransformer("myProperty"))
Only drawback is that generics are not supported, so type casting needs to be done.
What would be a solution that works in commons-collection4, taking advantage of generics?
Apparently they removed BeanToPropertyValueTransformer from the release of apache-commons-collection4.
I managed to achieve the same behavior by defininig a custom Transformer. The introduction of generics eliminates the necessity of casting the output collection:
Collection<MyInputType> myCollection = ...
Collection<MyType> myTypes = CollectionUtils.collect(myCollection, new Transformer<MyInputType, MyType>() {
#Override
public MyType transform(MyInputType input) {
return input.getMyProperty();
}
}
You could also write your own Transformer that uses reflection
class ReflectionTransformer<O>
implements
Transformer<Object, O> {
private String reflectionString;
public ReflectionTransformer(String reflectionString) {
this.reflectionString = reflectionString;
}
#SuppressWarnings("unchecked")
#Override
public O transform(
Object input) {
try {
return (O) BeanUtils.getProperty(input, reflectionString);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
}
and use it same as you used to do with BeanToPropertyValueTransformer
Collection<MyType> myTypes = CollectionUtils.collect(myCollection, new ReflectionTransformer<MyType>("myProperty"));
Try using the below class (using commons-collection4) instead -
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.lang.reflect.InvocationTargetException;
public class BeanToPropertyValueTransformer implements Transformer {
private final Log log = LogFactory.getLog(this.getClass());
private String propertyName;
private boolean ignoreNull;
public BeanToPropertyValueTransformer(final String propertyName) {
this(propertyName, false);
}
public BeanToPropertyValueTransformer(final String propertyName, final boolean ignoreNull) {
super();
if ((propertyName != null) && (propertyName.length() > 0)) {
this.propertyName = propertyName;
this.ignoreNull = ignoreNull;
} else {
throw new IllegalArgumentException(
"propertyName cannot be null or empty");
}
}
public Object transform(final Object object) {
Object propertyValue = null;
try {
propertyValue = PropertyUtils.getProperty(object, propertyName);
} catch (final IllegalArgumentException e) {
final String errorMsg = "Problem during transformation. Null value encountered in property path...";
if (ignoreNull) {
log.warn("WARNING: " + errorMsg + e);
} else {
final IllegalArgumentException iae = new IllegalArgumentException(errorMsg);
if (!BeanUtils.initCause(iae, e)) {
log.error(errorMsg, e);
}
throw iae;
}
} catch (final IllegalAccessException e) {
final String errorMsg = "Unable to access the property provided.";
final IllegalArgumentException iae = new IllegalArgumentException(errorMsg);
if (!BeanUtils.initCause(iae, e)) {
log.error(errorMsg, e);
}
throw iae;
} catch (final InvocationTargetException e) {
final String errorMsg = "Exception occurred in property's getter";
final IllegalArgumentException iae = new IllegalArgumentException(errorMsg);
if (!BeanUtils.initCause(iae, e)) {
log.error(errorMsg, e);
}
throw iae;
} catch (final NoSuchMethodException e) {
final String errorMsg = "No property found for name [" +
propertyName + "]";
final IllegalArgumentException iae = new IllegalArgumentException(errorMsg);
if (!BeanUtils.initCause(iae, e)) {
log.error(errorMsg, e);
}
throw iae;
}
return propertyValue;
}
public String getPropertyName() {
return propertyName;
}
public boolean isIgnoreNull() {
return ignoreNull;
}
}
Note: Every time I go to type up this question, I think I see something, but it never pans out, so for the third or fourth time.
Synopsis: I am trying to serialize an object that inherits from the base Response class using the Response class, of which the subclass may have non-primitive field types.
The code is as such (warning: large and not elegant), ordered from the specific class (SpecificResponse), as extended from a common class (CommonResponse), which is a concrete implementation of the abstract class (Response), driven by a test program (Program).
// SpecificResponse.java
package com.jdgj.thinking;
public final class SpecificResponse extends CommonResponse {
public String hell;
public int trike;
public short tail;
public SpecificResponse() {
super();
}
}
SpecifcResponse extends CommonResponse:
// CommonResponse.java
package com.jdgj.thinking;
public class CommonResponse extends Response {
public int thing2;
public Value value;
#Override
protected void initialize() {
System.out.println("hello!");
value = new Value();
}
}
For testing purposes, I just made a simple Value object:
// Value.java
package com.jdgj.thinking;
public class Value {
public int five;
}
And, that which does a lot of work, and also the foundation for CommonResponse, the Response class:
// Response.java
package com.jdgj.thinking;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
public abstract class Response {
public static Class<?> fromClassSignature(List<String> signature) throws IllegalArgumentException, IllegalStateException, ClassNotFoundException {
if (signature == null || signature.size() == 0) {
throw new IllegalArgumentException("Null or empty Response class signature.");
}
String lastClassName = null;
for (String line : signature) {
if (line.startsWith("class:")) {
lastClassName = line.split(":")[1];
}
}
if (lastClassName == null) {
throw new IllegalStateException("Could not find the Response class name.");
}
Class<?> c = Class.forName(lastClassName);
lastClassName = null;
Class<?> sc = c.getSuperclass();
while (sc != null && !sc.equals(Response.class)) {
sc = sc.getSuperclass();
}
if (sc != null) {
sc = null;
return c;
} else {
return null;
}
}
protected abstract void initialize();
private String getFieldSignature(Field field) {
return "field:" + field.getName() + "|" + field.getType().getCanonicalName();
}
private List<String> serializeObject(Class<?> c, Object o) {
List<String> serialization = new ArrayList<String>(0);
serialization.add("class:" + c.getName());
for (Field f : c.getDeclaredFields()) {
if (!f.isSynthetic() && Modifier.isPublic(f.getModifiers())) {
StringBuilder sb = new StringBuilder(getFieldSignature(f));
Class<?> t = f.getType();
Object value = null;
try {
value = f.get(o);
System.out.println(f.getName() + "=" + value);
if (t.isPrimitive() || t.equals(String.class)) {
sb.append("`" + value.toString() + "");
}
} catch (NullPointerException e) {
if (t.isPrimitive() || t.equals(String.class)) {
sb.append("`");
} else {
System.out.println("UNEXPECTED NULL POINTER EXCEPTION");
}
} catch (IllegalArgumentException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalAccessException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally {
serialization.add(sb.toString());
if (value != null) {
if (!(t.isPrimitive() || t.equals(String.class))) {
serialization.addAll(serializeObject(t, value));
}
}
}
sb = null;
t = null;
}
}
return serialization;
}
private List<String> describeClass(Class<?> c) {
List<String> description = new ArrayList<String>(0);
description.add("class:" + c.getName());
for (Field f : c.getDeclaredFields()) {
if (!f.isSynthetic() && Modifier.isPublic(f.getModifiers())) {
description.add(getFieldSignature(f));
Class<?> t = f.getType();
if (!(t.isPrimitive() || t.equals(String.class))) {
description.addAll(describeClass(t));
}
t = null;
}
}
return description;
}
public final List<String> getSerializedObject() {
Class<?> c = getClass();
List<String> object = new ArrayList<String>(0);
while (c != null && !c.equals(Response.class)) {
object.addAll(0, serializeObject(c, this));
c = c.getSuperclass();
}
c = null;
return object;
}
public final List<String> getClassSignature() {
Class<?> c = getClass();
List<String> signature = new ArrayList<String>(0);
while (c != null && !c.equals(Response.class)) {
signature.addAll(0, describeClass(c));
c = c.getSuperclass();
}
c = null;
return signature;
}
}
These classes are driven by a 'dev-test' program for now:
// Program.java
import com.jdgj.thinking.Response;
import com.jdgj.thinking.SpecificResponse;
public class Program {
private static void printClassSignature(Response response) {
for (String line : response.getClassSignature()) {
System.out.println(line);
}
}
private static void printSerializedObject(Response response) {
for (String line : response.getSerializedObject()) {
System.out.println(line);
}
}
public static void main(String[] args) {
String CN_SPECRSP = "com.jdgj.thinking.SpecificResponse";
Class<?> response = null;
try {
response = Response.fromClassSignature(new SpecificResponse().getClassSignature());
} catch (IllegalArgumentException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalStateException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally {
if (response != null) {
System.out.println("Expected: " + CN_SPECRSP + "; Actually: " + response.getCanonicalName());
Response rsp = null;
try {
rsp = (Response)response.newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (rsp != null) {
//printClassSignature(rsp);
printSerializedObject(rsp);
rsp = null;
}
}
response = null;
}
}
}
}
Here's the output:
Expected: com.jdgj.thinking.SpecificResponse; Actually: com.jdgj.thinking.SpecificResponse
hell=null
trike=0
tail=0
thing2=0
value=null
class:com.jdgj.thinking.CommonResponse
field:thing2|int`0
field:value|com.jdgj.thinking.Value
class:com.jdgj.thinking.SpecificResponse
field:hell|java.lang.String`
field:trike|int`0
field:tail|short`0
Why does value report null?
In both not having and having a constructor defined in CommonResponse to initialize the Value instance, it's still shown as null. If I uncomment the Program.getClassSignature method, the code delves into the Value object to get the five field:
Expected: com.jdgj.thinking.SpecificResponse; Actually: com.jdgj.thinking.SpecificResponse
class:com.jdgj.thinking.CommonResponse
field:thing2|int
field:value|com.jdgj.thinking.Value
class:com.jdgj.thinking.Value
field:five|int
class:com.jdgj.thinking.SpecificResponse
field:hell|java.lang.String
field:trike|int
field:tail|short
hell=null
trike=0
tail=0
thing2=0
value=null
class:com.jdgj.thinking.CommonResponse
field:thing2|int`0
field:value|com.jdgj.thinking.Value
class:com.jdgj.thinking.SpecificResponse
field:hell|java.lang.String`
field:trike|int`0
field:tail|short`0
I feel as if I've exhausted my Google-fu, and I feel like I'm missing something just.. blatantly obvious, but I cannot think of the reason, or the right query to ask Google. Everyone keeps providing ways to get primitive fields, but that is not what I am seeking. I therefore submit to the guidance of SO.
As Holger said you never initialize that field. You have a initialize() method to do it, but never invoke it.
Of course if you call getClassSignature() you get info about your field, actually it's there; you got a field named value of type com.jdgj.thinking.Value in your class, but it never has been instantiated, so that field value is null.
My java compiler is complaining that my code uses "unchecked or unsafe operations". Any idea which lines are causing that in the two code snippets?
#SuppressWarnings("unchecked")
private final void prepareChannelAccountStringsParserImplementedClassConstructor() {
try {
String channelAccountStringsParserImplementedClassName = channelIdentifier + "AccountStringsParser";
Class channelAccountStringsParserImplementedClass = Class.forName(channelAccountStringsParserImplementedClassName);
Class[] channelAccountStringsParserImplementedClassArguments = new Class[1];
channelAccountStringsParserImplementedClassArguments[0] = String.class;
channelAccountStringsParserImplementedClassConstructor = channelAccountStringsParserImplementedClass.getConstructor(channelAccountStringsParserImplementedClassArguments);
channelAccountStringsParserImplementedParseMethod = channelAccountStringsParserImplementedClass.getMethod("parse", String.class);
channelAccountStringsParserGetRequestIDMethod = channelAccountStringsParserImplementedClass.getMethod("getRequestID");
} catch (ClassNotFoundException classNotFoundException) {
NotifyMeListenersLogsDB notifyMeListenersLogsDB = DatabaseController.getInstance().getNotifyMeListenersLogsDB();
notifyMeListenersLogsDB.writeDeveloperException(classNotFoundException);
} catch (NoSuchMethodException noSuchMethodException) {
NotifyMeListenersLogsDB notifyMeListenersLogsDB = DatabaseController.getInstance().getNotifyMeListenersLogsDB();
notifyMeListenersLogsDB.writeDeveloperException(noSuchMethodException);
}
}
#SuppressWarnings("unchecked")
public synchronized final void requestChannelAccountsCompletionSuccess(String responseContent) {
Object channelAccountStringsParserImplementedInstance;
ArrayList<ChannelAccount> channelAccounts = null;
String requestID = null;
try {
channelAccountStringsParserImplementedInstance = channelAccountStringsParserImplementedClassConstructor.newInstance(responseContent);
channelAccounts = (ArrayList<ChannelAccount>) channelAccountStringsParserImplementedParseMethod.invoke(channelAccountStringsParserImplementedInstance, responseContent);
requestID = (String) channelAccountStringsParserGetRequestIDMethod.invoke(channelAccountStringsParserImplementedInstance);
} catch (InstantiationException instantiationException) {
NotifyMeListenersLogsDB notifyMeListenersLogsDB = DatabaseController.getInstance().getNotifyMeListenersLogsDB();
notifyMeListenersLogsDB.writeDeveloperException(instantiationException);
} catch (IllegalAccessException illegalAccessException) {
NotifyMeListenersLogsDB notifyMeListenersLogsDB = DatabaseController.getInstance().getNotifyMeListenersLogsDB();
notifyMeListenersLogsDB.writeDeveloperException(illegalAccessException);
} catch (InvocationTargetException invocationTargetException) {
NotifyMeListenersLogsDB notifyMeListenersLogsDB = DatabaseController.getInstance().getNotifyMeListenersLogsDB();
notifyMeListenersLogsDB.writeDeveloperException(invocationTargetException);
}
channelAccountStringsParserImplementedInstance = null;
try {
startChannelConnections(channelAccounts);
isStarted = true;
LoadBalancer.getInstance().sendSuccessAcknowledgement(requestID);
} catch (NotifyMeListenersApplicationInitializationException notifyMeListenersApplicationInitializationException) {
NotifyMeListenersLogsDB notifyMeListenersLogsDB = DatabaseController.getInstance().getNotifyMeListenersLogsDB();
notifyMeListenersLogsDB.writeNotifyMeListenersException(notifyMeListenersApplicationInitializationException);
System.exit(1);
}
}
Of course, I put the #SuppressWarnings to suppress it, but I'd like to know the cause. Anyone can help?
Class is a parameterized class. you should use Class<?> (or something more specific if necessary). of course, the compiler error probably tells you exactly where the problem is.
Also, this line is an unchecked cast, but you have no choice on that one:
channelAccounts = (ArrayList<ChannelAccount>)channelAccountStringsParserImplementedParseMethod.invoke(channelAccountStringsParserImplementedInstance, responseContent);
This question already has answers here:
How do I invoke a private static method using reflection (Java)?
(5 answers)
Closed 8 years ago.
I have a bunch of static method names, how do I execute them. I think I can use reflection, but how to do that?
directly from the interwebz
Class<?> class1;
try {
class1 = Class.forName(CLASS);
Method method = class1.getMethod(METHOD, String.class);
Object o = method.invoke(null, NAME);
System.out.println(o);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
Code to execute static method:
Method method = Utils.class.getMethod("generateCacheFolderName", Integer.class);
System.out.println(method.invoke(null, new Integer(10)));
and class with static method:
public class Utils {
public static String generateCacheFolderName(Integer len) {
Random rand = new Random();
StringBuilder sb = new StringBuilder(len);
for(int i = 0; i<len; ++i)
sb.append(rand.nextInt() % 10);
return sb.toString();
}
public static String anotherStaticMethod() {
return null;
}
}
static public Object execute( Class<?> cls, Object instance, String methodname,
Object[] args, Class<?>[] types ) throws Exception {
Object result = null;
Method met = cls.getMethod( methodname, types );
if (instance == null && !Modifier.isStatic( met.getModifiers() )) {
throw new Exception("Method '" + methodname + "' is not static, so "
+ "instance must be not null");
}
try {
result = met.invoke( instance, args );
}
catch (InvocationTargetException ite) {
throw (Exception) ite.getCause();
}
return result;
}