├── .gitignore
├── .idea
├── compiler.xml
├── copyright
│ ├── WickerLabs.xml
│ └── profiles_settings.xml
├── encodings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── LICENSE
├── README.md
├── SampleApp
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── wickerlabs
│ │ └── calls
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── ic_launcher-web.png
│ ├── java
│ │ └── com
│ │ │ └── wickerlabs
│ │ │ └── calls
│ │ │ ├── Adapter
│ │ │ └── LogsAdapter.java
│ │ │ └── MainActivity.java
│ └── res
│ │ ├── drawable
│ │ ├── cancelled.png
│ │ ├── missed.png
│ │ ├── received.png
│ │ └── sent.png
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ └── log_layout.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── wickerlabs
│ └── calls
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── logmanager
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── wickerlabs
│ │ └── logmanager
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── wickerlabs
│ │ │ └── logmanager
│ │ │ ├── LogObject.java
│ │ │ ├── LogsManager.java
│ │ │ └── interfaces
│ │ │ └── CallLogObject.java
│ └── res
│ │ └── values
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── wickerlabs
│ └── logmanager
│ └── ExampleUnitTest.java
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/WickerLabs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 2-Clause License
2 |
3 | Copyright (c) 2017, Wickerman
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | **Call Logs** - Android library for accessing device call logs
3 | ================
4 | [](https://jitpack.io/#wickerlabs/CallLogs)
5 | [](http://android-arsenal.com/details/1/4523)
6 |
7 | 
8 |
9 |
10 | Installation
11 | -------------
12 |
13 | **Step 1**. Add the JitPack repository to your root build.gradle file.
14 |
15 |
16 | allprojects {
17 | repositories {
18 | ...
19 | maven { url "https://jitpack.io" }
20 | }
21 | }
22 |
23 | **Step 2**. Add the library dependency to your app build.gradle file
24 |
25 | dependencies {
26 | implementation 'com.github.wickerlabs:CallLogs:1+@aar'
27 | }
28 |
29 | **Step 3**. Handle permissions (For API 23+)
30 |
31 | For those targeting API 23+,
32 | you should handle the runtime permissions for READ_CONTACTS and READ_CALL_LOG.
33 | As a reference, check out the sample app in the repository.
34 | Other than that, permissions are automatically added to the manifest file.
35 |
36 | Usage
37 | -------------
38 |
39 | - Initialization
40 |
41 | ```java
42 | LogsManager logsManager = new LogsManager(context);
43 | ```
44 |
45 |
46 | - Getting a list of call logs
47 |
48 |
49 | ```java
50 | List callLogs = logsManager.getLogs(type);
51 | ```
52 |
53 |
54 | - Available list types :
55 | >
56 | > ***LogsManager.INCOMING_CALLS***: for getting the list (LogObject) of all the incoming calls.
57 | >
58 | > ***LogsManager.OUTGOING_CALLS***: for getting the list (LogObject) of all the incoming calls.
59 | >
60 | > ***LogsManager.MISSED_CALLS***: for getting the list (LogObject) of all the incoming calls.
61 | >
62 | > ***LogsManager.ALL_CALLS***: for getting the list (LogObject) of all the calls.
63 |
64 | - Getting call durations
65 |
66 | `logsManager.getIncomingDuration()`: returns the number of seconds for all the incoming calls made.
67 |
68 | `logsManager.getOutgoingDuration()`: returns the number of seconds for all the outgoing calls made.
69 |
70 | `logsManager.getTotalDuration()`: returns the number of seconds for all the calls made.
71 |
72 | `logsManager.getCoolDuration(type)`: returns a String in the form of "***x* hrs *xx* mins**" or "***xx* mins *xx* secs**"
73 |
74 | - Available duration types :
75 | >
76 | > ***LogsManager.INCOMING***: for getting duration for all the incoming calls.
77 | >
78 | > ***LogsManager.OUTGOING***: for getting duration for all the incoming calls.
79 | >
80 | > ***LogsManager.TOTAL***: for getting duration for all the calls.
81 |
82 | Using LogObjects
83 | --------------------
84 | - Some useful methods
85 |
86 | `logObject.getDuration()`: returns an `int` of the seconds used for that particular call.
87 |
88 | `logObject.getNumber()`: returns a `String` of the number associated with the call made.
89 |
90 | `logObject.getContactName()`: returns a `String` of the contact name for the number in the log, if not found, it returns the number.
91 |
92 | `logObject.getType()`: returns an `int` for the type of the call log.
93 |
94 | `logObject.getCoolDuration()`: returns a `String` in the form of "***x* hrs *xx* mins**" or "***xx* mins *xx* secs**" based on the duration.
95 |
96 | Examples
97 | --------
98 | - Retriving a list of all call logs:
99 |
100 | ```java
101 | ListView logList = (ListView) findViewById(R.id.LogsList);
102 | LogsManager logsManager = new LogsManager(this);
103 | List callLogs = logsManager.getLogs(LogsManager.ALL_CALLS);
104 | LogsAdapter logsAdapter = new LogsAdapter(this, R.layout.log_layout, callLogs);
105 | logList.setAdapter(logsAdapter);
106 | ```
107 |
108 |
109 | be sure to check out the [sample](https://github.com/wickerlabs/CallLogs/tree/master/SampleApp) app in the repository.
110 |
111 | Acknowledgements
112 | ----------------
113 | > Icons made by [madebyoliver](http://www.flaticon.com/authors/madebyoliver) from [www.flaticon.com](http://www.flaticon.com)
114 |
--------------------------------------------------------------------------------
/SampleApp/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/SampleApp/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "24.0.2"
6 | defaultConfig {
7 | applicationId 'com.wickerlabs.logmanager'
8 | minSdkVersion 10
9 | targetSdkVersion 23
10 | versionCode 2
11 | versionName "1.0"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | productFlavors {
20 | }
21 | }
22 |
23 | dependencies {
24 | compile fileTree(include: ['*.jar'], dir: 'libs')
25 | testCompile 'junit:junit:4.12'
26 | compile 'com.android.support:appcompat-v7:23.4.0'
27 | //compile project(':logmanager')
28 | compile 'com.github.wickerlabs:CallLogs:1+@aar'
29 | }
30 |
--------------------------------------------------------------------------------
/SampleApp/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\Wickerman\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/SampleApp/src/androidTest/java/com/wickerlabs/calls/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | /**************************************************************************************************
2 | * Copyright (C) 2016 WickerLabs. inc - All Rights Reserved. *
3 | * *
4 | * NOTICE: All information contained herein is, and remains the property of WickerLabs, *
5 | * The intellectual and technical concepts contained herein are proprietary to WickerLabs. *
6 | * Dissemination of this information or reproduction of this material *
7 | * is strictly forbidden unless prior permission is obtained from WickerLabs. inc *
8 | * *
9 | **************************************************************************************************/
10 | package com.wickerlabs.calls;
11 |
12 | import android.app.Application;
13 | import android.test.ApplicationTestCase;
14 |
15 | /**
16 | * Testing Fundamentals
17 | */
18 | public class ApplicationTest extends ApplicationTestCase {
19 | public ApplicationTest() {
20 | super(Application.class);
21 | }
22 | }
--------------------------------------------------------------------------------
/SampleApp/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/SampleApp/src/main/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wickerlabs/calllogs/393c56574d43da3623a9691ac71ae4e750352fce/SampleApp/src/main/ic_launcher-web.png
--------------------------------------------------------------------------------
/SampleApp/src/main/java/com/wickerlabs/calls/Adapter/LogsAdapter.java:
--------------------------------------------------------------------------------
1 | package com.wickerlabs.calls.Adapter;
2 |
3 | import android.Manifest;
4 | import android.annotation.SuppressLint;
5 | import android.content.Context;
6 | import android.support.annotation.RequiresPermission;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.ArrayAdapter;
11 | import android.widget.ImageView;
12 | import android.widget.TextView;
13 |
14 | import com.wickerlabs.calls.R;
15 | import com.wickerlabs.logmanager.LogObject;
16 | import com.wickerlabs.logmanager.LogsManager;
17 |
18 | import java.text.DateFormat;
19 | import java.util.Date;
20 | import java.util.List;
21 |
22 | public class LogsAdapter extends ArrayAdapter {
23 |
24 | List logs;
25 | Context context;
26 | int resource;
27 |
28 | public LogsAdapter(Context context, int resource, List callLogs) {
29 | super(context, resource, callLogs);
30 | this.logs = callLogs;
31 | this.context = context;
32 | this.resource = resource;
33 |
34 | }
35 |
36 | @Override
37 | public Context getContext() {
38 | return context;
39 | }
40 |
41 | @Override
42 | public int getCount() {
43 | return logs.size();
44 | }
45 |
46 | @Override
47 | public LogObject getItem(int position) {
48 | return logs.get(position);
49 | }
50 |
51 | @Override
52 | @SuppressLint("ViewHolder")
53 | @RequiresPermission(Manifest.permission.READ_CONTACTS)
54 | public View getView(int position, View convertView, ViewGroup parent) {
55 | View row = LayoutInflater.from(getContext()).inflate(resource, parent, false);
56 |
57 | TextView phone = (TextView) row.findViewById(R.id.phoneNum);
58 | TextView duration = (TextView) row.findViewById(R.id.callDuration);
59 | TextView date = (TextView) row.findViewById(R.id.callDate);
60 | ImageView imageView = (ImageView) row.findViewById(R.id.callImage);
61 |
62 | LogObject log = getItem(position);
63 | Date date1 = new Date(log.getDate());
64 |
65 | DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.ERA_FIELD, DateFormat.SHORT);
66 | phone.setText(log.getContactName());
67 | duration.setText(log.getCoolDuration());
68 | date.setText(dateFormat.format(date1));
69 |
70 | switch (log.getType()) {
71 |
72 | case LogsManager.INCOMING:
73 | imageView.setImageResource(R.drawable.received);
74 | break;
75 | case LogsManager.OUTGOING:
76 | imageView.setImageResource(R.drawable.sent);
77 | break;
78 | case LogsManager.MISSED:
79 | imageView.setImageResource(R.drawable.missed);
80 | break;
81 | default:
82 | imageView.setImageResource(R.drawable.cancelled);
83 | break;
84 |
85 | }
86 |
87 |
88 | return row;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/SampleApp/src/main/java/com/wickerlabs/calls/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.wickerlabs.calls;
2 |
3 | import android.Manifest;
4 | import android.annotation.TargetApi;
5 | import android.content.DialogInterface;
6 | import android.content.pm.PackageManager;
7 | import android.os.Build;
8 | import android.os.Bundle;
9 | import android.support.annotation.NonNull;
10 | import android.support.v4.content.ContextCompat;
11 | import android.support.v4.content.PermissionChecker;
12 | import android.support.v7.app.AlertDialog;
13 | import android.support.v7.app.AppCompatActivity;
14 | import android.widget.ListView;
15 |
16 | import com.wickerlabs.calls.Adapter.LogsAdapter;
17 | import com.wickerlabs.logmanager.LogObject;
18 | import com.wickerlabs.logmanager.LogsManager;
19 |
20 | import java.util.List;
21 |
22 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
23 | public class MainActivity extends AppCompatActivity {
24 |
25 | private static final int READ_LOGS = 725;
26 | private ListView logList;
27 | private Runnable logsRunnable;
28 | private String[] requiredPermissions = {Manifest.permission.READ_CALL_LOG, Manifest.permission.READ_CONTACTS};
29 |
30 | @Override
31 | protected void onCreate(Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 | setContentView(R.layout.activity_main);
34 |
35 | logList = (ListView) findViewById(R.id.LogsList);
36 |
37 | logsRunnable = new Runnable() {
38 | @Override
39 | public void run() {
40 | loadLogs();
41 | }
42 | };
43 |
44 | // Checking for permissions
45 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
46 | checkPermissionToExecute(requiredPermissions, READ_LOGS, logsRunnable);
47 | } else {
48 | logsRunnable.run();
49 | }
50 |
51 | }
52 |
53 | // This is to be run only when READ_CONTACTS and READ_CALL_LOG permission are granted
54 | private void loadLogs() {
55 | LogsManager logsManager = new LogsManager(this);
56 | List callLogs = logsManager.getLogs(LogsManager.ALL_CALLS);
57 |
58 | LogsAdapter logsAdapter = new LogsAdapter(this, R.layout.log_layout, callLogs);
59 | logList.setAdapter(logsAdapter);
60 | }
61 |
62 | // A method to check if a permission is granted then execute tasks depending on that particular permission
63 | @TargetApi(Build.VERSION_CODES.M)
64 | private void checkPermissionToExecute(String permissions[], int requestCode, Runnable runnable) {
65 |
66 | boolean logs = ContextCompat.checkSelfPermission(this, permissions[0]) != PackageManager.PERMISSION_GRANTED;
67 | boolean contacts = ContextCompat.checkSelfPermission(this, permissions[1]) != PackageManager.PERMISSION_GRANTED;
68 |
69 | if (logs || contacts) {
70 | requestPermissions(permissions, requestCode);
71 | } else {
72 | runnable.run();
73 | }
74 | }
75 |
76 | @Override
77 | @TargetApi(Build.VERSION_CODES.M)
78 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
79 | super.onRequestPermissionsResult(requestCode, permissions, grantResults);
80 |
81 | if (requestCode == READ_LOGS && permissions[0].equals(Manifest.permission.READ_CALL_LOG) && permissions[1].equals(Manifest.permission.READ_CONTACTS)) {
82 | if (grantResults[0] == PermissionChecker.PERMISSION_GRANTED && grantResults[1] == PermissionChecker.PERMISSION_GRANTED) {
83 | logsRunnable.run();
84 | } else {
85 | new AlertDialog.Builder(MainActivity.this)
86 | .setMessage("The app needs these permissions to work, Exit?")
87 | .setTitle("Permission Denied")
88 | .setCancelable(false)
89 | .setPositiveButton("Retry", new DialogInterface.OnClickListener() {
90 | @Override
91 | public void onClick(DialogInterface dialog, int which) {
92 | dialog.dismiss();
93 | checkPermissionToExecute(requiredPermissions, READ_LOGS, logsRunnable);
94 | }
95 | })
96 | .setNegativeButton("Exit App", new DialogInterface.OnClickListener() {
97 | @Override
98 | public void onClick(DialogInterface dialog, int which) {
99 | dialog.dismiss();
100 | finish();
101 | }
102 | }).show();
103 | }
104 | }
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/SampleApp/src/main/res/drawable/cancelled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wickerlabs/calllogs/393c56574d43da3623a9691ac71ae4e750352fce/SampleApp/src/main/res/drawable/cancelled.png
--------------------------------------------------------------------------------
/SampleApp/src/main/res/drawable/missed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wickerlabs/calllogs/393c56574d43da3623a9691ac71ae4e750352fce/SampleApp/src/main/res/drawable/missed.png
--------------------------------------------------------------------------------
/SampleApp/src/main/res/drawable/received.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wickerlabs/calllogs/393c56574d43da3623a9691ac71ae4e750352fce/SampleApp/src/main/res/drawable/received.png
--------------------------------------------------------------------------------
/SampleApp/src/main/res/drawable/sent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wickerlabs/calllogs/393c56574d43da3623a9691ac71ae4e750352fce/SampleApp/src/main/res/drawable/sent.png
--------------------------------------------------------------------------------
/SampleApp/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
15 |
16 |
--------------------------------------------------------------------------------
/SampleApp/src/main/res/layout/log_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
21 |
22 |
30 |
31 |
40 |
41 |
51 |
--------------------------------------------------------------------------------
/SampleApp/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wickerlabs/calllogs/393c56574d43da3623a9691ac71ae4e750352fce/SampleApp/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SampleApp/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wickerlabs/calllogs/393c56574d43da3623a9691ac71ae4e750352fce/SampleApp/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SampleApp/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wickerlabs/calllogs/393c56574d43da3623a9691ac71ae4e750352fce/SampleApp/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SampleApp/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wickerlabs/calllogs/393c56574d43da3623a9691ac71ae4e750352fce/SampleApp/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SampleApp/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wickerlabs/calllogs/393c56574d43da3623a9691ac71ae4e750352fce/SampleApp/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SampleApp/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
14 | 64dp
15 |
16 |
--------------------------------------------------------------------------------
/SampleApp/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #4caf50
4 | #388e3c
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/SampleApp/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 | 16dp
13 | 16dp
14 |
15 |
--------------------------------------------------------------------------------
/SampleApp/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Call logs
3 |
4 |
--------------------------------------------------------------------------------
/SampleApp/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/SampleApp/src/test/java/com/wickerlabs/calls/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | /**************************************************************************************************
2 | * Copyright (C) 2016 WickerLabs. inc - All Rights Reserved. *
3 | * *
4 | * NOTICE: All information contained herein is, and remains the property of WickerLabs, *
5 | * The intellectual and technical concepts contained herein are proprietary to WickerLabs. *
6 | * Dissemination of this information or reproduction of this material *
7 | * is strictly forbidden unless prior permission is obtained from WickerLabs. inc *
8 | * *
9 | **************************************************************************************************/
10 | package com.wickerlabs.calls;
11 |
12 | import org.junit.Test;
13 |
14 | import static org.junit.Assert.assertEquals;
15 |
16 | /**
17 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
18 | */
19 | public class ExampleUnitTest {
20 | @Test
21 | public void addition_isCorrect() throws Exception {
22 | assertEquals(4, 2 + 2);
23 | }
24 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:2.1.3'
10 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1'
11 |
12 | // NOTE: Do not place your application dependencies here; they belong
13 | // in the individual module build.gradle files
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | jcenter()
20 | maven { url "https://jitpack.io" }
21 | }
22 | }
23 |
24 | task clean(type: Delete) {
25 | delete rootProject.buildDir
26 | }
27 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | #org.gradle.java.home=C:\\Program Files\\Java\\jdk1.8.0_25
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wickerlabs/calllogs/393c56574d43da3623a9691ac71ae4e750352fce/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Oct 16 14:09:04 EAT 2016
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn ( ) {
37 | echo "$*"
38 | }
39 |
40 | die ( ) {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/logmanager/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/logmanager/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 |
4 | group = 'com.github.wickerlabs'
5 |
6 | android {
7 | signingConfigs {
8 | }
9 | compileSdkVersion 23
10 | buildToolsVersion "24.0.2"
11 | defaultConfig {
12 | minSdkVersion 10
13 | targetSdkVersion 22
14 | }
15 | productFlavors {
16 | }
17 | }
18 |
19 | dependencies {
20 | compile fileTree(include: ['*.jar'], dir: 'libs')
21 | testCompile 'junit:junit:4.12'
22 | compile 'com.android.support:appcompat-v7:23.4.0'
23 | }
24 |
25 |
26 |
--------------------------------------------------------------------------------
/logmanager/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:\Users\Wickerman\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/logmanager/src/androidTest/java/com/wickerlabs/logmanager/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.wickerlabs.logmanager;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/logmanager/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/logmanager/src/main/java/com/wickerlabs/logmanager/LogObject.java:
--------------------------------------------------------------------------------
1 | package com.wickerlabs.logmanager;
2 |
3 | import android.content.ContentResolver;
4 | import android.content.Context;
5 | import android.database.Cursor;
6 | import android.net.Uri;
7 | import android.provider.ContactsContract;
8 |
9 | import com.wickerlabs.logmanager.interfaces.CallLogObject;
10 |
11 | import java.text.DecimalFormat;
12 |
13 | public class LogObject implements CallLogObject {
14 | private String number;
15 | private long date;
16 | private int duration, type;
17 | private Context context;
18 |
19 | public LogObject() {
20 | }
21 |
22 | public LogObject(Context context) {
23 | this.context = context;
24 | }
25 |
26 | public String getNumber() {
27 | return number;
28 | }
29 |
30 | public void setNumber(String number) {
31 | this.number = number;
32 | }
33 |
34 | public int getType() {
35 | return type;
36 | }
37 |
38 | public void setType(int type) {
39 | this.type = type;
40 | }
41 |
42 | public long getDate() {
43 | return date;
44 | }
45 |
46 | public void setDate(long date) {
47 | this.date = date;
48 | }
49 |
50 | public int getDuration() {
51 | return duration;
52 | }
53 |
54 | public void setDuration(int duration) {
55 | this.duration = duration;
56 | }
57 |
58 | public String getCoolDuration() {
59 | return getCoolDuration(getDuration());
60 | }
61 |
62 | public String getContactName(){
63 | if(getNumber() != null){
64 | return findNameByNumber(getNumber());
65 | } else {
66 | return null;
67 | }
68 | }
69 |
70 | private String findNameByNumber(final String phoneNumber) {
71 | ContentResolver cr = context.getContentResolver();
72 |
73 | Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
74 |
75 | Cursor cursor = cr.query(uri, new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME},null, new String[]{ContactsContract.PhoneLookup.DISPLAY_NAME}, null);
76 | if (cursor == null) {
77 | return null;
78 | }
79 |
80 | String contactName = null;
81 |
82 | if(cursor.moveToFirst()) {
83 | contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME));
84 | }
85 |
86 | if(!cursor.isClosed()) {
87 | cursor.close();
88 | }
89 |
90 | return (contactName == null) ? phoneNumber : contactName;
91 | }
92 |
93 | private String getCoolDuration(float sum) {
94 |
95 | String duration = "";
96 | String result;
97 |
98 | if (sum >= 0 && sum < 3600) {
99 |
100 | result = String.valueOf(sum / 60);
101 | String decimal = result.substring(0, result.lastIndexOf("."));
102 | String point = "0" + result.substring(result.lastIndexOf("."));
103 |
104 | int minutes = Integer.parseInt(decimal);
105 | float seconds = Float.parseFloat(point) * 60;
106 |
107 | DecimalFormat formatter = new DecimalFormat("#");
108 | duration = minutes + " min " + formatter.format(seconds) + " secs";
109 |
110 | } else if (sum >= 3600) {
111 |
112 | result = String.valueOf(sum / 3600);
113 | String decimal = result.substring(0, result.lastIndexOf("."));
114 | String point = "0" + result.substring(result.lastIndexOf("."));
115 |
116 | int hours = Integer.parseInt(decimal);
117 | float minutes = Float.parseFloat(point) * 60;
118 |
119 | DecimalFormat formatter = new DecimalFormat("#");
120 | duration = hours + " hrs " + formatter.format(minutes) + " min";
121 |
122 | }
123 |
124 | return duration;
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/logmanager/src/main/java/com/wickerlabs/logmanager/LogsManager.java:
--------------------------------------------------------------------------------
1 | package com.wickerlabs.logmanager;
2 |
3 | import android.content.Context;
4 | import android.database.Cursor;
5 | import android.provider.CallLog;
6 |
7 | import java.text.DecimalFormat;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | public class LogsManager {
12 |
13 | public static final int INCOMING = CallLog.Calls.INCOMING_TYPE;
14 | public static final int OUTGOING = CallLog.Calls.OUTGOING_TYPE;
15 | public static final int MISSED = CallLog.Calls.MISSED_TYPE;
16 | public static final int TOTAL = 579;
17 |
18 | public static final int INCOMING_CALLS = 672;
19 | public static final int OUTGOING_CALLS = 609;
20 | public static final int MISSED_CALLS = 874;
21 | public static final int ALL_CALLS = 814;
22 | private static final int READ_CALL_LOG = 47;
23 | private Context context;
24 |
25 |
26 | public LogsManager(Context context) {
27 | this.context = context;
28 | }
29 |
30 | public int getOutgoingDuration() {
31 | int sum = 0;
32 |
33 | Cursor cursor = context.getContentResolver().query(CallLog.Calls.CONTENT_URI, null,
34 | CallLog.Calls.TYPE + " = " + CallLog.Calls.OUTGOING_TYPE, null, null);
35 |
36 | int duration = cursor.getColumnIndex(CallLog.Calls.DURATION);
37 |
38 | while (cursor.moveToNext()) {
39 | String callDuration = cursor.getString(duration);
40 | sum += Integer.parseInt(callDuration);
41 | }
42 |
43 | cursor.close();
44 |
45 | return sum;
46 | }
47 |
48 | public int getIncomingDuration() {
49 | int sum = 0;
50 |
51 | Cursor cursor = context.getContentResolver().query(CallLog.Calls.CONTENT_URI, null,
52 | CallLog.Calls.TYPE + " = " + CallLog.Calls.INCOMING_TYPE, null, null);
53 |
54 | int duration = cursor.getColumnIndex(CallLog.Calls.DURATION);
55 |
56 | while (cursor.moveToNext()) {
57 | String callDuration = cursor.getString(duration);
58 | sum += Integer.parseInt(callDuration);
59 | }
60 |
61 | cursor.close();
62 |
63 | return sum;
64 | }
65 |
66 | public int getTotalDuration() {
67 | int sum = 0;
68 |
69 | Cursor cursor = context.getContentResolver().query(CallLog.Calls.CONTENT_URI, null, null, null, null);
70 |
71 | int duration = cursor.getColumnIndex(CallLog.Calls.DURATION);
72 |
73 | while (cursor.moveToNext()) {
74 | String callDuration = cursor.getString(duration);
75 | sum += Integer.parseInt(callDuration);
76 | }
77 |
78 | cursor.close();
79 |
80 | return sum;
81 | }
82 |
83 | public String getCoolDuration(int type) {
84 | float sum;
85 |
86 | switch (type) {
87 | case INCOMING:
88 | sum = getIncomingDuration();
89 | break;
90 | case OUTGOING:
91 | sum = getOutgoingDuration();
92 | break;
93 | case TOTAL:
94 | sum = getTotalDuration();
95 | break;
96 | default:
97 | sum = 0;
98 | }
99 |
100 | String duration = "";
101 | String result;
102 |
103 | if (sum >= 0 && sum < 3600) {
104 |
105 | result = String.valueOf(sum / 60);
106 | String decimal = result.substring(0, result.lastIndexOf("."));
107 | String point = "0" + result.substring(result.lastIndexOf("."));
108 |
109 | int minutes = Integer.parseInt(decimal);
110 | float seconds = Float.parseFloat(point) * 60;
111 |
112 | DecimalFormat formatter = new DecimalFormat("#");
113 | duration = minutes + " min " + formatter.format(seconds) + " secs";
114 |
115 | } else if (sum >= 3600) {
116 |
117 | result = String.valueOf(sum / 3600);
118 | String decimal = result.substring(0, result.lastIndexOf("."));
119 | String point = "0" + result.substring(result.lastIndexOf("."));
120 |
121 | int hours = Integer.parseInt(decimal);
122 | float minutes = Float.parseFloat(point) * 60;
123 |
124 | DecimalFormat formatter = new DecimalFormat("#");
125 | duration = hours + " hrs " + formatter.format(minutes) + " min";
126 |
127 | }
128 |
129 | return duration;
130 | }
131 |
132 | public List getLogs(int callType) {
133 | List logs = new ArrayList<>();
134 |
135 | String selection;
136 |
137 | switch (callType) {
138 | case INCOMING_CALLS:
139 | selection = CallLog.Calls.TYPE + " = " + CallLog.Calls.INCOMING_TYPE;
140 | break;
141 | case OUTGOING_CALLS:
142 | selection = CallLog.Calls.TYPE + " = " + CallLog.Calls.OUTGOING_TYPE;
143 | break;
144 | case MISSED_CALLS:
145 | selection = CallLog.Calls.TYPE + " = " + CallLog.Calls.MISSED_TYPE;
146 | break;
147 | case ALL_CALLS:
148 | selection = null;
149 | default:
150 | selection = null;
151 | }
152 |
153 | Cursor cursor = context.getContentResolver().query(CallLog.Calls.CONTENT_URI, null, selection, null, null);
154 | int number = cursor.getColumnIndex(CallLog.Calls.NUMBER);
155 | int type = cursor.getColumnIndex(CallLog.Calls.TYPE);
156 | int date = cursor.getColumnIndex(CallLog.Calls.DATE);
157 | int duration = cursor.getColumnIndex(CallLog.Calls.DURATION);
158 |
159 | while (cursor.moveToNext()) {
160 | LogObject log = new LogObject(context);
161 |
162 | log.setNumber(cursor.getString(number));
163 | log.setType(cursor.getInt(type));
164 | log.setDuration(cursor.getInt(duration));
165 | log.setDate(cursor.getLong(date));
166 |
167 | logs.add(log);
168 | }
169 |
170 | cursor.close();
171 |
172 |
173 | return logs;
174 | }
175 |
176 | }
177 |
--------------------------------------------------------------------------------
/logmanager/src/main/java/com/wickerlabs/logmanager/interfaces/CallLogObject.java:
--------------------------------------------------------------------------------
1 | /**************************************************************************************************
2 | * Copyright (C) 2016 WickerLabs. inc - All Rights Reserved. *
3 | * *
4 | * NOTICE: All information contained herein is, and remains the property of WickerLabs, *
5 | * The intellectual and technical concepts contained herein are proprietary to WickerLabs. *
6 | * Dissemination of this information or reproduction of this material *
7 | * is strictly forbidden unless prior permission is obtained from WickerLabs. inc *
8 | * *
9 | **************************************************************************************************/
10 | package com.wickerlabs.logmanager.interfaces;
11 |
12 | /**
13 | * Created by: WickerLabs.Inc
14 | * Project title: CallLogs
15 | * Time: 10:06 AM
16 | * Date: 1/27/2017
17 | * Website: http://www.wickerlabs.com
18 | */
19 |
20 | public interface CallLogObject {
21 |
22 | String getNumber();
23 |
24 | void setNumber(String number);
25 |
26 | int getType();
27 |
28 | void setType(int type);
29 |
30 | long getDate();
31 |
32 | void setDate(long date);
33 |
34 | int getDuration();
35 |
36 | void setDuration(int duration);
37 |
38 | String getCoolDuration();
39 |
40 | String getContactName();
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/logmanager/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Call Log Manager
3 |
4 |
--------------------------------------------------------------------------------
/logmanager/src/test/java/com/wickerlabs/logmanager/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.wickerlabs.logmanager;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.assertEquals;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':SampleApp', ':logmanager'
2 |
--------------------------------------------------------------------------------