CodeTyphon 提供了一種非常方便的網(wǎng)絡(luò)訪問方式羡疗,這在 JNI 內(nèi)尤其有用糜颠,代碼如下:
with TFPHttpClient.Create(nil) do begin
Result := Get(URL);
Free;
end;
如果希望使用異步的方式否彩,并且更加方便的進(jìn)行 Post 請(qǐng)求或是上傳文件瑞凑,可以使用我封裝好的庫,點(diǎn)擊此處看項(xiàng)目:
with THttpThread.Create(URL, hmPost) do begin
PostParam.Add('key', 'value');
FileParam.Add('file', '/sdcard/sample.txt');
Callback := @httpCallback
Start();
end;
然而陡叠,在 Android P上玩郊,這樣的代碼會(huì)報(bào)一個(gè)異常,無法正常發(fā)起請(qǐng)求枉阵,經(jīng)過跟蹤译红,發(fā)現(xiàn)請(qǐng)求時(shí)未發(fā)現(xiàn) DNS Server,因此無法對(duì)域名進(jìn)行解析兴溜,造成請(qǐng)求失敗侦厚。
看一下 CodeTyphon 內(nèi)的 fpcsrc
耻陕,可以找到 fcl-net
下有一個(gè) netdb.pp
文件,里面針對(duì) Android 的處理有一段關(guān)鍵代碼:
{$ifdef android}
Function GetDNSServers: Integer;
var
i: integer;
s: string;
H: THostAddr;
begin
Result := 0;
SetLength(DNSServers, 9);
for i := 1 to 9 do begin
s := GetSystemProperty(PAnsiChar('net.dns' + IntToStr(i)));
if s = '' then break;
H := StrToNetAddr(s);
if H.s_bytes[1] <> 0 then begin
DNSServers[Result] := H;
Inc(Result);
end;
end;
SetLength(DNSServers, Result);
end;
其實(shí)已經(jīng)很明顯能看到問題了刨沦,由于 Android P 不再允許使用 net.dnsX
來獲取 DNS Server诗宣,因此這段代碼將返回 Permission Denied
并且使 s
的值永久為空。
既然無法突破 Google 的限制想诅,那就給設(shè)定一個(gè)默認(rèn)的 DNS Server 來解決問題了召庞,在不破壞原有邏輯的前提下,增加一些代碼:
{$ifdef android}
Function GetDNSServers: Integer;
var
i: integer;
s: string;
H: THostAddr;
begin
Result := 0;
SetLength(DNSServers, 9);
for i := 1 to 9 do begin
s := GetSystemProperty(PAnsiChar('net.dns' + IntToStr(i)));
if s = '' then break;
H := StrToNetAddr(s);
if H.s_bytes[1] <> 0 then begin
DNSServers[Result] := H;
Inc(Result);
end;
end;
// fix
if (Result = 0) then begin
H := StrToNetAddr('8.8.8.8');
DNSServers[0] := H;
Inc(Result);
end;
SetLength(DNSServers, Result);
end;
經(jīng)過測(cè)試来破,這段代碼在 Android P 上能夠正常工作篮灼,至此,問題修復(fù)完畢讳癌。
相關(guān)的 fix 代碼也已上傳至 CodeTyphon 官方論壇穿稳,將在下個(gè)版本被合并,點(diǎn)擊此處查看官方論壇帖子