В телефонах Gingerbread я всегда получаю эту ошибку: Trust Anchor not found for Android SSL Connection
, даже если я настроюсь полагаться на свой сертификат.
Вот код, который я использую (на языке Scala):
object Security {
private def createCtxSsl(ctx: Context) = {
val cer = {
val is = ctx.getAssets.open("mycertificate.crt")
try
CertificateFactory.getInstance("X.509").generateCertificate(is)
finally
is.close()
}
val key = KeyStore.getInstance(KeyStore.getDefaultType)
key.load(null, null)
key.setCertificateEntry("ca", cer)
val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
tmf.init(key)
val c = SSLContext.getInstance("TLS")
c.init(null, tmf.getTrustManagers, null)
c
}
def prepare(url: HttpURLConnection)(implicit ctx: Context) {
url match {
case https: HttpsURLConnection ⇒
val cSsl = ctxSsl match {
case None ⇒
val res = createCtxSsl(ctx)
ctxSsl = Some(res)
res
case Some(c) ⇒ c
}
https.setSSLSocketFactory(cSsl.getSocketFactory)
case _ ⇒
}
}
def noSecurity(url: HttpURLConnection) {
url match {
case https: HttpsURLConnection ⇒
https.setHostnameVerifier(new HostnameVerifier {
override def verify(hostname: String, session: SSLSession) = true
})
case _ ⇒
}
}
}
, и вот код подключения:
def connect(securize: HttpURLConnection ⇒ Unit) {
val conn = url.openConnection().asInstanceOf[HttpURLConnection]
securize(conn)
conn.connect();
....
}
try {
connect(Security.prepare)
} catch {
case ex: SSLHandshakeException /*if ex.getMessage != null && ex.getMessage.contains("Trust anchor for certification path not found")*/ ⇒
connect(Security.noSecurity)
}
В принципе, я настраиваю доверие к своему пользовательскому сертификату. Если это не удается, я отключу безопасность. Это не самый лучший вариант, но единственный выбор, который я знаю со старыми и багги-телефонами.
Этот пример кода можно легко перевести на Java.
Если вы просто пытаетесь вызвать метод, вы можете использовать стандартный синтаксис:
[self meth2:next_int];
Если вам действительно нужно использовать performSelectorOnMainThread:
, вы можете заключить номер в NSNumber
для звонка. Вы говорите, что не можете этого сделать, потому что вам нужно изменить число, но вы можете просто вытащить int и изменить его:
[self performSelectorOnMainThread:@selector(meth2:) withObject:[NSNumber numberWithInt:next_int] waitUntilDone:NO];
// ... later ...
- (void)meth2:(NSNumber *)number {
int myInt = [number intValue];
// do stuff with myInt
}
Но, возможно, вы имеете в виду, что хотите получить значение числа в качестве вывода из вашего позвоните на meth2
. Если это то, что вы имеете в виду, то вы можете передать двойной указатель, чтобы получить обратно новый объект:
- (void)meth2:(NSNumber **)number {
int myInt = [*number intValue];
// do stuff with myInt
*number = [NSNumber numberWithInt:myInt];
}
// The caller can now operate like this:
NSNumber *number = [NSNumber numberWithInt:next_int];
[self performSelectorOnMainThread:@selector(meth2:) withObject:&number waitUntilDone:YES];
int returnInt = [*number intValue];
Конечно, это не совсем поточно-ориентированное, поэтому, если вы делаете что-то с несколькими потоками, я бы посоветовал использование ключевого слова @synchronized
для доступа к многопоточным переменным или настройка атомарных свойств (т. е. свойств, не объявленных как nonatomic
).
Кроме того, метамфетамин вреден !! ха-ха
Вы не можете использовать next_int
в качестве withObject:
, потому что это не объект.
Измените свой вызов на:
[self performSelectorOnMainThread:@selector(meth2:)
withObject:[NSNumber numberWithInt:next_int] waitUntilDone:NO];
EDIT:
И измените meth2
на ожидание NSNumber
вместо int
.
Оберните целое число в NSNumber перед передачей:
int next_int = 1
NSNumber *theNumber = [NSNumber numberWithInt:next_int];
[self performSelectorOnMainThread:@selector(meth2:) withObject:theNumber waitUntilDone:NO];
Тогда ваш метод -meth2: может выглядеть примерно так:
- (void)meth2:(NSNumber*)theNumber
{
int next_int = [theNumber intValue];
// do whatever
}