2013-03-21 13 views
31

Có cách nào để phát hiện khi đồng hồ hệ thống Android đã được đặt lại bởi người dùng trong Android không?Có cách nào để phát hiện khi người dùng đã thay đổi thời gian đồng hồ trên thiết bị của họ không?

Tôi đang thiết kế một ứng dụng sử dụng thời gian hệ thống để xác định thời điểm người dùng ở một địa điểm nhất định tại một thời điểm nhất định và tôi không muốn dựa vào tính khả dụng của mạng tại thời điểm đó. Rõ ràng, do đó, nó sẽ là tốt để biết khi người dùng đã thay đổi đồng hồ hệ thống, vì vậy họ không thể "ăn gian".

Trả lời

39

Có, có. Các ACTION_TIME_CHANGED Intent được phát sóng khi thời gian thiết bị được thay đổi, và bạn có thể có một phương pháp sẽ kích hoạt khi Intent này được phát hiện.

Mục đích này đã ở trong Android kể từ API cấp 1, vì vậy nó sẽ hoạt động trên bất kỳ nền tảng nào bạn có thể cần phải tương thích.

Bạn sẽ cần phải xử lý các Broadcast với một BroadcastReceiver:

public class TimeChangedReceiver extends BroadcastReceiver { 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     //Do whatever you need to 
    } 

} 

Bạn cũng sẽ cần phải thêm một cái gì đó như thế này để Manifest của bạn:

<receiver android:name=".TimeChangedReceiver"> 
    <intent-filter> 
    <action android:name="android.intent.action.TIME_SET" /> 
    </intent-filter> 
</receiver> 

này sẽ cho phép Android để biết kích hoạt bộ thu của bạn khi phát hiện loại ý định này.

Dường như điều này không quan tâm ai chỉnh sửa thời gian, nhưng cũng không kích hoạt trên các điều chỉnh tự động khi bạn được đồng bộ hóa với mạng. Nếu bạn mất mạng và lấy lại nó, tuy nhiên, điều này có thể sẽ cháy vì thời gian của bạn sẽ hơi khác (giả sử bạn đang sử dụng thời gian mạng tự động).

Tuy nhiên, trong khi đồng hồ trên điện thoại di động không phải là đặc biệt là chính xác (vì chúng thường dựa vào đồng bộ hóa với tín hiệu thời gian mà chúng nhận được) trong kinh nghiệm của chúng, chúng hoàn toàn không được mất quá 30 giây hoặc một phút mỗi giờ, ở mức tối đa tuyệt đối, vì vậy nếu thay đổi thời gian nhỏ, bạn có thể giả sử nó là tự động. Leap giây, khi chúng được thêm vào, cũng sẽ có khả năng tạo ra một thông báo thay đổi thời gian, mặc dù đây rõ ràng là nhỏ và không thường xuyên.

Bạn có thể sử dụng ConnectivityManager để theo dõi xem điện thoại có kết nối hay không và bạn có thể thay đổi hành vi dựa trên đó (ví dụ: miễn là kết nối mạng và thời gian tự động/mạng, bỏ qua thời gian thay đổi hoặc một cái gì đó) nhưng tôi không thể tìm thấy bất kỳ ý định liên quan đến mất/lấy lại kết nối mạng, do đó bạn có thể sẽ phải sử dụng một phương pháp bỏ phiếu.

+2

Phương pháp này có khác biệt giữa người dùng ** thay đổi thời gian và thời gian thay đổi do cập nhật mạng không? –

+1

Đó là một câu hỏi rất hay. Câu trả lời dường như là không, vì nó đã kích hoạt khi tôi đặt điện thoại của tôi vào chế độ trên máy bay trong vài phút và sau đó bật radio trở lại. Tuy nhiên, nó không xuất hiện để kích hoạt khi bạn đang nhận được cập nhật thời gian tự động từ mạng và nó làm cho điều chỉnh nhỏ của nó để giữ cho thời gian của bạn chính xác. Có một vài lựa chọn để nhận thời gian rất chính xác: bạn có thể sử dụng dấu thời gian trên một đối tượng địa điểm, rất chính xác nhưng không thể yêu cầu theo yêu cầu (bạn có thể nghe chúng vào và khi nào bạn biết thời gian tại thời điểm đó). – matt5784

+0

Xem http://stackoverflow.com/a/12320918/1003511 để có thể triển khai thời gian từ vị trí. Dường như có thể là một cách để kích hoạt cài đặt đồng bộ hóa thời gian tự động của thiết bị nhưng điều này có lẽ không phải là điều tốt nhất cho người dùng của bạn nếu họ đã đặt thời gian theo cách thủ công vì một lý do nào đó. Xem http://stackoverflow.com/a/8214204/1003511 để biết thêm thông tin về điều này. Tôi cũng đã chỉnh sửa câu trả lời của mình. – matt5784

1

Nếu bạn không ngại ứng dụng của mình sẽ bị lừa khi đồng hồ của người dùng được cập nhật do * DT/* ST thay đổi, thỉnh thoảng đồng bộ với các nguồn NTP có thể tua lại đồng hồ của bạn, quá trình ngừng của riêng bạn, có thể thực hiện một kiểm tra "hậu quả" trên hệ thống thời gian để nếu thời gian đã đi "trở lại" bạn cho rằng đó là một "gian lận". Nếu không, bạn phải dựa vào máy chủ sẽ là nguồn của bạn "thời gian" hợp lệ. Và thậm chí sau đó, thời gian máy chủ của bạn cũng có thể thỉnh thoảng quay ngược lại.

+1

Thật sự tôi chỉ nghĩ đến một cái gì đó: Tôi có thể đo lường sự khác biệt giữa 'System.currentTimeMillis() 'và' SystemClock.elapsedRealtime() 'và nếu nó thay đổi thêm hơn một vài phút tôi biết có điều gì đó đã xảy ra. Rõ ràng tôi sẽ phải thiết lập lại nó trên một hệ thống khởi động nhưng tôi có thể thêm một 'BroadcastReceiver' trong cho các sự kiện khởi động hệ thống. Cảm ơn bạn đã cập nhật thông tin cập nhật đồng hồ tự động; Tôi đã hy vọng sẽ có một phương pháp để phát hiện thay đổi người dùng chỉ nhưng tôi đoán không! –

9

Thời gian hệ thống (System.currentTimeMillis()) sẽ thay đổi nếu người dùng điều chỉnh đồng hồ, nhưng thời gian trôi qua kể từ khi khởi động (SystemClock.elapsedRealtime()) hy vọng sẽ không. Bằng cách theo dõi sự khác biệt giữa hai, nó sẽ có thể phát hiện những thay đổi lớn cho đồng hồ hệ thống của người sử dụng.

Điều quan trọng là không theo dõi những thay đổi nhỏ có thể do mạng cập nhật đồng hồ hệ thống gây ra. Tôi sẽ giả định rằng với mục đích của tôi, bất kỳ sự thay đổi nào trong khoảng nửa giờ là không liên quan; thời gian hệ thống không nên thay đổi trên quốc gia Locale thay đổi nhưng điều đó cũng có thể đáng để loại bỏ.

Thời gian thực đã trôi qua rõ ràng sẽ được đặt lại khi khởi động nên tôi phải bao gồm BroadcastReceiver để đặt lại chênh lệch khi nhận được android.intent.action.BOOT_COMPLETED.

+0

không thể sử dụng SystemClock.elapsedRealtime() trực tiếp mà không cần suy nghĩ System.currentTimeMillis() – Suranga

17

Một thông báo nhỏ cho câu trả lời của matt5784: Tôi phát hiện ra rằng trên Android 4.1.2 hành động ý định không có sẵn, không biết nếu điều này là dành cho tất cả các phiên bản Android hoặc chỉ tại tôi. Thay vì

 "android.intent.action.ACTION_TIME_CHANGED" 

sử dụng

 "android.intent.action.TIME_SET" 
+0

Tôi xin lỗi tôi nhấn nút Xuống bởi Sai lầm: (Tôi sẽ cố gắng nghịch đảo nó Sau này, cho thời điểm stackoverflow chặn tôi hoàn tác nó: | Xin lỗi lần nữa. – ahmedibrahim085

+0

:) .... không có vấn đề .... – Opiatefuchs

+0

Tôi đã thử lại, nhưng nó mang lại cho tôi một thông báo màu đỏ: "Phiếu bầu của bạn hiện bị khóa trừ khi câu trả lời này được chỉnh sửa". Tôi thực sự xin lỗi – ahmedibrahim085

2

Chúng ta có thể sử dụng cả hai TIME_SETTIMEZONE_CHANGED.

<application 
    ...> 

    <receiver android:name=".TimeChangedReceiver"> 
     <intent-filter> 
      <action android:name="android.intent.action.TIME_SET"/> 
      <action android:name="android.intent.action.TIMEZONE_CHANGED"/> 
     </intent-filter> 
    </receiver> 
</application> 

TimeChangedReceiver.java

public class TimeChangedReceiver extends BroadcastReceiver { 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     Toast.makeText(context, "time change " + intent.getAction(), Toast.LENGTH_SHORT).show(); 
    } 
} 
Các vấn đề liên quan